Template Components

Payload Structure

Complete reference for the top-level VaultPDF JSON payload. Covers templateId, metadata, theme, header, footer, layoutSchema, templateSettings, hierarchyRules, and all other recognized top-level keys.

Overview

Every VaultPDF document starts as a single JSON object. The rendering engine reads a fixed set of top-level keys to configure the document; all remaining keys are treated as data and fed to the content renderer.

{
  "templateId":       "...",
  "metadata":         { },
  "theme":            { },
  "templateSettings": { },
  "hierarchyRules":   { },
  "watermarkText":    "...",
  "layoutSchema":     { },
  "sampleData":       { },

  "customerName":  "Acme Corp",
  "salesOrders":   [ ]
}

The .vpdf File Format

A .vpdf file is a plain JSON file saved with a .vpdf extension - there is no binary encoding or compression. It is the portable, self-contained export of a VaultPDF template: everything the rendering engine needs to produce a PDF, bundled into one file.

What's Inside

A .vpdf file contains exactly the same top-level keys described in this document, plus extra metadata catalog fields (displayName, category, tags, complexity, thumbnail) that power the template library browser.

{
  "templateId": "invoice-standard-v2",
  "metadata": {
    "templateId": "invoice-standard-v2",
    "displayName": "Invoice Standard v2",
    "description": "Enterprise-grade invoice with logo and line-item table.",
    "category": "finance",
    "tags": ["invoice", "finance"],
    "version": "2.0",
    "author": "VaultPDF Team",
    "engineVersion": "1.0.0",
    "renderMode": "flow",
    "lastModified": "2026-02-13"
  },
  "theme": { },
  "templateSettings": { },
  "layoutSchema": { },
  "hierarchyRules": { },
  "sampleData": { }
}

How .vpdf Files Are Used

ContextBehaviour
Designer - ExportThe "Export" button in the Designer saves the current template as {templateName}.vpdf. All schema, theme, and settings are embedded.
Designer - ImportDrop or pick a .vpdf file to reload a template. The Designer restores schema, theme, templateSettings, sampleData, and hierarchyRules in one step.
Server renderingThe rendering engine resolves the incoming templateId and reads {templateId}.vpdf from the server's templates/ folder.
Render API callSend the .vpdf JSON directly as the request body, merging your live data at the top level. The sampleData key is ignored at render time - it is only used for Designer preview.

Sending a .vpdf to the Render API

Read the .vpdf file, add your runtime data keys at the top level alongside the existing template keys, and POST the merged object:

