Template extensions
Add integrations or change markup while keeping the upgrade surface small.
Reach for a template only when configuration and CSS cannot express the change. Zola loads a site template before a theme template with the same path, so the site can extend a block or replace one partial without editing the installed DevLab copy.
Choose the maintenance boundary
| The site needs... | Use... | What the site owns |
|---|---|---|
| Metadata, CSS, JavaScript or an integration | A base-template hook | Only the added markup |
| Different content inside the built-in footer | partials/footer-content.html | Footer content, not its layout |
| A completely different shared component | One matching partial | That component and its behavior |
| A different structure for one page type | One layout block | That block's markup |
Prefer extension over copying
Extend the namespaced DevLab template and override one block. A complete copied template may build successfully while silently missing accessibility or navigation improvements from a later release.
Extend the base template
Create templates/base.html in the site. Keep only the blocks the project actually uses:
{% extends "devlab-theme/templates/base.html" %}
{% block head_extra %}
<meta name="application-name" content="Acme Docs">
{% endblock head_extra %}
{% block extra_styles %}
<link rel="stylesheet" href="{{ get_url(path='custom.css') }}">
{% endblock extra_styles %}
{% block extra_scripts %}
<script src="{{ get_url(path='js/custom.js') }}"></script>
{% endblock extra_scripts %}
Put referenced files under the site's static/ directory. get_url keeps their URLs correct when the site is deployed below a path prefix.
The base template exposes these focused hooks:
| Block | Position | Good fit |
|---|---|---|
head_extra | After DevLab metadata and main.css | Verification tags, metadata and preload hints |
extra_styles | Last in the page head | Site stylesheets |
body_start | After the skip link, before the site shell | Environment banners and accessibility integrations |
extra_scripts | After DevLab scripts | Site JavaScript that uses rendered theme markup |
body_end | Last before </body> | Integrations that must be the final body markup |
The structural title, main_class and content blocks belong to page layouts. Override them in a specific layout instead of changing the site-wide base wrapper.
Override one partial
A site partial replaces the theme partial at the same relative path:
your-site/
└── templates/
└── partials/
└── footer-content.html
footer-content.html is the smallest useful footer override. DevLab continues to own the separator, centered layout and compact Docs variant while the site controls the inner markup. The partial receives:
footer_textandfooter_year;footer_note;footer_linksandfooter_links_label;footer_compactfor the Docs presentation.
Reuse site-footer-note, site-footer-copyright, site-footer-links, site-footer-link and site-footer-link-icon when you want to keep the built-in responsive styling.
You can also replace partials/header.html or partials/footer.html, but that is a complete component replacement. The site then owns its keyboard behavior, accessible names, responsive states and every runtime hook the component needs. A full footer override must handle footer_compact, because the same partial appears below regular pages, in the desktop Docs sidebar and in the mobile Docs panel.
Header and navigation overrides must retain the data-* hooks used by site-menu.js, search.js and theme.js, or deliberately provide equivalent behavior. DevLab's CSS classes and JavaScript DOM hooks are implementation details in v0.8.0, not a stable extension API.
Override one layout block
Suppose ordinary content pages need a project-specific header but should keep every other DevLab block. Create templates/page.html:
{% extends "devlab-theme/templates/page.html" %}
{% block content %}
<article class="content custom-page">
<header class="page-header">
<p class="hero-eyebrow">Acme</p>
<h1>{{ page.title }}</h1>
</header>
{{ page.content | safe }}
</article>
{% endblock content %}
The same pattern works with index.html, section.html, docs.html, doc-page.html, blog.html, blog-page.html and downloads.html. Extending the namespaced file keeps every untouched block connected to the installed theme.
Zola documents namespaced inheritance and site-template priority in Customizing a theme.
Validate the override
Run the native checks after every template change:
zola check
zola build
Then review only the surfaces the override can affect:
- desktop and mobile widths;
- light and dark modes;
- keyboard focus and accessible names;
- the mobile menu when header or navigation markup changed;
- compact Docs presentation when footer markup changed;
- stored Docs groups, search results and active navigation when their hooks changed.
Upgrade without surprises
Before selecting a new DevLab tag, list the site's template overrides. For each one, compare the matching file or parent block in the new release. A valid build proves that Tera can render the page; it does not prove that a copied component includes newly added accessible markup or runtime hooks.
After the comparison, run the checks again and repeat the focused manual review. If an override has grown difficult to compare, move any styling back to CSS and any behavior back to configuration, then keep only the structural markup that still requires a template.