Chapter 4: Designing Pixel-Perfect PDFs
The JSONC Template Engine
After your workflow has successfully ingested data and your AI Reasoning step has structured it, it is time to generate the final document. In Strucsta, the Render step uses a declarative layout engine powered by pdfmake and written in JSONC (JSON with Comments).
Instead of wrestling with absolute X/Y coordinates or imperative drawing code, you define your document structurally. You describe the layout—headers, columns, tables, and paragraphs—and the engine handles the complex math of pagination, text wrapping, and page breaks.
Why JSONC?
Standard JSON is excellent for machine-to-machine communication, but it is notoriously difficult for humans to read and maintain as visual templates because it does not support comments.
By using JSONC, you get the predictability of JSON with the maintainability of a standard programming language. You can annotate your layouts, temporarily disable sections during testing, and keep your template organized:
{
"content": [
// --- HEADER SECTION ---
{
"text": "Monthly Executive Report",
"style": "headerTitle"
},
// The summary below is generated by the AI Reason step
{
"text": "{{executiveSummary}}",
"margin": [0, 10, 0, 20]
}
// --- TABLES SECTION ---
/* TODO: Add the financial breakdown table here
once the AI schema is updated.
*/
]
}
Injecting Dynamic Data
Because Strucsta operates on a Cumulative Context Model, the Render step receives a perfectly flat, finalized JSON state containing all original inputs and all AI-generated outputs.
To inject this data into your document, you use standard Handlebars syntax. The runtime processes the Handlebars tags before parsing the JSONC, ensuring your data is safely injected into the document definition.
- Standard Text Injection:
"text": "Prepared for: {{clientName}}" - Raw HTML/Entity Decoding: The engine automatically decodes HTML entities passed from upstream forms, so
&renders correctly as&.
The Basic Structure
A Strucsta document template consists of three primary root properties: content, styles, and defaultStyle.
Here is a complete, minimal example of a starting layout:
{
// 1. CONTENT: An array defining the flow of your document elements
"content": [
{
"text": "Invoice #{{invoiceNumber}}",
"style": "header"
},
{
"text": "Billed To: {{clientName}}",
"style": "subheader"
},
{
"text": "Thank you for your business. The summary of your AI-processed line items is below.",
"margin": [0, 15, 0, 15] // [left, top, right, bottom]
}
],
// 2. STYLES: A dictionary of reusable formatting rules
"styles": {
"header": {
"fontSize": 24,
"bold": true,
"color": "#1e293b",
"margin": [0, 0, 0, 10]
},
"subheader": {
"fontSize": 14,
"italics": true,
"color": "#64748b"
}
},
// 3. DEFAULT STYLE: Applied to all text that doesn't specify a style
"defaultStyle": {
"fontSize": 10,
"color": "#334155",
"lineHeight": 1.4
}
}
Layout Building Blocks
The underlying pdfmake engine provides powerful structural blocks to help you build complex, pixel-perfect designs. The most common blocks you will use include:
- Columns: To create side-by-side layouts (e.g., placing a logo on the left and company details on the right).
- Tables: For highly structured data with customizable borders, shading, and dynamic row heights.
- Images: Rendered via base64 strings or linked via the Strucsta Resource Manager.
- Stacks: For grouping elements together to ensure they do not break awkwardly across pages.
By keeping the layout logic strictly separated from the AI reasoning logic, the 70/30 Rule remains intact: The AI guarantees the structure of the data, and your JSONC template guarantees the pixel-perfect rendering of the brand.
