Rendering Views
@streetjs/plugin-htmx ships a tiny, dependency-free view engine (consistent with
StreetJS’s minimal-dependency philosophy). No Handlebars/Nunjucks/Eta runtime dep.
Template syntax
- `` — HTML-escaped interpolation (XSS-safe by default)
}— raw, unescaped interpolation- `` — include a partial from
partials/ - Dotted paths: ``
Loops and conditionals are intentionally omitted — compose lists by rendering partials in your controller (see Partials & Fragments).
Layouts
A layout is any template with a } placeholder:
1
2
3
4
5
<!-- src/views/layouts/main.html -->
<!doctype html>
<html><head><title></title>
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
</head><body><main>}</main></body></html>
Pages and ctx.htmx.view
1
2
3
4
@Get('/dashboard')
async dashboard(ctx: StreetContext) {
ctx.htmx.view('dashboard', { title: 'Dashboard', user });
}
- On a normal navigation,
view()renderspages/dashboard.htmland wraps it in the configured layout → a full HTML document. - On an HTMX request (
HX-Request: true),view()returns just the page fragment (no layout) so HTMX can swap it in.
Override the layout per call: ctx.htmx.view('page', data) uses the default;
pass options through the engine for advanced cases.
The engine directly
For manual rendering (e.g. composing fragments), use ctx.htmx.engine:
1
2
const rows = items.map((it) => ctx.htmx.engine.partial('row', it)).join('');
ctx.htmx.view('list', { rows }); // } in the page
Next: Partials & Fragments.