{
  "templateId": "invoice-standard-v2",
  "metadata": { },
  "theme": { },
  "templateSettings": { },
  "layoutSchema": { },

  "companyName": "Acme Corp",
  "customerName": "Beta Industries",
  "invoiceNumber": "INV-1042",
  "invoiceLines": [
    { "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99 }
  ]
}

sampleData at Render Time

sampleData is only read by the Designer for live preview. At render time the engine reads data from the runtime keys you supply at the top level - it never renders sampleData into the final PDF.


Top-Level Key Reference

KeyRequiredDescription
templateIdRequiredStable identifier for the template. Used by the API and the "Prepare for Production" checker.
metadataRecommendedHuman-readable document meta - version, description, author, etc.
themeRecommendedColor palette and typography for the document. Falling back omits explicit colors across tables and headers.
templateSettingsRecommendedLocale, date formats, currency, boolean labels, TOC, watermark, security. See Template Settings.
hierarchyRulesOptionalPer-level styling, computations, and column manifests for hierarchical tables. See Hierarchical Table.
watermarkTextOptionalRuntime override for watermark text. Takes precedence over templateSettings.watermark.value.
layoutSchemaOptionalDesigner-generated schema (SchemaV2). When present this path takes precedence over content[].
contentOptionalLegacy document content array. Used when layoutSchema is absent.
sampleDataOptionalExample payload for template preview and the "Prepare for Production" checker.

Reserved Key Names

Keys that start with _ and the reserved names theme, activeTheme, metadata, hierarchyRules, __meta, __schema are excluded from adaptive table columns automatically. Your data keys never conflict with these control keys as long as you avoid those names.


templateId

A stable, unique string that identifies the template. Required for production export and API calls.

  • Resolved first from the top-level templateId key.
  • Falls back to metadata.templateId if the top-level key is absent.
  • Must be a non-empty string.
{
  "templateId": "sales-order-v2",
  "metadata": {
    "version": "2.1"
  }
}

Tip

Use a consistent slug-style identifier (e.g. "invoice-us-en", "shipment-manifest") so it remains stable across payload versions.


metadata

Optional free-form object for human-readable document meta. None of the fields are structurally required, but version is used by the integrity checker.

PropertyTypeDescription
metadata.templateIdstringFallback template identifier when the top-level templateId key is absent.
metadata.versionstringTemplate version string (e.g. "1.0", "2.3.1"). Used by the integrity checker - a warning is emitted when absent.
metadata.descriptionstringHuman-readable description of the template's purpose.
metadata.authorstringTemplate author or team name.
metadata.createdAtstringISO date string recording when the template was created.
metadata.tagsstring[]Free-form tags for categorization.
{
  "metadata": {
    "templateId": "sales-order-v2",
    "version": "2.1",
    "description": "Sales order confirmation for US domestic accounts.",
    "author": "VaultPDF Team",
    "createdAt": "2026-01-15",
    "tags": ["sales", "order", "us", "domestic"]
  }
}

theme

The theme object supplies the visual identity for the entire document. Colors defined here propagate automatically to table headers, section title accents, border lines, zebra-stripe rows, and all "theme.*" token references in node props.

Structure

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#1E3A5F",
      "secondary":     "#2D6A9F",
      "headerShade":   "#F1F5F9",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    },
    "typography": {
      "bodyFont":    "Inter",
      "headingFont": "Inter"
    }
  }
}

theme.type

ValueDescription
"modern"Clean sans-serif enterprise style with lighter tints auto-generated from primary.
"formal"More structured layout with slightly higher contrast.
"custom"All palette values taken literally - no automatic tint generation.

theme.colors Properties

All color values must be valid 3- or 6-digit hex strings (e.g. "#1E3A5F" or "#FFF").

PropertyDescriptionEffect when missing
primaryPrimary brand color. Used for table header fills and section title accents.Falls back to #1A73E8.
secondarySecondary accent color. Used for tints and highlights.Auto-derived from primary.
headerShadeLight background tint used in key-value sections and sub-headers.Auto-derived from primary.
textOnPrimaryText and icon color rendered on top of primary-filled cells.Auto-computed via contrast ratio.
textOnShadeDefault body text and label color.Falls back to #333333.
borderColorLine color for table borders, separators, and section outlines.Falls back to #E5E7EB.
stripeShadeFill color for zebra-striped table rows.Falls back to #F9FAFB.

Auto-Generated Colors

When theme.colors.primary is supplied and theme.type is "modern" or "formal", VaultPDF auto-generates secondary, headerShade, textOnPrimary, textOnShade, and stripeShade using a perceptual contrast algorithm. You only need to override them explicitly when the auto-generated values don't match your brand.

theme.typography

PropertyTypeDefaultDescription
typography.bodyFontstring"Inter"Font family for body text and table content. Must be registered in the VaultPDF font registry.
typography.headingFontstring"Inter"Font family for section headings and table headers.

Theme Tokens

Node props throughout the Designer accept "theme.*" string tokens instead of raw hex values. The renderer resolves them at render time from the active palette so swapping the theme object automatically recolors the entire document.

TokenResolves to
"theme.primary"theme.colors.primary
"theme.secondary"theme.colors.secondary
"theme.headerShade"theme.colors.headerShade
"theme.textOnPrimary"theme.colors.textOnPrimary
"theme.textOnShade"theme.colors.textOnShade
"theme.borderColor"theme.colors.borderColor
"theme.stripeShade"theme.colors.stripeShade

Applying a token in a field node prop:

{
  "type": "field",
  "props": {
    "label": "Customer",
    "path": "customerName",
    "labelFillColor": "theme.primary",
    "labelTextColor": "theme.textOnPrimary",
    "labelStyled": true
  }
}

Minimal (primary only - let engine auto-generate the rest):

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary": "#1E3A5F"
    }
  }
}

