Skip to content

Template structure

When you open the Template tab in Studio, you’re editing a single JSON document that defines the whole template — its page setup, layout, styling, and where data is filled in. This page is the reference for that structure.

You rarely need to write this from scratch — the AI Assistant generates and edits it for you. This reference is for when you want to read the definition or change it precisely by hand.

A template is a JSON object. The only property you always need is elements; everything else has a sensible default.

{
"pageSize": "a4",
"pageMargins": { "top": 57, "bottom": 57, "left": 57, "right": 57 },
"elements": [
{ "type": "text", "content": "Hello {{customerName}}" }
],
"headers": [],
"footers": [],
"pageBackgrounds": [],
"watermarks": []
}

These are the top-level (root) properties.

Property Type What it does
pageSize a4 · letter · legal · custom Page size. Defaults to a4.
pageOrientation portrait · landscape Page orientation. Defaults to portrait.
customPageWidth / customPageHeight number (mm) Page dimensions in millimetres. Required when pageSize is custom.
pageMargins spacing Margins on every page, in points. Defaults to 40 on each side.
defaultFontFamily string Default font for all text that doesn’t set its own. See Fonts.
pageBackgrounds array Per-page background colour/image — see Page backgrounds.
headers / footers array Content repeated at the top/bottom of pages — see Headers and footers.
watermarks array Overlays drawn on top of (or behind) page content — see Watermarks.
elements array The document body: elements rendered top-to-bottom in order.

Most page setup is also editable through the visual Page Properties form — see Edit by hand → Page setup.

elements are stacked top-to-bottom in the order they appear. To place things side by side, use a row with columns:

{
"type": "row",
"gutter": 20,
"columns": [
{ "width": { "value": 0.25, "type": "proportional" }, "elements": [ /* … */ ] },
{ "width": { "value": 0.75, "type": "proportional" }, "elements": [ /* … */ ] }
]
}
  • gutter — horizontal space (points) between columns. With N columns there are N−1 gutters.
  • Each column has an optional width and its own elements list (which flow top-to-bottom inside the column).
  • A column width has a value and a type:
    • proportionalvalue is a fraction of the row (0.25 = 25%). This is the default.
    • absolutevalue is a fixed width in points.
  • Columns with no width share the remaining space evenly.
  • A row can also draw a vertical divider between its columns.

A table lays out a grid with fixed column widths, optional header rows, and body rows that can repeat over data.

{
"type": "table",
"columnWidths": [
{ "value": 0.5, "type": "proportional" },
{ "value": 0.5, "type": "proportional" }
],
"defaultBodyCellBorder": { "bottom": { "width": 0.5, "color": "#E0E0E0" } },
"headers": [
{ "backgroundColor": "#17395D", "cells": [
{ "elements": [ { "type": "text", "content": "Description", "typography": { "bold": true, "color": "#FFFFFF" } } ] },
{ "elements": [ { "type": "text", "content": "Total", "alignment": "right", "typography": { "bold": true, "color": "#FFFFFF" } } ] }
] }
],
"rows": [
{ "dataSource": "lineItems", "cells": [
{ "elements": [ { "type": "text", "content": "{{description}}" } ] },
{ "elements": [ { "type": "text", "content": "{{total as currency('EUR')}}", "alignment": "right" } ] }
] }
]
}

Table properties

Property What it does
columnWidths Array of { value, type } (see widths); the length defines the number of columns.
headers Header rows, repeated at the top of the table on each page.
rows Body rows. Each is static or data-bound (see below).
border Outer border of the whole table.
defaultHeaderCellBorder / defaultBodyCellBorder Default cell borders, overridable per cell.

Row properties (headers and rows entries): cells, dataSource (repeat — see Repeating content), condition, backgroundColor, minHeight.

Cell properties (cells entries): elements, padding, backgroundColor, border (per-side, see Borders), verticalAlignment (top · middle · bottom), and colSpan / rowSpan for spanning.

This is how data gets into the document.

Wrap a property from your data model in double braces. Use dots for nested values:

{{invoiceNumber}}
{{customer.name}}

Placeholders work in text content, in colours and image sources, and in most string fields — the reference notes where.

Append as <formatter>(…) inside the braces to format a value, for example:

{{issueDate as date(dd-MM-yyyy)}}
{{unitPrice as currency('EUR')}}

{{_system.*}} placeholders (date, page context, user, organisation, …) are injected automatically at render time. The full list is in the editor’s System Data tab — see Edit by hand.

Most elements (and table rows) accept a condition string that decides whether they render. Two forms:

  • Truthiness{{Paid}} renders the element when the value is truthy (a true boolean, a non-empty string, a non-empty collection, or any non-null object).
  • Comparison{{PropertyPath}} op value, where op is =, !=, >, <, >=, or <=. The value is a number, a quoted string, or a boolean. Prefer single quotes for strings (the whole condition is already inside a double-quoted JSON string):
{ "type": "text", "content": "DRAFT", "condition": "{{status}} = 'draft'" }

String and boolean comparisons support only = and !=.

To render something once per item in a collection, bind a data source. The property name is the plain name, without {{ }}. Inside the repeat, placeholders resolve against the current item.

  • Table rows — set dataSource on a row (see the table example).
  • loop — set dataSourceProperty; its children render once per item.
  • list — set dataSourceProperty + itemTemplate (e.g. "{{name}}").
  • checkbox — set dataSourceProperty / optionsDataSourceProperty.

