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() renders pages/dashboard.html and 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.