Full override (every color explicit):

{
  "theme": {
    "type": "custom",
    "colors": {
      "primary":       "#1E3A5F",
      "secondary":     "#2D6A9F",
      "headerShade":   "#F1F5F9",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    },
    "typography": {
      "bodyFont": "Inter"
    }
  }
}

Warm amber brand:

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#B45309",
      "textOnPrimary": "#FFFFFF",
      "borderColor":   "#FDE68A"
    }
  }
}

The header is a Designer node of type: "header" inside layoutSchema. When present and visible is not false, it repeats on every page in the top margin area. The page's top content margin is automatically increased to prevent content from overlapping the header.

Header Node Props

PropertyTypeDefaultDescription
titlestring"Document"Main heading text. Supports {FIELD} tokens.
subtitlestringnoneSecondary line below the title.
textColorstring"theme.textOnShade"Color for title and subtitle text. Accepts hex or "theme.*" token.
fontSizenumber18Font size (pt) for the title text.
subtitleFontSizenumber10Font size (pt) for the subtitle text.
alignment"left" | "center" | "right""left"Horizontal alignment of the title block (used when no logo is present).
titleLayout"combined" | "split" | "split-reverse""combined""combined" stacks title and subtitle. "split" puts them in a two-column row (title left, subtitle right). "split-reverse" reverses the order.
backgroundstringnoneHeader area background fill. Accepts hex or "theme.*" token.
borderStyle"solid" | "dashed" | "none""none"Style of the border line drawn below the header.
borderColorstring"#E2E8F0"Color of the header border line.
borderWidthnumber1Width (pt) of the header border line.
paddingVnumber6Vertical padding (pt) inside the header area. Increasing this also increases the top content margin.
visiblebooleantrueWhen false, no header is rendered and top content margin returns to the default 40pt.

Logo Props

These props are set on the header node in the template (Designer or .vpdf file) and define the default logo for the document.

PropertyTypeDefaultDescription
showLogobooleanfalseEnable logo rendering in the header. Must be true for any logo - template or payload - to appear.
logoType"svg" | "image""svg""svg" renders an inline SVG string; "image" renders a base64-encoded PNG or JPEG.
logoSvgstringnoneInline SVG markup for the logo. Used when logoType is "svg".
logoBase64stringnoneBase64-encoded PNG/JPEG. Accepted as a raw base64 string or a full data:image/png;base64,... data URI. Used when logoType is "image".
logoWidthnumber120Rendered width of the logo in points (max 200). Height scales proportionally for SVG; use logoHeight with logoType: "image" for explicit height.
logoHeightnumbernoneExplicit rendered height in points (max 200). For "image" logos this sets the fit bounding box; for "svg" logos it forces the row height.
logoAlignment"left" | "center" | "right""left"Alignment of the logo within its column.
logoLayout"logo-left-title-right" | "title-left-logo-right" | "title-center""logo-left-title-right"Layout of logo and title within the header row. "title-center" hides the logo column entirely.

Runtime Logo Override via branding

Source systems (ERP, CRM, Power Platform connectors, etc.) can supply or replace the logo at generate time without modifying the template. Pass a top-level branding object in the payload alongside your data:

{
  "templateId": "sales-order-v2",
  "branding": {
    "logoSvg":    "<svg ...>...</svg>",
    "logoBase64": null,
    "logoWidth":  160,
    "logoLayout": "logo-left-title-right"
  },
  "general": { ... }
}

Template must have showLogo: true

The payload branding override patches an existing logo column in the rendered header - it does not inject a new one. The template header node must have showLogo: true and at least one of logoSvg or logoBase64 set, even as a placeholder, for the runtime override to take effect.

branding Override Fields

FieldTypeDescription
branding.logoSvgstringSVG string that replaces the template's logo. Takes priority over logoBase64 when both are provided. Passed through the SVG sanitizer - scripts, event handlers, and data: URLs are rejected.
branding.logoBase64stringBase64 PNG/JPEG that replaces the template's logo. Accepted as raw base64 or a full data:image/png;base64,... data URI. Only used when logoSvg is absent or null.
branding.logoWidthnumberOverrides the logo width (points). Applied after the SVG/image swap.
branding.logoLayout"logo-left-title-right" | "title-left-logo-right" | "title-center"Overrides the column arrangement at render time. "title-center" removes the logo column and centers the title.

