Skip to main content

Template Schema Reference

This guide defines the exact JSON schema structure for document templates in RenderDoc. Use this as the authoritative reference when creating templates programmatically, via API, or with AI assistants.

warning

For AI/LLM Systems: Variables must be a plain JSON array [...], NOT wrapped in an object like {"variables": [...]}. See the AI Import Format section below.

AI/LLM Import Format

When generating templates with AI, you need to provide two separate JSON structures:

  1. Variables Array - The data schema defining what variables the template expects
  2. Template Schema - The visual design structure (sections and components)

Variables Format

⚠️ CRITICAL FOR AI/LLM: Variables must be a PLAIN JSON ARRAY [...], NOT wrapped in an object like { "variables": [...] }.

danger

Common AI Mistake: Do NOT wrap variables in an object. The format is a plain array.

✅ CORRECT format (plain array):

[
{
"id": "var_1",
"name": "customerName",
"type": "string",
"required": true,
"description": "Customer's full name",
"defaultValue": "John Doe"
},
{
"id": "var_2",
"name": "orderTotal",
"type": "number",
"required": true,
"defaultValue": 99.99
}
]

❌ INCORRECT format (DO NOT USE):

{
"variables": [
{ "name": "customerName", "type": "string" }
]
}

This WILL NOT work. Variables must be a plain array, not wrapped in an object.

[
{
"id": "var_1",
"name": "customerName",
"type": "string",
"required": true,
"description": "Customer's full name",
"defaultValue": "John Doe"
}
]
{
"variables": [
{ "name": "customerName", "type": "string" }
]
}

This will NOT work. Variables must be a plain array.

Variable Object Fields

FieldTypeRequiredDescription
idstringNo*Unique identifier (auto-generated if omitted)
namestringYesVariable name (used in {{variableName}} syntax)
typestringYesOne of: string, number, boolean, date, array, object
requiredbooleanNoWhether the variable is required (default: false)
descriptionstringNoHuman-readable description
defaultValueanyRecommendedDefault/sample value for testing and preview
isCalculatedbooleanNotrue if this is a calculated variable
expressionstringNoJavaScript expression (required if isCalculated: true)
schemaobjectNoType schema for array and object types
formatobjectNoDisplay format configuration

*If id is omitted, it will be auto-generated when imported.

Array Variable Example

{
"id": "var_items",
"name": "items",
"type": "array",
"itemType": "object",
"required": true,
"description": "List of order items",
"defaultValue": [
{ "name": "Product A", "quantity": 1, "price": 29.99 }
],
"schema": {
"type": "array",
"itemType": "object",
"itemSchema": {
"properties": {
"name": { "type": "string" },
"quantity": { "type": "number" },
"price": { "type": "number" }
}
}
}
}

Object Variable Example

{
"id": "var_customer",
"name": "customer",
"type": "object",
"required": true,
"description": "Customer information",
"defaultValue": {
"name": "Jane Smith",
"email": "[email protected]"
},
"schema": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Customer name" },
"email": { "type": "string", "description": "Customer email" }
}
}
}

Basic Template Schema

Templates use a sections array at the root level.

{
"sections": [
{
"id": "body-section",
"type": "body",
"props": {
"backgroundColor": "#ffffff",
"padding": "40px 20px"
},
"components": [
// Array of component objects
]
}
]
}

Section Types

TypeDescription
headerTop section (logo, navigation)
main or bodyMain content section
footerBottom section (copyright, links)

Multi-Page Template Schema

PDF and Excel templates can use a pages array with nested sections for multi-page documents:

{
"outputFormats": ["pdf"],
"pages": [
{
"pageId": "page-1",
"pageName": "Invoice",
"pageSettings": {
"format": "A4",
"orientation": "portrait",
"margin": { "top": "20mm", "right": "15mm", "bottom": "20mm", "left": "15mm" }
},
"sections": [
{
"id": "main-section",
"type": "main",
"props": {},
"components": []
}
]
}
]
}

Output Formats

FormatDescription
["pdf"]Generate PDF attachment
["excel"]Generate Excel attachment
["pdf", "excel"]Generate both formats

Page Settings

FieldTypeDefaultDescription
formatstring"A4""A4", "Letter", "Legal", "A3", "A5", "Tabloid"
orientationstring"portrait""portrait" or "landscape"
marginobject-Page margins (top, right, bottom, left)
backgroundColorstring"#ffffff"Page background color
headerobject-Header configuration
footerobject-Footer configuration

Component Reference

Component Types by Output Format

ComponentPDFExcelDescription
rich-textRich text with HTML (use instead of text)
buttonCTA buttons with links
imageImages
tableData tables
table-layoutCustom table layouts
containerComponent wrapper
columnsMulti-column layout
dividerHorizontal rule
spacerVertical space
conditionalIf/else rendering
loopIteration over arrays
listOrdered/unordered lists
qr-codeQR codes
barcodeBarcodes (Code128, EAN, UPC, etc.)
chartCharts (bar, line, pie, etc.)
timelineActivity timeline
html-fragmentRaw HTML injection
note

The text and heading components are deprecated. Use rich-text instead.

Component Structure

Components use one of three patterns:

1. Content-based (rich-text, button, list):

{
"id": "welcome-text",
"type": "rich-text",
"props": { "marginBottom": "16px" },
"content": "<p>Hello {{name}}</p>"
}

2. Props-based (image, divider, spacer, qr-code):

{
"id": "logo",
"type": "image",
"props": {
"src": "{{company.logo}}",
"alt": "Logo",
"width": "120px"
}
}

3. Children-based (container, columns, conditional, loop):

{
"id": "wrapper",
"type": "container",
"props": { "padding": "20px" },
"children": [
{ "id": "child-1", "type": "rich-text", "content": "..." }
]
}

