Partial Templates¶
Partial templates let you define reusable UI chunks once and render them anywhere. This is especially powerful with HTMX, Turbo, or any AJAX-style partial response pattern.
Table of Contents¶
Defining Partials¶
Use {% partialdef %} to define a named partial inside any template:
<!-- views/home.html -->
{% partialdef card %}
<div class="card">
<h3>{{ title|default:"Untitled" }}</h3>
<p>{{ body|truncatewords:30 }}</p>
{% if featured %}<em>Featured</em>{% endif %}
</div>
{% endpartialdef %}
{% for entry in entries %}
{% partial card with title=entry.title body=entry.body featured=entry.featured %}
{% endfor %}
Inline Partials¶
A {% partialdef %} block renders its body inline where it is defined and registers itself for later use:
This means you get immediate output and a reusable partial in one declaration.
Use the inline option explicitly:
{% partialdef greeting inline %}
Hello {{ name }}!
{% endpartialdef %}
<!-- Above line ALSO outputs "Hello World!" when rendered -->
Rendering Partials by Name¶
Once defined, you can render a partial by name from your routes using the view#partial syntax:
The syntax is viewName#partialName. The engine resolves the file, extracts the named partial, and renders only that block.
Real-world HTMX example:
<!-- views/products.html -->
{% partialdef product_card %}
<div class="product-card" id="product-{{ product.id }}">
<img src="{{ product.image|static }}" alt="{{ product.name }}">
<h3>{{ product.name|capfirst }}</h3>
<p class="price">${{ product.price|floatformat:2 }}</p>
<button hx-post="/cart/add/{{ product.id }}" hx-swap="outerHTML">
Add to Cart
</button>
</div>
{% endpartialdef %}
{% for product in products %}
{% partial product_card with product=product %}
{% endfor %}
// The entire page renders all cards
app.get('/shop', (req, res) =>
res.render('products', { products: catalog })
);
// HTMX swaps just one card after an action
app.post('/cart/add/:id', (req, res) =>
res.render('products#product_card', {
product: catalog.find(p => p.id == req.params.id)
})
);
Nested Partials¶
Partials can call other partials:
{% partialdef header %}
<div class="card-header">
<h3>{{ title }}</h3>
</div>
{% endpartialdef %}
{% partialdef card %}
<div class="card">
{% partial header with title=title %}
<p>{{ body }}</p>
</div>
{% endpartialdef %}
Partials with Context¶
By default, partials inherit the parent context. Use with to pass explicit values:
You can also pass context variables:
Partials with Include¶
You can include a partial from another template file using the #partialName syntax:
This loads header.html, registers all its partials, and renders only the named one.
Real-world navigation include:
<!-- views/nav.html -->
{% partialdef navigation %}
<nav>
{% for link in links %}
<a href="{{ link.url }}" class="{% if link.active %}current{% endif %}">{{ link.label }}</a>
{% endfor %}
</nav>
{% endpartialdef %}
Rendering Partials Programmatically¶
renderPartialFromSource¶
Render a named partial from a template source string:
renderPartialFromFile¶
Render a named partial from a template file:
compiled.renderPartial¶
Render a partial from a compiled template:
compiled.renderBlock¶
Render a single block from a compiled template — useful for AJAX responses:
Express Partial Rendering¶
res.render with #partial¶
When using setupExpress(), you can render partials directly:
res.renderPartial middleware¶
If you don't want to patch res.render, add the partial renderer middleware instead:
Partial API Reference¶
renderPartialFromSource(fileContent, partialName, contextObj, options, filePath?)¶
Render a named partial from a template source string.
| Parameter | Type | Description |
|-----------|------|-------------|
| fileContent | string | Template source string |
| partialName | string | Name of the partial to render |
| contextObj | object | Variables to inject |
| options | object | Options |
| filePath | string? | Optional file path for error messages |
renderPartialFromFile(fileName, partialName, contextObj, options)¶
Render a named partial from a template file.
| Parameter | Type | Description |
|-----------|------|-------------|
| fileName | string | Template file name (without extension) |
| partialName | string | Name of the partial to render |
| contextObj | object | Variables to inject |
| options | object | Options including views directories |
Common Pitfalls¶
| Issue | Symptom | Fix |
|-------|---------|-----|
| Missing partial name | {% partial %} renders nothing | Ensure the name matches a defined partialdef. |
| Variable not found | Appears empty | Variables are resolved in the current context; use with to pass explicit values. |
| Inline vs non-inline confusion | Duplicate output | Use inline only when you want immediate rendering at the declaration site. |
| Partial leaks across includes | Unexpected partials available | include "file#partial" isolates partials; include "file" (full) makes all partials available. |