Frontend

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:

  1. Additives — each enabled Additive contributes its templates under its own id namespace (more on that in the Additives chapters).
  2. Your app — everything inside fluid/templates.
  3. The framework — the bundled templates like fluid_base.html and 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:

resolution text
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:

fluid/templates/errors/404.html html
{% 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.