DOCX Templates
DOCX templates let you author in Microsoft Word (or LibreOffice Writer) and
keep a fully editable layout. Velkin fills Handlebars placeholders directly in
the document's OOXML, then either returns the native .docx or converts it to
PDF via LibreOffice.
| Asset extension | .docx |
| Engine | Handlebars.js 4.7.8 (goja VM), preprocessed on word/document.xml |
| Renderer | Native fill, or LibreOffice (soffice) → PDF |
| Endpoints | render-docx (native), render-pdf (converted) |
How it works
A .docx is a ZIP of OOXML parts. When you render, Velkin:
- unzips the document;
- rejoins Handlebars tags that Word split across formatting runs;
- promotes block markers that sit alone in a row or paragraph so the loop or condition wraps the whole row/paragraph;
- runs the document XML through Handlebars with your data;
- re-zips the parts and returns the result.
Placeholders
Type Handlebars tags straight into the document text:
Invoice #{{number}}
Bill to: {{customer.name}}
Issued: {{date}}
Nested fields use dotted paths ({{customer.address.city}}), exactly as in HTML
templates.
Word silently splits text into multiple "runs" when formatting changes
mid-word, which can fragment a tag like {{amount}} into {{amo + unt}}.
Velkin rejoins split runs before substituting, so this usually just works —
but you'll have the fewest surprises if you type each tag in one go and clear
stray formatting inside it (select the tag → Clear Formatting).
Loops and conditionals
{{#each}} and {{#if}} work across paragraphs and table rows. The trick is
where you place the markers: put the opening and closing tags alone in
their own row or paragraph, and Velkin promotes them to wrap everything
between.
In a table — opening tag alone in a row, the repeated content in the next row, closing tag alone in a row:
┌─────────────────────────────────────┐
│ {{#each items}} │
├──────────────────┬──────────────────┤
│ {{description}} │ {{amount}} € │ ← repeated once per item
├──────────────────┴──────────────────┤
│ {{/each}} │
└─────────────────────────────────────┘
In body text — each marker on its own paragraph:
{{#if overdue}}
This invoice is overdue. Please pay immediately.
{{/if}}
Helpers & partials
The report's helpers.hbs works inside DOCX templates exactly as in HTML: it's
JavaScript, so register helpers and partials with Handlebars.registerHelper /
Handlebars.registerPartial and invoke them with {{helperName arg}} /
{{> name}}. See Helpers & Partials.
On the DOCX/XLSX pipelines Handlebars runs with HTML-escaping disabled, because the document XML is already entity-encoded. A helper that returns markup won't be double-escaped — but it also won't be sanitized, so keep helper output to plain text and values.
Native vs PDF output
render-docxreturns the filled-in.docx— editable, fonts and layout exactly as authored.render-pdffills the template and converts to PDF with LibreOffice. Use it for a non-editable artefact.
In the Studio, the preferredOutput setting (native / pdf) only decides
which of these the download button calls — see
Output formats.
PDF conversion runs through the LibreOffice bundled in the backend image. If a font used by your template isn't installed there, LibreOffice substitutes the closest match, which can shift layout. Install the fonts you need in the backend image, or stick to widely available families.