Your first template

A template is a directory. The directory name is the template name used in the URL (/templates/<name>/render). Only the body template is required; everything else is optional.

invoice/
  template.handlebars       # body — REQUIRED
  header.handlebars         # optional page header
  footer.handlebars         # optional page footer
  schema.json               # optional JSON Schema for request data
  params.json               # optional PDF print options
  examples/
    sample.json             # optional example datasets
  assets/
    styles.css              # optional static files, referenced as ./assets/...
    logo.svg
  partials/
    line-item.handlebars    # optional reusable fragments

The body template

The body file’s extension selects the engine: template.mustache, template.handlebars, template.tmpl (Go), or template.html (static). If several exist, the first in that priority order wins.

<!-- template.handlebars -->
<!doctype html>
<html>
  <head><link rel="stylesheet" href="assets/styles.css"></head>
  <body>
    <h1>Invoice {{number}}</h1>
    <p>Billed to: {{customer.name}}</p>
  </body>
</html>

The request JSON body becomes the template data: {"number": "A-1", "customer": {"name": "Alice"}}.

Schema (schema.json)

An optional JSON Schema. Request data is validated before rendering; invalid data returns 422 and never reaches the browser. The schema is also published at GET /templates/<name>/schema.json.

PDF options (params.json)

Optional PDF print parameters: page size, margins, orientation, background printing, scale, and which lifecycle event to wait for.

{ "pdf": { "landscape": false, "printBackground": true, "marginTop": 0.5 } }

Optional header.<ext> and footer.<ext> files render the running page header and footer. They use the same engines as the body but do not have access to assets. See Headers & footers.

Examples (examples/*.json)

Each JSON file is a named example dataset. It powers GET /templates/<name>/examples/<example> (renders a PDF), GET /templates/<name>/examples-data (returns the data), the tester UI, and the validate CI check. Commit at least one — it is your fixture and your docs.

Assets and partials

assets/ holds static files referenced from the body as ./assets/<path> (served to the browser at render time). partials/ holds reusable fragments for Handlebars, Go, and Mustache templates. See Assets and Partials.

Next