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.
Overview
The Supplementary Annex (supplementary_Annex) is a section type that appends a self-contained supporting-documentation block to a Structured Content document. For every line item that carries notes or images, it produces:
- A themed header bar - item number, description, and an optional document reference subtitle
- Installation / QC notes - one plain paragraph per note string
- A responsive image grid - downsampled to a configurable DPI for efficient PDF file sizes
The feature is controlled by a single payload flag (features.supplementaryAnnex: true) so the same template can render with or without the annex depending on the context.
Quick Start
1 - Add the node to your template .vpdf
{
"id": "supplementary-annex",
"type": "structured_content",
"props": {
"assetPath": "Documents/SupplementaryAnnex/supplementary-annex-layout.yaml",
"library": "assets"
},
"pagination": { "breakBefore": "always" }
}2 - Upload the layout YAML to SharePoint
Store the file at the path you referenced in assetPath inside your assets library.
See the full layout reference YAML below.
3 - Add the feature flag to your payload
{
"features": {
"supplementaryAnnex": true
},
"Lines": [ "..." ]
}When features.supplementaryAnnex is false or absent, the annex section is silently omitted - no placeholder is rendered, the page break is suppressed, and the TOC entry is not added.
Layout YAML Reference
The layout YAML is a StructuredDocument asset with documentType: supplementary-annex. It contains exactly one supplementary_Annex section.
Document-level fields
| Field | Type | Description |
|---|---|---|
documentType | string | Must be "supplementary-annex". |
version | string | Semantic version, e.g. "1.0.0". |
title | string | Section heading shown at the top of the annex page, e.g. "Supporting Documentation". |
sections | array | Array containing one supplementary_Annex block. |
supplementary_Annex block
sections:
- type: supplementary_Annex
data_source: "{{Lines}}"
notes_field: notes
images_field: images
id_field: "No."
name_field: Description
showDivider: false
includeInToc: true
sectionNumbering: true
item_template:
- type: sub_header
text: "Item {{item.id}} - {{item.name}}"
subtitle: "Document {{Header.No.}} | Date {{Header.Order Date|date}}"
style: variant_blue_bar
- type: repeat_notes
source: "{{item.notes}}"
style: paragraph_block
- type: image_grid
source: "{{item.images}}"
columns: 2
target_dpi: 150
image_quality: 80
show_captions: true
caption: "Documentation photo - Item {{item.id}}"Data Binding
| Property | Type | Required | Description |
|---|---|---|---|
data_source | string | Yes | Double-brace placeholder resolving to the root array in the payload. Example: "{{Lines}}". |
notes_field | string | string[] | No | Field name(s) on each item whose value is a string[] of note texts. When multiple names are given the first non-empty one wins. |
images_field | string | string[] | No | Field name(s) on each item whose value is a string[] of image URLs or relative asset paths. |
id_field | string | No | Field used as the unique identifier in headers, breadcrumbs, and annex anchors. Supports dots (e.g. "No."). |
name_field | string | No | Field used as the human-readable label in the item header. |
children_fields | string[] | No | Nested child array field names for hierarchical data. The flattener recurses into each, accumulating notes and images from all levels. |
Items with neither notes nor images are skipped entirely - they produce no output and no TOC entry.
Layout Options
| Property | Type | Default | Description |
|---|---|---|---|
showDivider | boolean | true | Renders a thin horizontal rule between consecutive items. |
includeInToc | boolean | false | When true, each qualifying item is listed in the PDF Table of Contents as a sub-section under the annex title. |
sectionNumbering | boolean | false | When true (and includeInToc: true), TOC entries are prefixed with hierarchical section numbers such as 2.1, 2.2. |
item_template Blocks
Each item is rendered by iterating the item_template array. Three block types are supported:
sub_header
Renders the themed blue primary bar for each item.
| Property | Type | Description |
|---|---|---|
text | string | Main header line. Supports {{item.id}}, {{item.name}}, {{item.contextPath}}, and any top-level payload field (e.g. {{Header.No.}}). |
subtitle | string | Second line of the header bar. Supports the same tokens plus format pipes (|date, |currency, |number). Set to "" to suppress the second line. |
style | string | Visual variant - currently variant_blue_bar. |
Variable tokens available in header templates:
| Token | Resolves to |
|---|---|
{{item.id}} | Value of id_field for this item |
{{item.name}} | Value of name_field for this item |
{{item.contextPath}} | Breadcrumb path for nested items (e.g. "Order > Line 1 > Component A") |
{{Header.No.}} | Any field on the payload root (dots and spaces supported) |
{{Header.Order Date|date}} | Payload root field formatted with a pipe filter |
repeat_notes
Renders one paragraph per string in the resolved notes array.
| Property | Type | Description |
|---|---|---|
source | string | Template expression resolving to the notes array, e.g. "{{item.notes}}". |
style | string | Paragraph style key - paragraph_block applies standard body text styling. |
image_grid
Renders a responsive N-column photo grid. Images are fetched and downsampled at render time.
| Property | Type | Default | Description |
|---|---|---|---|
source | string | - | Expression resolving to string[] of image URLs or relative asset paths. |
columns | number | 2 | Number of columns in the grid. Column width is calculated automatically from the page content width. |
target_dpi | number | 150 | Target resolution for downsampling. Lower values reduce file size; 72 is screen resolution, 300 is print quality. |
image_quality | number | 80 | JPEG compression quality (1-100). Only applies to JPEG output from Sharp. |
show_captions | boolean | false | Show a caption below each image. |
caption | string | - | Caption template. Supports {{item.id}}, {{item.name}}, etc. |
Image path formats accepted:
| Format | Example |
|---|---|
| Relative asset path | "Media/Images/photo.png" |
| Absolute HTTPS URL | "https://cdn.example.com/photo.jpg" |
| Pre-authenticated SharePoint download URL | "https://<tenant>.sharepoint.com/.../@microsoft.graph.downloadUrl" |
| Azure Blob SAS URL | "https://<account>.blob.core.windows.net/...?sv=..." |
SharePoint Site URLs
Plain SharePoint site URLs (https://<tenant>.sharepoint.com/sites/...) require authentication and cannot be fetched directly. Use the @microsoft.graph.downloadUrl value from the Graph API or a SAS URL instead.
SVG Images
Sharp automatically rasterises SVG files to PNG at render time. For most reliable results, export images to PNG before uploading them to your asset library.
Inline Suppression in the Main Table
When features.supplementaryAnnex: true, the render pipeline automatically suppresses notes and images from the main hierarchical table to avoid duplication:
- The Notes column value is replaced with a styled, clickable cross-reference: See supporting documentation - Item 0371 (clicking jumps directly to the annex section for that item).
- The Images column value is cleared so the "Images:" sub-row is hidden entirely.
This behaviour is automatic - no template changes are needed.
TOC Integration
When includeInToc: true, each qualifying annex item emits a TOC entry as a sub-section under the annex document title:
2. Supporting Documentation
2.1 Item 0371 - Push Pier, Drive Tool, Crawlspace
2.2 Item 0349 - Push Pier, Drive Tool, Standard
2.3 Item 300844 - Crock KitEach entry is a clickable internal link that jumps to the item's header in the annex. Page numbers are generated automatically.
sectionNumbering: true adds the 2.1, 2.2 ... prefix. When false, entries appear at the sub-section indent level without numbers.
Payload Structure
{
"features": {
"supplementaryAnnex": true
},
"Header": {
"No.": "SO-00123",
"Order Date": "2026-03-29"
},
"Lines": [
{
"No.": "0371",
"Description": "Push Pier - Drive Tool, Crawlspace, Galv., Shorty",
"Type": "Item",
"Quantity": 2,
"notes": [
"Install per engineered drawings Rev B.",
"Torque to 2,500 ft-lb minimum at each pier location."
],
"images": [
"Media/Images/push-pier-crawlspace-install.png",
"Media/Images/push-pier-crawlspace-detail.png"
]
},
{
"No.": "0349",
"Description": "Push Pier - Drive Tool, Standard, 19\", Galv.",
"Type": "Item",
"Quantity": 2,
"notes": [
"Verify bearing stratum before terminating."
],
"images": []
},
{
"No.": "300844",
"Description": "Crock Kit - Red Basin, Gray Lid, Small",
"Type": "Item",
"Quantity": 40,
"notes": [],
"images": []
}
]
}Items 0349 and 300844 have empty notes and images arrays - they are silently skipped by the annex renderer and produce no output.
Page Break Behaviour
Add "pagination": { "breakBefore": "always" } to the structured_content node in your template to force the annex onto a new page:
{
"id": "supplementary-annex",
"type": "structured_content",
"props": {
"assetPath": "Documents/SupplementaryAnnex/supplementary-annex-layout.yaml",
"library": "assets"
},
"pagination": { "breakBefore": "always" }
}Each item header and its notes block are kept together (unbreakable) so a header bar is never stranded at the bottom of a page without its content.
templateSettings Integration
The annex honours all active templateSettings - date formatting, locale, currency, and section numbering are applied consistently with the rest of the document.
{
"templateSettings": {
"dateFormat": "DD MMM YYYY",
"locale": "en-AU",
"toc": { "enabled": true },
"sectionNumbering": true,
"supplementaryAnnex": {
"titleIcon": "file-text"
}
}
}templateSettings key | Type | Description |
|---|---|---|
toc.enabled | boolean | Master switch for the PDF Table of Contents. includeInToc in the YAML has no effect unless this is true. |
sectionNumbering | boolean | Applies document-wide section numbers. The annex sub-entries inherit the parent section's number automatically. |
supplementaryAnnex.titleIcon | string | Icon key displayed beside the annex title bar (e.g. "file-text", "clipboard"). |
Feature Flag Reference
The features key lives at the root of the payload:
{
"features": {
"supplementaryAnnex": true
}
}| Value | Effect |
|---|---|
true | Annex is rendered, inline suppression active, TOC entries added |
false or absent | Annex section entirely omitted, no page break, no TOC entries |
Related Pages
- Structured Content - the
structured_contentnode that hosts a supplementary annex layout - Template Settings -
toc,sectionNumbering, and locale options - Hierarchical Table - the main data table whose Notes/Images columns are suppressed when the annex is active
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.
Template Settings
Reference for templateSettings in VaultPDF. Controls locale, date/time formatting, number and currency display, boolean labels, section numbering, Table of Contents, watermarks, and security.