6.6 Rendering HTML with the template service

The template service is the other side of "data in, result out": instead of running a stored query and returning rows, it runs a stored JSX template and returns HTML. Use it for server-rendered pages, email bodies, and reusable HTML fragments.

It requires a node built with the JavaScript engine.

Mounting and authoring

{ "path": "/render", "service": "template", "config": {
    "access": { "read": "all", "write": "A", "invoke": "all" }
} }

Templates are authored like files under /.templates/, just as queries live under /.queries/. Every other path, on any verb, renders the longest-prefix-matched template. A .root template covers the mount root and otherwise-unmatched paths.

The stored envelope contains a compiled single-file module, not raw JSX:

{ "source": "<compiled ESM>",
  "contentType": "text/html; charset=utf-8" }

You normally create that envelope with the CLI:

// welcome.jsx
export default function Welcome(props) {
  return <main><h1>Hello, {props.name ?? "world"}!</h1></main>;
}
npm install preact preact-render-to-string
rs2 template build welcome.jsx
rs2 send /render/.templates/welcome --file welcome.template.json `
  --content-type application/json

template build uses esbuild and Preact to transpile and bundle the component. A JS-enabled CLI also compile-checks the result. The server validates the envelope when you store it; an exception thrown during rendering appears on the first render request.

How props are assembled

The template receives one props object. Later sources win:

  1. URL segments after the matched template become positional keys ("0", "1", …).
  2. Non-$ query-string parameters add named values.
  3. A JSON object request body adds or replaces named values.

For example, GET /render/welcome?name=Ada renders the welcome template with {name: "Ada"}. A pipeline can fetch a record and POST it to the template mount to render stored data.

Templates are intentionally pure: they receive no file, data, or outbound HTTP capabilities. Compose those operations in a pipeline before rendering. Compiled templates are cached by content version in a resident isolate, and a PUT of new bytes swaps the render on the next request.

The discovery surface advertises .templates as the mount's specSubtree and describes JSX/Preact authoring, so a generic editor can offer the correct build step without special-casing the service name.


Previous: 6.5 Param schemas · Manual home · Next: Part 7 — 7.1 The pipeline service →