Template resolution
We've been calling fluid.render("index.html") and extending
fluid_base.html without ever explaining where those names actually point. This
chapter pulls back the curtain — which matters, because the name you pass decides
which file wins.
Rendering, the short version
fluid.render(template, **ctx) does two things: it runs every registered context
processor (that's where the surface variables from the previous chapter come from) and then
renders the template through the async Jinja environment. The template argument
is a name, and that name is looked up against a stack of loaders.
Three sources, in order
When your app starts, the framework assembles the Jinja loader from three layers and searches them in this exact order:
- Additives — each enabled Additive contributes its templates under its own id namespace (more on that in the Additives chapters).
-
Your app — everything inside
fluid/templates. -
The framework — the bundled templates like
fluid_base.htmland the error pages.
Because your app sits before the framework, an unprefixed name resolves to your file first and falls through to the framework only if you don't have one. So the names map to disk like this:
render("index.html") -> fluid/templates/index.html (your app)
render("docs/intro.html") -> fluid/templates/docs/intro.html (your app)
render("fluid_base.html") -> bundled with the framework
render("errors/404.html") -> bundled with the framework
The path you pass is always relative to fluid/templates. Nest as deeply as you like: the documentation site you are reading right now renders pages with names such as docs/1.0.0a1/get-started.html, which is just a file at that path inside its fluid/templates.
Overriding framework templates
That ordering has a useful consequence: since your app is searched first, you can replace
any framework template by simply creating a file with the same name. Want your own 404 page
or your own base layout? Drop it into fluid/templates and it takes over —
no configuration needed:
{% extends "fluid_base.html" %}
{% block content %}
<h1>{{ _('Lost at sea') }}</h1>
{% endblock %}
Explicit namespaces
Sometimes you want to be unambiguous about which layer you mean. Each source also answers to a prefix, so you can skip the fall-through entirely:
-
app/…— force your app's templates, e.g.app/index.html. -
fluid/…— force the framework's templates, e.g.fluid/fluid_base.html. Handy when you have overridden a name locally but still want to extend the original. -
<additive_id>/…— an Additive's templates always live under its id.
This is why Additives never collide with your app: their files are only ever reachable
through their own id namespace. An Additive's own render() adds that prefix for
you automatically, so inside an Additive you keep writing plain names.
What the framework gives you
For reference, these are the templates you can always extend or override:
fluid_base.html— the default page layout.base_email.html— a starting point for HTML mails.errors/403.html,errors/404.html,errors/500.html— the default error pages (rendered automatically by the processing layer).
Keep this resolution order in mind when you name your pages. As long as your page lives under fluid/templates and doesn't shadow a framework name you rely on, you are free to structure the directory however suits your project.
Continue reading
From here you can continue straight with the Additives introduction.