Variables
Variables let you inject dynamic data into your HTML templates at render time.
Syntax
Use double curly braces: {{variable_name}}
<h1>Invoice for {{company_name}}</h1>
<p>Amount due: {{total}}</p>
<p>Due date: {{due_date}}</p>Naming rules
Variable names must match this pattern:
[a-zA-Z_][a-zA-Z0-9_]*- Must start with a letter or underscore
- Can contain letters, numbers, and underscores
- Case-sensitive (
Nameandnameare different variables)
Valid: name, invoice_number, totalAmount, _internal, item2
Invalid: 2items (starts with number), full-name (contains hyphen), my.field (contains dot)
How rendering works
- PDF4.dev extracts all
{{variables}}from your template - Compiles the template with Handlebars
- Replaces each variable with the corresponding value from your
dataobject - Renders the resulting HTML to PDF
Variables that are not provided in data are replaced with an empty string.
Passing data
The data object accepts any JSON value: strings, numbers, booleans, nested objects, and arrays.
{
"template_id": "invoice",
"data": {
"company_name": "Acme Corp",
"invoice_number": "INV-2025-001",
"total": 4500.00,
"date": "March 1, 2025",
"items": [
{ "description": "Design work", "amount": 3000 },
{ "description": "Development", "amount": 1500 }
]
}
}Block helpers
Handlebars block helpers let you loop over arrays and conditionally render content.
{{#each}}
Iterate over an array. Inside the block, {{this}} refers to the current item, and named properties are accessible directly.
<table>
<tbody>
{{#each items}}
<tr>
<td>{{description}}</td>
<td>{{amount}}</td>
</tr>
{{/each}}
</tbody>
</table>With the data above, this renders one row per item in items.
{{#if}} and {{#unless}}
Render content conditionally. {{#if}} renders when the value is truthy; {{#unless}} renders when it is falsy.
{{#if discount}}
<p>Discount applied: {{discount}}</p>
{{/if}}
{{#unless paid}}
<p class="warning">Payment pending</p>
{{/unless}}You can combine these with comparison helpers (see below) for richer conditions.
Built-in helpers
PDF4.dev registers a set of Handlebars helpers available in every template.
Formatting
| Helper | Description |
|---|---|
{{formatNumber value "en-US"}} | Locale-aware number formatting. Accepts an optional decimals hash: {{formatNumber value "en-US" decimals=2}} |
{{formatDate value "short"}} | Date formatting. Formats: "short", "long", "iso", or a custom pattern like "dd MMM yyyy" |
{{formatCurrency value "EUR" "fr-FR"}} | Currency formatting with currency code and locale |
<p>Total: {{formatNumber total "en-US" decimals=2}}</p>
<p>Date: {{formatDate due_date "dd MMM yyyy"}}</p>
<p>Price: {{formatCurrency amount "EUR" "fr-FR"}}</p>Text
| Helper | Description |
|---|---|
{{uppercase value}} | Converts to uppercase |
{{lowercase value}} | Converts to lowercase |
{{padStart value 5 "0"}} | Pads a string to the given length with a fill character |
<p>{{uppercase company_name}}</p>
<p>{{padStart invoice_number 6 "0"}}</p>Comparison
Use these inside {{#if}} for conditional logic.
| Helper | Description |
|---|---|
{{eq a b}} | True if a === b |
{{neq a b}} | True if a !== b |
{{gt a b}} | True if a > b |
{{lt a b}} | True if a < b |
{{gte a b}} | True if a >= b |
{{lte a b}} | True if a <= b |
{{#if (gt total 1000)}}
<p>Large order discount applies.</p>
{{/if}}
{{#if (eq status "paid")}}
<p class="badge">Paid</p>
{{/if}}Math
| Helper | Description |
|---|---|
{{math a "+" b}} | Arithmetic between two values. Supports +, -, *, /, % |
<p>Subtotal: {{math total "-" discount}}</p>
<p>Tax (20%): {{math total "*" 0.2}}</p>Auto-detection
The dashboard automatically detects variables in your HTML and displays them in the Variables panel. You can set sample values there for the live preview.
Variables are also auto-completed in the Monaco code editor when you type {.
Tips
- Keep variable names descriptive:
customer_emailovere - Use underscores for multi-word names:
invoice_numberoverinvoiceNumber - Variables work in any part of the HTML: attributes, styles, content
- You can use the same variable multiple times in a template
<a href="mailto:{{email}}">{{email}}</a>
<div style="color: {{brand_color}}">{{company_name}}</div>