Priority Order

When the renderer builds the logo it resolves sources in this order - the first non-null value wins:

PrioritySourceWhere it lives
1 (highest)branding.logoSvgRuntime payload
2branding.logoBase64Runtime payload
3logoSvg node propTemplate / Designer
4logoBase64 node propTemplate / Designer
-No logoshowLogo: false or all sources null

Choosing a Logo Strategy

ScenarioRecommended approach
Single-tenant, logo never changesBake logoSvg or logoBase64 into the template props. No payload overhead.
Multi-tenant / per-customer logoSet a placeholder SVG in the template; pass branding.logoSvg or branding.logoBase64 per call.
Logo from an ERP/CRM (PNG export)Pass branding.logoBase64 as the base64 string. Include branding.logoWidth to size it correctly.
Logo direction differs by documentPass branding.logoLayout alongside the logo string to swap sides per call.
Suppress logo for some callsNot directly supported via payload - set showLogo: false in the template, or use a separate template variant.

SVG is preferred over PNG

SVG logos render crisply at any scale and are typically 1 - 5 KB of text. PNG/JPEG logos work well but require base64 encoding (roughly 33% size overhead) and may look soft at non-native sizes. If your source system can export SVG, prefer it.


Header Examples

Title + subtitle, no logo:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "Sales Order Confirmation",
    "subtitle": "{{companyName}}",
    "textColor": "#1E293B",
    "fontSize": 20,
    "subtitleFontSize": 11,
    "alignment": "left",
    "borderStyle": "solid",
    "borderColor": "#CBD5E1",
    "borderWidth": 0.5,
    "paddingV": 8
  }
}

SVG logo baked into template (logo left, title right):

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "{{companyName}}",
    "subtitle": "Sales Order Confirmation",
    "textColor": "#1E293B",
    "showLogo": true,
    "logoType": "svg",
    "logoSvg": "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 60'>...</svg>",
    "logoWidth": 140,
    "logoLayout": "logo-left-title-right",
    "borderStyle": "solid",
    "borderColor": "#E2E8F0",
    "paddingV": 6
  }
}

Base64 PNG logo baked into template:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "ORDER CONFIRMATION",
    "subtitle": "{{general.No.}}",
    "showLogo": true,
    "logoType": "image",
    "logoBase64": "data:image/png;base64,iVBORw0KGgo...",
    "logoWidth": 140,
    "logoHeight": 52,
    "logoLayout": "logo-left-title-right",
    "borderStyle": "bottom-line",
    "borderColor": "theme.borderColor",
    "borderWidth": 0.5,
    "paddingV": 10
  }
}

Multi-tenant: template with placeholder, logo supplied per call:

Template (.vpdf or Designer):

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "ORDER CONFIRMATION",
    "subtitle": "Sales Order",
    "showLogo": true,
    "logoType": "svg",
    "logoSvg": "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'></svg>",
    "logoWidth": 160,
    "logoLayout": "logo-left-title-right"
  }
}

Payload from source system (e.g. Dynamics 365 BC):

{
  "templateId": "sales-order-v2",
  "branding": {
    "logoSvg": "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 275 52' width='275' height='52'><polygon points='0,0 18,0 30,27 42,0 60,0 30,50 0,0' fill='#1D3B8A'/><text x='68' y='23' font-family='Arial,sans-serif' font-size='18' font-weight='700' fill='#1D3B8A'>VaultTech Solutions</text><text x='68' y='40' font-family='Arial,sans-serif' font-size='11' fill='#0673BC'>Trusted. Compliant. Delivered.</text></svg>",
    "logoWidth": 185
  },
  "general": {
    "No.": "S-ORD101001",
    "Sell-to Customer Name": "Adatum Corporation"
  }
}

Multi-tenant with PNG logo from ERP export:

{
  "templateId": "sales-order-v2",
  "branding": {
    "logoBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
    "logoWidth": 160,
    "logoLayout": "logo-left-title-right"
  },
  "general": { ... }
}

