Reports & Templates
Velkin organizes everything around the report (internally a
ReportTemplate): one document that holds a project's templates, helpers,
sample data, and output options. The API renders reports — you never POST a
template inline.
The report document
A report is a single JSON document with these fields:
| Field | Type | Notes |
|---|---|---|
slug | string | URL identifier. Lowercase letters, numbers, single dashes. |
name | string | Human-readable title. |
description | string | Optional. |
engine | string | Templating engine — currently always handlebars. |
helpersHbs | string | JavaScript helpers & partials (the helpers.hbs tab) — see Helpers. |
templates | array | The template assets (see below). |
sampleData | object | Default render data (the data.json tab). |
outputOptions | object | Active template + PDF/output settings (the options.json tab). |
status | string | draft, published, or archived. |
version | int | Bumped on every update to the report document. |
Reports are addressed by slug (or by their Mongo id) in every API URL, e.g.
POST /api/reports/{slug}/render-pdf.
Template assets
A template asset is one renderable file owned by a report. Its kind is
derived from the filename extension:
| Extension | Kind | Storage |
|---|---|---|
.html, .htm | html | text |
.docx | docx | binary bytes |
.xlsx | xlsx | binary bytes |
A report can hold several assets side by side (e.g. an HTML and a DOCX variant).
Asset names must be a plain filename — no path separators — matching
^[A-Za-z0-9][A-Za-z0-9._-]*$, and cannot collide with the reserved names below.
Templates are managed through dedicated endpoints
(/api/reports/{id}/templates/...); they are not mutated by
PUT /api/reports/{id}, which only edits the report's editable fields.
The reserved files
The Studio shows every project with three always-present "files". These are not template assets — they are reserved names that map onto report fields:
| File | Maps to | Purpose |
|---|---|---|
options.json | outputOptions | Active template + output settings |
data.json | sampleData | Default data used when none is POSTed |
helpers.hbs | helpersHbs | JavaScript helpers & partials |
Because they are reserved, you cannot name a template asset options.json,
data.json, or helpers.hbs.
options.json
options.json is the serialized outputOptions. It picks the active template
and configures the output pipeline:
{
"template": "template.html",
"preferredOutput": "pdf",
"pdf": {
"enabled": true,
"printBackground": true,
"landscape": false,
"preferCSSPageSize": true,
"format": "A4"
},
"docx": { "enabled": true },
"xlsx": { "enabled": true }
}
| Key | Purpose |
|---|---|
template | Which asset is rendered. Must match an asset in templates. |
preferredOutput | pdf or native — steers the Studio download button (see below). |
pdf.format | Page size: A0–A6, B4, B5, LETTER, LEGAL, TABLOID, LEDGER. |
pdf.printBackground | Print background colors/images. |
pdf.landscape | Landscape orientation. |
pdf.preferCSSPageSize | Let CSS @page size win over pdf.format. |
preferredOutput is a Studio hintThe render endpoints are deterministic by format — render-pdf always returns
PDF, render-docx always returns DOCX, render-xlsx always returns XLSX. The
render endpoints ignore preferredOutput (the backend only validates it's pdf
or native); it just tells the Studio which endpoint its "download" button
should call for a binary template. See
Output formats.
Handlebars
All formats use Handlebars.js 4.7.8 for data binding, run server-side in a
sandboxed JavaScript VM (goja). The data object you POST to /render-*
becomes the template context; omit it and the report's sampleData is used
instead:
For DOCX and XLSX the same syntax works inside paragraphs, table rows, and cells — Velkin reassembles the OOXML runs and substitutes the tags before rendering. See the DOCX and XLSX guides for the format-specific rules.
Reusable logic — custom helpers and partials — lives in helpers.hbs, which is
executed as JavaScript before each template compiles. See
Helpers & Partials.
Versioning
Every template asset and reserved file carries its own revision history, persisted server-side. From the Studio you can:
- browse the history of any file,
- view a previous revision and restore it,
- group a set of changes into a commit with a message.
History is per-file, so editing template.html doesn't bump the DOCX asset.
The API surface lives under /api/reports/{id}/history/... and
/api/reports/{id}/commits — see the API reference.