Structured Content
Author rich legal, policy, or compliance documents in YAML or JSON and embed them anywhere in a VaultPDF template. At render time, the VaultPDF engine fetches the StructuredDocument asset and injects its fully-typed blocks directly into the PDF output. Also hosts the supplementary_Annex section type for per-line-item supporting documentation.
Overview
A Structured Content node embeds a separately-authored document (stored as a YAML or JSON asset) directly inside a VaultPDF template. Instead of building long-form text sections (terms and conditions, service agreements, policy clauses) inside the Designer, you write them once as a StructuredDocument asset file and reference it from one or many templates.
When a document is generated, the VaultPDF engine pre-fetches the asset before beginning layout composition. The document is then converted to layout blocks and injected in place of the node. All theme colours, TOC integration, and section numbering are applied automatically.
In addition to standard document sections, a structured_content node can host a supplementary_Annex section - a specialised block that appends per-line-item supporting documentation (notes and photo grids) to the end of any VaultPDF output.
Node Configuration
Add a structured_content node to your layoutSchema:
{
"id": "node_terms",
"type": "structured_content",
"props": {
"assetPath": "Documents/policies/terms-and-conditions.yaml",
"library": "assets",
"conditionContext": {
"isUK": true,
"tier": "enterprise"
}
}
}| Property | Type | Required | Description |
|---|---|---|---|
assetPath | string | Yes | Path to the YAML or JSON asset within the configured storage library. |
library | string | No | Storage library to read from. Default: "assets". |
conditionContext | object | No | Key/value pairs forwarded to each block's condition evaluator. |
visible | boolean | No | When false, the node is completely skipped and no content is rendered. |
StructuredDocument Format
The asset file (YAML or JSON) must conform to the StructuredDocument shape.
Required Fields
| Field | Type | Description |
|---|---|---|
documentType | string | Logical document category identifier, e.g. "terms-and-conditions" or "master-services-agreement". |
version | string | Semantic version string, e.g. "2.1.0". |
title | string | Document title rendered as the level-1 heading (and TOC root entry when TOC is enabled). |
sections | ContentBlock[] | Ordered array of content blocks that make up the document body. |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
region | string | Metadata tag, e.g. "UK" or "US". Not rendered; useful for asset management. | |
effectiveDate | string | ISO date string. Not rendered directly but available to conditionContext expressions as needed. | |
tocMode | "flat" | "nested" | "flat" | Controls how headings appear in the document TOC. "flat" includes only level-1 headings; "nested" includes levels 1 and 2 with indentation. |
Minimal YAML Example
documentType: terms-and-conditions
version: "1.0.0"
title: Terms and Conditions
sections:
- type: heading
text: Acceptance of Terms
level: 1
- type: paragraph
text: >
By accessing this service you agree to be bound by these terms.
Please read them carefully before proceeding.
- type: heading
text: Changes to Terms
level: 1
- type: paragraph
text: >
We reserve the right to modify these terms at any time.
Continued use of the service constitutes acceptance.Content Blocks
Every item in sections is a typed block. The type field selects the block renderer.
heading
Renders a styled section heading. Three depth levels are supported.
| Property | Type | Default | Description |
|---|---|---|---|
text | string | Heading text. Supports inline formatting markers. | |
level | 1 | 2 | 3 | 1 | Depth. Level 1 = 18 pt primary color; level 2 = 15 pt secondary; level 3 = 13 pt border color. |
includeInToc | boolean | Override TOC inclusion. true = always include; false = always exclude; omit = auto (level 1 in flat mode; levels 1-2 in nested mode). |
- type: heading
text: "Liability Limitations"
level: 1
- type: heading
text: "Indirect Damages"
level: 2
includeInToc: falseparagraph
Renders a block of body text.
| Property | Type | Description |
|---|---|---|
text | string | Body text. Supports inline formatting. Use YAML > (folded) or ` |
- type: paragraph
text: >
This agreement is governed by the laws of England and Wales.
Any disputes shall be resolved in the courts of London.
# Literal multi-line (preserves newlines as visible line breaks)
- type: paragraph
text: |
Line one.
Line two indented.
Further indented line.list
Renders a bulleted or numbered list.
| Property | Type | Description |
|---|---|---|
style | "bullet" | "ordered" | "bullet" = unordered; "ordered" = numbered. |
items | string[] | List item strings. Each item supports inline formatting. |
- type: list
style: bullet
items:
- Full **24/7** support access
- Dedicated account manager
- _Priority_ response SLA
- type: list
style: ordered
items:
- Submit a written notice to the registered address.
- Allow 30 days for acknowledgement.
- Escalate to arbitration if unresolved.note
Renders a styled callout box with an icon, accent stripe, and tinted background. Suitable for warnings, disclaimers, or informational asides.
| Property | Type | Default | Description |
|---|---|---|---|
text | string | Body text. Supports inline formatting. | |
variant | "info" | "warning" | "error" | "success" | "important" | "neutral" | "neutral" | Sets the accent colour, background tint, and icon. |
label | string | Capitalised variant name | Bold prefix rendered before the note body. |
Variant Reference
| Variant | Colour | Icon |
|---|---|---|
info | Blue | info |
warning | Amber | warning |
error | Red | x |
success | Green | check |
important | Red | circle-alert |
neutral | Secondary | info |
- type: note
variant: warning
text: >
Failure to comply with the data retention schedule may result in
regulatory penalties under applicable data protection law.
- type: note
variant: info
label: "Reminder"
text: "Renew your subscription **30 days** before expiry to avoid service interruption."clause
Renders a numbered legal clause with an auto-assigned clause number (section.clause). Clause numbers increment automatically within each level-1 heading section.
| Property | Type | Description |
|---|---|---|
text | string | Clause body text. Supports inline formatting and {{var}} substitution. |
title | string | Optional bold title prefixed before the clause body, e.g. "Confidentiality". |
subclauses | SubClause[] | Up to one nesting level. Each sub-clause gets a section.clause.subclause number. |
SubClause shape
| Property | Type | Description |
|---|---|---|
text | string | Sub-clause text. Supports inline formatting. |
condition | string | Condition key or expression. Sub-clause is skipped when falsy. |
- type: heading
text: Confidentiality
level: 1
- type: clause
title: Definition
text: >
"Confidential Information" means any information disclosed by one party
to the other that is designated as confidential or that reasonably should
be understood to be confidential.
- type: clause
title: Obligations
text: >
Each party agrees to hold the other's Confidential Information
in strict confidence and not to disclose it to any third party.
subclauses:
- text: Not to copy or reproduce Confidential Information without prior consent.
- text: To use the same degree of care as it uses for its own confidential information.
- text: To limit access to personnel with a need to know.
condition: isEnterprisesignature_block
Renders one or more signature slots in a table layout. Compatible with e-signature platform anchor tokens (DocuSign, Adobe Sign, etc.).
| Property | Type | Default | Description |
|---|---|---|---|
title | string | Optional heading displayed above the signature table. | |
columns | 1 | 2 | 3 | Auto (from signatory count, max 3) | Number of signature columns per row. |
signatories | Signatory[] | Single blank slot | Explicit list of signatories. When omitted, a single auto-generated slot is used. |
includeName | boolean | true | Show a printed-name field in the auto-generated slot. |
includeDate | boolean | true | Show a date field in the auto-generated slot. |
Signatory shape
| Property | Type | Description |
|---|---|---|
name | string | Pre-filled printed name. Omit for a blank signature line. |
role | string | Role label displayed above the signature line (e.g. "Authorized Signatory"). Also used to generate the e-sign anchor token [[SIGN_AUTHORIZED_SIGNATORY|required]]. |
date | string | Pre-filled date string. Omit for a blank date field. |
# Simple auto-generated single slot
- type: signature_block
title: Authorization
includeName: true
includeDate: true
# Multi-signatory with two columns
- type: signature_block
title: Agreed by both parties
columns: 2
signatories:
- role: Customer Representative
- role: VaultPDF Account Manager
name: Jane Smith
date: "2026-03-28"checkbox
Renders a checkbox icon followed by a label. Useful for acknowledgement lists and form-like documents.
| Property | Type | Default | Description |
|---|---|---|---|
label | string | Text displayed beside the checkbox. Supports inline formatting. | |
checked | boolean | false | Renders the checkbox in the checked (filled) state when true. |
- type: checkbox
label: "I have read and understood the **Privacy Policy**."
checked: false
- type: checkbox
label: "I consent to receiving email communications."
checked: trueradio
Renders a radio-button icon followed by a label. Use multiple radio blocks with the same group value to represent an option set.
| Property | Type | Default | Description |
|---|---|---|---|
label | string | Text displayed beside the radio button. Supports inline formatting. | |
selected | boolean | false | Renders the radio in the selected (filled) state when true. |
group | string | Semantic group identifier. Metadata only and not rendered. |
- type: radio
label: Standard plan
group: plan
selected: false
- type: radio
label: "**Enterprise** plan (includes SLA)"
group: plan
selected: truepage_break
Inserts a hard page break. Subsequent blocks start at the top of a new page.
- type: page_breakInline Formatting
All text-bearing blocks (paragraph, heading, list items, clause, note, checkbox, radio) support inline formatting markers.
| Syntax | Effect |
|---|---|
**bold** | Bold text |
_italic_ | Italic text |
__underline__ | Underlined text |
==highlight== | Highlighted text (theme-tinted background) |
{{section:Heading Text}} | Cross-reference link to a heading with matching text |
Markers do not nest. Unmatched open markers are treated as plain text.
Variable Substitution
Use {{varName}} or {{dot.path}} placeholders in any text field. At render time these are replaced with matching values from conditionContext (or the merged context from the payload).
- type: paragraph
text: >
This agreement is entered into by **{{customerName}}**
(the "Customer") and VaultPDF on {{effectiveDate}}.
- type: clause
text: >
The agreed monthly fee is {{pricing.monthlyFee}} per seat,
billed on the {{billing.dayOfMonth}}th of each month.Substitution is resolved from the merged context in priority order:
- Raw payload fields (lowest priority)
conditionContextset innode.propsconditionContextfrompayloadData.conditionContext(global override)payloadData.structuredContentOverrides[nodeId].conditionContext(per-node, highest priority)
Field Names with Dots or Spaces
The substitution engine uses greedy longest-match, so field names containing dots (.) or spaces are supported without any escaping:
- type: paragraph
text: "Order {{Header.No.}} raised on {{Header.Order Date}}."{{Header.No.}} resolves the literal key "No." on Header, and {{Header.Order Date}} resolves the key "Order Date" - neither requires quoting or encoding in the template.
Pipe Filters
Append a pipe filter to a placeholder to format its value at render time:
- type: paragraph
text: "Effective {{effectiveDate|date}} - total {{summary.amount|currency}} for {{summary.count|number}} items."| Filter | Effect |
|---|---|
|date | Formats an ISO 8601 date string using templateSettings.dateFormat (default "DD MMM YYYY"). |
|currency | Formats a number as a locale-aware currency string using templateSettings.locale and templateSettings.currency. |
|number | Formats a number with locale-appropriate thousands separators and decimal notation. |
ISO 8601 Auto-detection
Date fields that contain a valid ISO 8601 string (e.g. "2026-03-29" or "2026-03-29T00:00:00Z") are auto-detected by the |date filter - no inputDateFormat configuration is required.
Conditional Blocks
Any block can carry a condition field. The block is skipped entirely when the condition evaluates to falsy.
- type: note
variant: warning
condition: isUK
text: "This section applies exclusively to customers domiciled in the United Kingdom."
- type: clause
condition: "pricing.monthlyFee > 5000"
title: Enterprise Discount
text: "Customers with a monthly fee exceeding £5,000 qualify for the enterprise discount programme."Condition Forms
| Form | Example | Behaviour |
|---|---|---|
| Simple key | isUK | Truthy when context.isUK is truthy |
| Dot path | customer.isPremium | Resolves nested object paths |
| Comparison | "summary.total > 10000" | Numeric comparison (>, <, >=, <=, ===, !==) |
| String match | "tier == enterprise" | Loose equality against a string literal |
YAML Quoting
YAML values containing > or < must be quoted: condition: "summary.total > 5000".
Unquoted > in YAML is a block scalar indicator and will produce unexpected results.
Payload-Level Overrides
Without modifying the .vpdf template, you can control individual structured_content nodes from the render payload.
Global context override
Applies to all structured_content nodes in the document:
{
"templateId": "service-agreement-v2",
"conditionContext": {
"isUK": true,
"tier": "enterprise"
},
"customerName": "Acme Corp"
}Per-node override (by node id)
Targets a specific node and takes highest priority:
{
"templateId": "service-agreement-v2",
"structuredContentOverrides": {
"node_terms": {
"visible": false
},
"node_dpa": {
"conditionContext": {
"isGDPR": true
}
}
}
}| Override Key | Type | Description |
|---|---|---|
visible | boolean | false hides the node entirely. true clears a template-level visible: false. |
conditionContext | object | Merged at the highest priority into the node's condition evaluator context. |
TOC Integration
When templateSettings.toc.enabled is true, heading blocks from structured_content nodes are automatically merged into the document-level Table of Contents.
- Flat mode (
tocMode: "flat"or default): only level-1 headings appear as TOC entries. - Nested mode (
tocMode: "nested"): level-1 headings are parents; level-2 headings are indented children.
includeInToc: false on an individual heading excludes it regardless of mode.
When a structured_content node hosts a supplementary_Annex section with includeInToc: true, each qualifying line item emits a TOC sub-entry that is merged into the same document TOC at the correct depth. These entries appear as children of the annex title heading and inherit the active sectionNumbering prefix (e.g. 2.1, 2.2).
Section Numbering
When templateSettings.sectionNumbering is true, level-1 headings inside structured_content blocks receive auto-incrementing ordinal prefixes (1., 2., 3.) that are continuous with the rest of the document's section counter.
Pagination
Pagination hints from the surrounding node are respected:
pagination setting | Effect |
|---|---|
breakBefore: "always" | Forces a page break before the structured content block. |
breakBefore: "whenOverflow" | Behaves the same as always for layout purposes. |
breakAfter: "always" | Forces a page break after the block. |
keepTogether: true | Marks the entire block as unbreakable and tries to keep it on one page. |
Designer Preview
In the Designer (which has no asset access), the node renders a visible grey placeholder:
[Structured content: Documents/policies/terms-and-conditions.yaml]If pre-fetching fails at render time, a red error message is shown instead:
[Structured content error: Documents/policies/terms-and-conditions.yaml]
HTTP 404: The specified resource does not exist.Full Document Example
A complete master-services-agreement.yaml illustrating all block types:
documentType: master-services-agreement
version: "3.0.0"
title: Master Services Agreement
region: UK
effectiveDate: "2026-01-01"
tocMode: nested
sections:
# Section 1
- type: heading
text: Definitions
level: 1
- type: paragraph
text: >
In this Agreement the following terms shall have the meanings set out below.
All other capitalised terms are defined where they first appear.
- type: clause
title: Agreement
text: >
Means this Master Services Agreement, including all Schedules and
Order Forms incorporated by reference.
- type: clause
title: Confidential Information
text: >
Means any information disclosed in connection with this Agreement that
is designated confidential or that a reasonable person would consider
confidential given the circumstances of disclosure.
# Section 2
- type: heading
text: Services
level: 1
- type: heading
text: Scope of Services
level: 2
- type: paragraph
text: >
VaultPDF shall provide the services set out in each Order Form
executed under this Agreement (**"Services"**).
- type: note
variant: info
text: >
Service specifications, SLAs, and pricing are defined in the relevant
Order Form and Schedule A attached hereto.
# Section 3 (conditional)
- type: heading
text: Data Protection (UK/EU)
level: 1
condition: isGDPR
- type: paragraph
condition: isGDPR
text: >
The parties agree to comply with the UK GDPR and any applicable
successor legislation in respect of all personal data processed
under this Agreement.
- type: note
variant: warning
condition: isGDPR
text: >
A Data Processing Addendum (**DPA**) must be signed separately before
any personal data is transferred between the parties.
# Section 4
- type: heading
text: Fees and Payment
level: 1
- type: clause
title: Fees
text: >
The Customer shall pay the fees set out in the applicable Order Form.
The monthly fee of **{{pricing.monthlyFee}}** per seat is invoiced
in advance on the first business day of each calendar month.
subclauses:
- text: All fees are exclusive of VAT and other applicable taxes.
- text: "Enterprise customers (>£5,000/month) receive a 5% volume discount."
condition: "pricing.monthlyFee > 5000"
# Acknowledgement
- type: heading
text: Acceptance
level: 1
- type: paragraph
text: >
By executing this Agreement the parties confirm they have read,
understood, and agree to be bound by all terms herein.
- type: checkbox
label: "Customer has received and reviewed Schedule A (Service Specifications)."
checked: false
- type: checkbox
label: "Customer has received and reviewed Schedule B (Data Processing Addendum)."
condition: isGDPR
checked: false
- type: page_break
- type: signature_block
title: Signatures
columns: 2
signatories:
- role: Customer Representative
- role: VaultPDF Authorized SignatoryRelated Pages
- Supplementary Annex - per-line-item supporting documentation section hosted inside a
structured_contentnode - Template Settings -
toc,sectionNumbering,dateFormat, and locale options that affect structured content rendering - Hierarchical Table - the main data table whose Notes/Images columns are suppressed when a supplementary annex is active
Icon Reference
Complete reference of valid icon names available for use in VaultPDF documents. Includes status, information, content, system, and form control icons.
Supplementary Annex
Generate a per-line-item supporting documentation section at the end of any VaultPDF output. The supplementary_Annex block flattens hierarchical order-line data, fetches and downsamples images, and renders a themed header, notes, and photo grid for every qualifying item - all gated behind a single feature flag.