Title left, subtitle right (split, no logo):

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "Acme Corporation",
    "subtitle": "Invoice #{{invoiceNumber}}",
    "titleLayout": "split",
    "textColor": "#1E293B",
    "fontSize": 16,
    "subtitleFontSize": 12,
    "borderStyle": "solid",
    "borderColor": "#CBD5E1",
    "paddingV": 8
  }
}

Themed background:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "{{documentTitle}}",
    "textColor": "theme.textOnPrimary",
    "background": "theme.primary",
    "fontSize": 18,
    "paddingV": 10
  }
}

The footer is a Designer node of type: "footer" inside layoutSchema. When present and visible is not false, it renders at the bottom of every page via the document engine's footer callback - completely outside the content flow, so it never pushes content to a new page.

PropertyTypeDefaultDescription
textstring""Left-side footer text. Supports {FIELD} tokens.
textColorstring"theme.textOnShade"Color for footer text and page number. Accepts hex or "theme.*" token.
showPageNumbersbooleantrueShow Page X of Y right-aligned in the footer. Set to false to suppress page numbers.
fontSizenumber9Font size (pt) for footer text and page numbers.
backgroundstringnoneFooter area background fill. Accepts hex or "theme.*" token.
borderStyle"solid" | "dashed" | "none""none"Style of the border line drawn above the footer.
borderColorstring"theme.borderColor"Color of the footer border line.
borderWidthnumber0.5Width (pt) of the footer border line.
paddingVnumber4Vertical padding (pt) inside the footer area.
visiblebooleantrueWhen false, no footer is rendered.

Text + page numbers:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "Confidential - Acme Corp",
    "textColor": "#6B7280",
    "showPageNumbers": true,
    "fontSize": 9,
    "borderStyle": "solid",
    "borderColor": "#E5E7EB",
    "borderWidth": 0.5,
    "paddingV": 4
  }
}

Dynamic text from payload:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "Order: {orderNumber}  |  Customer: {customerName}",
    "textColor": "#6B7280",
    "showPageNumbers": true,
    "fontSize": 8
  }
}

Themed background footer:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "{{companyName}}",
    "textColor": "theme.textOnPrimary",
    "background": "theme.primary",
    "showPageNumbers": true,
    "fontSize": 9,
    "paddingV": 6
  }
}

No footer:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "visible": false
  }
}

layoutSchema

layoutSchema is the Designer-generated schema (SchemaV2 format). When this key is present, the rendering engine uses it as the primary rendering path instead of content[].

Structure

{
  "layoutSchema": {
    "schemaVersion": 2,
    "rootId": "root-1",
    "nodes": {
      "root-1": {
        "id": "root-1",
        "type": "root",
        "children": ["header-1", "section-1", "footer-1"]
      },
      "header-1": {
        "id": "header-1",
        "type": "header",
        "props": { "title": "{{documentTitle}}" }
      },
      "section-1": {
        "id": "section-1",
        "type": "section",
        "props": { "title": "Customer Details" },
        "children": ["field-1", "field-2"]
      },
      "field-1": {
        "id": "field-1",
        "type": "field",
        "props": { "label": "Name", "path": "customerName" }
      },
      "field-2": {
        "id": "field-2",
        "type": "field",
        "props": { "label": "Account #", "path": "accountNumber" }
      },
      "footer-1": {
        "id": "footer-1",
        "type": "footer",
        "props": { "text": "Confidential", "showPageNumbers": true }
      }
    }
  }
}

Supported Node Types in layoutSchema

Node typeDescription
"root"Root container. Contains children referencing all top-level nodes in document order.
"header"Repeating page header (title, subtitle, logo). See Header.
"footer"Repeating page footer (text, page numbers). See Footer.
"section"Content section with optional title, accent color, box model, and column layout.
"layout_group"Multi-column layout container. Children are rendered as side-by-side columns.
"field"Key-value field with label and data path binding.
"text"Plain text or data-bound text block.
"table"Data-bound table with column definitions, grouping, and aggregates.
"hierarchical_table"Multi-level nested table. Delegates to the Universal Adaptive Renderer.
"spacer_separator"Visual divider or vertical space gap.
"signature"Signature/initials/date/check capture zone.

watermarkText