Every element has a type plus these optional properties (from the element base):

Property Type What it does
margin spacing Outer spacing (points). Defaults to 0 on all sides.
padding spacing Inner spacing (points). Defaults to 0.
backgroundColor colour Fill behind the element.
condition string Render conditionally — see Conditions.
position { x, y } (cm) Absolute position from the page’s top-left corner. When set, the element is taken out of the normal flow.
rotation number (deg) Clockwise rotation around the element’s centre.
verticalAlignment top · middle · bottom Vertical alignment within its parent (row column, cell, border box).

A spacing value is { top, bottom, left, right } in points (any side optional). A colour is a hex string like "#17395D" or a two-stop linear gradient like "linear-gradient(90deg, #17395D, #E08A2B)".

Text-bearing elements take a typography object:

Property Default
fontSize 12 Points.
fontFamily "Arial" See Fonts.
bold / italic / underline false
color "#000000" Hex or gradient.
lineSpacing 1.0 Multiplier of the font’s natural line height.

Every element sets type and inherits the shared properties above. The fields below are each element’s own.

text — a run of text.

Field Notes
content The text; may contain placeholders.
typography See Typography.
alignment left (default) · center · right · stretch.
translationKey Resolve the text from the Translations dictionary instead of content.
columns Optional multi-column layout: { count (≥2), gap, maxHeight, fillType: grow|divide, rule }.
{ "type": "text", "content": "Invoice", "typography": { "fontSize": 18, "bold": true, "color": "#3E6491" } }

html — rich text from an HTML string (content), with typography and alignment. Use it for inline styling that plain text can’t express; supports {{placeholders}} and a set of common HTML tags.

imagesource, maxWidth, maxHeight (points), alignment. The source can be a gallery reference (pagr-image://<id>), a URL, a base64 data URI, or a {{placeholder}} that resolves to one. The image scales down to fit the max box while keeping its aspect ratio.

list — a bulleted or numbered list.

Field Notes
listStyle disc (default) · dash · circle · decimal · lowerAlpha · upperAlpha · lowerRoman · upperRoman.
items Static array of strings (each supports placeholders).
dataSourceProperty + itemTemplate Data-bound items — see Repeating content.
indentWidth Points reserved for the marker column.
itemSpacing Vertical gap between items (points, default 2).

checkbox — one or more checkbox options. Provide options (each { label, value }) or bind them with optionsDataSourceProperty; dataSourceProperty decides which are checked. Style with checkedStyle (check · cross · filledSquare · circle · filledCircle), boxColor, checkColor, and optionLayout (vertical · horizontal).

qrCodecontent (the value to encode, supports placeholders), size (points, default 80), alignment, color.

pageNumber — a page counter. format uses {current} and {total} (e.g. "Page {current} of {total}"), plus typography and alignment.

row — side-by-side columns, with gutter and optional divider. See Layout.

table — a grid with headers, rows, and cell borders. See Tables.

loop — repeat a block of children once per item in dataSourceProperty. keepStartTogether: true pushes the loop to a new page if the first item wouldn’t fit. See Repeating content.

border — a box drawn around child children.

Field Notes
borderColor Hex; defaults to black.
borderWidth Per-side widths (a single number for uniform, or { top, right, bottom, left }).
cornerRadius Points; 0 for sharp corners.
sizing stretch · shrink · fill.
pageBreak close · continue — how the box behaves when its content spills onto a new page.

separator — a horizontal rule: thickness (points, default 1) and color (hex or gradient).

pageBreak — starts a new page. Optionally changes pageSize / pageOrientation / customPageWidth / customPageHeight for that page and all pages after it — handy for a landscape page inside a portrait document.

shape — a vector rectangle, ellipse, or line.

Field Notes
shape rectangle (default) · ellipse · line.
width / height Bounding box in points.
fillColor Hex or gradient; omit for no fill.
strokeColor / strokeWidth / strokeStyle Outline; strokeStyle is solid · dashed · dotted.
cornerRadius For rectangles.
lineStart / lineEnd { x, y } in cm — only for line.

graph — a chart rendered from a Chart.js configuration object.

Field Notes
chart The Chart.js config (type, data, optional options); may contain {{placeholders}}.
title Optional heading above the chart.
width / height Points (height defaults to 250).
chartBackgroundColor Canvas background (default transparent).
theme { brand, pixelRatio } — brand colour and raster sharpness.

headers and footers each hold definitions with a displayOn rule and their own elements:

"footers": [
{ "displayOn": "allPages", "elements": [
{ "type": "pageNumber", "format": "Page {current} of {total}", "alignment": "center" }
] }
]

displayOn accepts allPages, firstOnly, lastOnly, allPagesExceptFirst, allPagesExceptLast, oddPages, or evenPages.

Each watermarks entry overlays text or an image on the page:

Field Notes
type text or image.
content / source Text content, or image source (same formats as image).
displayOn Same options as headers/footers.
layer front or behind page content.
opacity 0.01.0 (default 0.3).
rotation Degrees.
anchor center (default) · topLeft · topRight · bottomLeft · bottomRight, or set explicit x / y in cm.

Each pageBackgrounds entry targets a page (1-based) or acts as the default when page is null. Set a color, an image, or both. A background image takes a source plus optional size, position, opacity, rotation, and margin.

"pageBackgrounds": [ { "page": null, "color": "#FFFFFF" } ]