Variable Syntax

Basic Substitution

{{variableName}}
{{customer.firstName}}
{{order.items[0].name}}

In Content

{
"type": "rich-text",
"content": "<p>Hello {{customer.name}}, your order #{{order.number}} is ready.</p>"
}

In Props

{
"type": "button",
"props": {
"href": "{{trackingUrl}}"
},
"content": "Track Package"
}

Conditional Logic

{
"id": "discount-banner",
"type": "conditional",
"props": {
"condition": "hasDiscount",
"operator": "==",
"value": true
},
"children": [
{
"id": "discount-text",
"type": "rich-text",
"content": "<p>You saved ${{discountAmount}}!</p>"
}
]
}

Operators

OperatorDescription
==Equals
!=Not equals
>Greater than
<Less than
>=Greater than or equal
<=Less than or equal
containsString/array contains
startsWithString starts with
endsWithString ends with
existsValue exists (not null/undefined)
isEmptyValue is empty

Loop Iteration

{
"id": "items-loop",
"type": "loop",
"props": {
"dataSource": "{{items}}",
"itemVariable": "item",
"indexVariable": "index"
},
"children": [
{
"id": "item-row",
"type": "rich-text",
"content": "<p>{{index}}. {{item.name}} - ${{item.price}}</p>"
}
]
}

Loop Props

PropRequiredDescription
dataSourceYesVariable containing array: {{items}}
itemVariableYesName for current item: item
indexVariableNoName for current index: index

System-Provided Global Constants

These variables are automatically available in all templates:

Date Constants

VariableExample Value
{{__CURRENT_DATE__}}2025-12-02
{{__CURRENT_YEAR__}}2025
{{__CURRENT_MONTH__}}December
{{__CURRENT_DAY__}}2
{{__CURRENT_DAY_NAME__}}Tuesday

Company Constants

VariableDescription
{{__COMPANY_NAME__}}Company display name
{{__COMPANY_LEGAL_NAME__}}Legal name
{{__COMPANY_EMAIL__}}Contact email
{{__COMPANY_PHONE__}}Phone number
{{__COMPANY_WEBSITE__}}Website URL
{{__COMPANY_ADDRESS_LINE1__}}Address line 1
{{__COMPANY_CITY__}}City
{{__COMPANY_STATE__}}State/Province
{{__COMPANY_POSTAL_CODE__}}Postal/ZIP code
{{__COMPANY_COUNTRY__}}Country

Complete Example

Variables

[
{
"id": "var_customer",
"name": "customer",
"type": "object",
"required": true,
"defaultValue": { "name": "Jane Smith", "email": "[email protected]" },
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
}
}
},
{
"id": "var_items",
"name": "items",
"type": "array",
"itemType": "object",
"required": true,
"defaultValue": [
{ "name": "Widget", "qty": 2, "price": 25.00 }
],
"schema": {
"type": "array",
"itemType": "object",
"itemSchema": {
"properties": {
"name": { "type": "string" },
"qty": { "type": "number" },
"price": { "type": "number" }
}
}
}
},
{
"id": "var_total",
"name": "orderTotal",
"type": "number",
"required": true,
"defaultValue": 99.99
}
]

Template Schema

{
"sections": [
{
"id": "body-section",
"type": "body",
"props": { "backgroundColor": "#f9fafb", "padding": "40px 20px" },
"components": [
{
"id": "main-container",
"type": "container",
"props": {
"backgroundColor": "#ffffff",
"maxWidth": "600px",
"margin": "0 auto",
"borderRadius": "8px",
"padding": "32px"
},
"children": [
{
"id": "greeting",
"type": "rich-text",
"props": { "marginBottom": "24px" },
"content": "<h1 style=\"margin: 0; font-size: 24px;\">Hello {{customer.name}}</h1>"
},
{
"id": "intro",
"type": "rich-text",
"props": { "marginBottom": "16px" },
"content": "<p style=\"margin: 0; color: #6b7280;\">Thank you for your order:</p>"
},
{
"id": "items-loop",
"type": "loop",
"props": {
"dataSource": "{{items}}",
"itemVariable": "item"
},
"children": [
{
"id": "item-row",
"type": "rich-text",
"content": "<p style=\"margin: 4px 0;\">• {{item.name}} x {{item.qty}} = ${{item.price}}</p>"
}
]
},
{
"id": "total-row",
"type": "rich-text",
"props": { "marginTop": "16px" },
"content": "<p style=\"margin: 0; font-weight: bold;\">Total: ${{orderTotal}}</p>"
}
]
}
]
}
]
}

AI Generation Checklist

Before outputting a template, verify:

  • Variables are a plain array [...], not { "variables": [...] }
  • Every variable has name and type fields
  • Every variable has a defaultValue for testing
  • Array variables have itemType and schema.itemSchema.properties
  • Object variables have schema.properties
  • Schema has sections array (single-page) or pages array (multi-page)
  • Every component has a unique id
  • Variable references use {{variableName}} syntax
  • Loop components use {{arrayVariable}} for dataSource
  • Nested object access uses dot notation: {{customer.name}}

How to Import into RenderDoc

Open the Template Designer

Navigate to Templates and create a new template or edit an existing one.

Import Variables

  1. Click Manage Variables in the toolbar
  2. Switch to the Raw JSON tab
  3. Paste your variables array
  4. Click Validate to check for errors
  5. Click Apply Changes

Import Schema

  1. Click the code icon (</>) in the toolbar to open Raw Schema Editor
  2. Paste your schema JSON
  3. Click Validate to check for errors
  4. Click Apply Changes

Save Template

Click Save to persist your changes.