A runtime override for the watermark value. When present, it takes precedence over templateSettings.watermark.value.

This is the preferred way to inject dynamic watermark text from the API without re-publishing the template.

{
  "watermarkText": "DRAFT",
  "templateSettings": {
    "watermark": {
      "enabled": true,
      "type": "text",
      "opacity": 0.1,
      "rotation": -45,
      "position": "center"
    }
  }
}

sampleData

Optional object containing representative sample values for every data field in the template. Used by:

  • The Designer's live preview to render a realistic-looking document.
  • The "Prepare for Production" integrity checker (emits a warning when absent).
{
  "sampleData": {
    "documentTitle": "Sales Order Confirmation",
    "customerName": "Acme Corp",
    "orderNumber": "SO-1001",
    "orderDate": "2026-03-15",
    "salesOrders": [
      {
        "partNumber": "P-101",
        "description": "Widget Alpha",
        "qty": 5,
        "unitPrice": 49.99
      }
    ]
  }
}

Full Payload Example

A complete, minimal-but-realistic VaultPDF payload combining all top-level keys. Copy, adjust the templateId and data, and send to the render API.

{
  "templateId": "sales-order-v2",

  "metadata": {
    "version": "2.1",
    "description": "Sales order confirmation - US domestic",
    "author": "VaultPDF Team"
  },

  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#1E3A5F",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    }
  },

  "templateSettings": {
    "timezone":   "America/Chicago",
    "locale":     "en-US",
    "dateFormat": "MMM D, YYYY",
    "currency":   { "code": "USD", "symbol": "$", "position": "before" },
    "toc":        { "enabled": false },
    "watermark":  { "enabled": false }
  },

  "watermarkText": "",

  "layoutSchema": {
    "schemaVersion": 2,
    "rootId": "root-1",
    "nodes": {
      "root-1": {
        "id": "root-1",
        "type": "root",
        "children": ["header-1", "section-customer", "table-orders", "footer-1"]
      },
      "header-1": {
        "id": "header-1",
        "type": "header",
        "props": {
          "title": "Sales Order Confirmation",
          "subtitle": "{{companyName}}",
          "textColor": "#1E293B",
          "fontSize": 20,
          "borderStyle": "solid",
          "borderColor": "#CBD5E1",
          "paddingV": 8
        }
      },
      "section-customer": {
        "id": "section-customer",
        "type": "section",
        "props": { "title": "Customer Details", "showHeader": true },
        "children": ["field-name", "field-order", "field-date"]
      },
      "field-name": {
        "id": "field-name",
        "type": "field",
        "props": { "label": "Customer", "path": "customerName", "labelStyled": true }
      },
      "field-order": {
        "id": "field-order",
        "type": "field",
        "props": { "label": "Order #", "path": "orderNumber", "labelStyled": true }
      },
      "field-date": {
        "id": "field-date",
        "type": "field",
        "props": { "label": "Order Date", "path": "orderDate", "format": "date", "labelStyled": true }
      },
      "table-orders": {
        "id": "table-orders",
        "type": "hierarchical_table",
        "props": {
          "title": "Order Lines",
          "dataSource": "{{lines}}"
        }
      },
      "footer-1": {
        "id": "footer-1",
        "type": "footer",
        "props": {
          "text": "Confidential - {{companyName}}",
          "textColor": "#6B7280",
          "showPageNumbers": true,
          "fontSize": 9,
          "borderStyle": "solid",
          "borderColor": "#E5E7EB"
        }
      }
    }
  },

  "sampleData": {
    "companyName": "Acme Corp",
    "customerName": "Beta Industries",
    "orderNumber": "SO-1001",
    "orderDate": "2026-03-15",
    "lines": [
      { "partNumber": "P-101", "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99 }
    ]
  },

  "companyName": "Acme Corp",
  "customerName": "Beta Industries",
  "orderNumber": "SO-1001",
  "orderDate": "2026-03-15",
  "lines": [
    { "partNumber": "P-101", "description": "Widget Alpha", "qty": 5,  "unitPrice": 49.99 },
    { "partNumber": "P-102", "description": "Gadget Beta",  "qty": 2,  "unitPrice": 129.00 }
  ]
}

On this page