Skip to main content
When do you need templates? Most developers don’t. If you’re using the npm package, just write JSX and call renderDocument() — you can use any JavaScript you want (loops, math, formatting, conditionals). Templates are for when you need to render PDFs without a JavaScript runtime: a hosted API, a Rust/Go/Python backend, or stored templates that accept dynamic data at render time. Template-mode templates must be pure display — all computation happens in your data layer, not in the template.

How it works

The template compiler traces your JSX with a recording proxy that captures property accesses and .map() calls, producing a JSON document with expression markers instead of concrete values.

1. Write a template

Export a function that receives data and returns a <Document>:
This is the same JSX you’d use for a normal Forme PDF. The only difference is that data will be a recording proxy during compilation.

2. Compile to template JSON

This produces a JSON file where dynamic values are expression nodes:

3. Render with data

In Node.js

From any language

The template JSON and data JSON are plain strings. Any language that can call the Forme WASM module or a future HTTP API can render templates.

Expression reference

These expression nodes are what the compiler produces. You can also hand-write template JSON if you prefer.

$ref — Data lookup

Dot-path traversal into the data object. Missing paths are silently omitted.

$each — Array iteration

Iterates an array and renders the template for each item. Results are flattened into the parent array.
The as field names the loop variable (default: $item). Inside the template, $ref paths starting with that name resolve to the current item.

$if / then / else — Conditional

Renders then if the condition is truthy, else otherwise. The else branch is optional.

$cond — Ternary value

Three-element array: [condition, ifTrue, ifFalse].

Comparison operators

Two-element arrays. Return true or false.

Arithmetic operators

Two-element arrays. Return a number.

String operators

The $format operator formats a number. The format string determines decimal places: "0.00" gives 2 decimal places, "0.0" gives 1.

expr helpers

For operations that a property-access proxy can’t capture (comparisons, arithmetic, conditionals), use the expr helpers in your JSX template:

Available helpers

Truthiness

For $if and $cond, values are truthy/falsy like JavaScript with one difference: