Template Components
A comprehensive guide to all available components in document templates (PDF and Excel).
Table of Contents
- Overview
- Component Categories
- Template Type Support
- Layout Components
- Content Components
- Data Components
- Interactive Components
- Advanced Components
- Best Practices
- Complete Examples
Overview
Templates are built using a component-based architecture. Each component represents a visual or functional element in your document. Components can be simple (like text or images) or complex (like tables with calculations or conditional sections).
Key Concepts
Component Structure: Every component has:
id(string, required): Unique identifiertype(string, required): Component type (e.g., "text", "button", "table")props(object, optional): Component properties and configurationchildren(array, optional): Nested child componentscontent(string, optional): Text content for some components
Template Types: Components can be used in:
- PDF templates: Rendered as PDF documents
- Excel templates: Rendered as Excel spreadsheets
- Both: Works in both template types
Variable Support: Most components support Handlebars syntax {{variableName}} for dynamic content.
Component Categories
Layout Components
Structure and organize other components:
- Container - Wrapper with background, padding, and styling
- Columns - Multi-column layouts (2-4 columns)
- Table Layout - Grid-based layout system
- Divider - Horizontal separator line
- Spacer - Vertical spacing control
Content Components
Display text, images, and static content:
- Text - Simple paragraph text
- Heading - Headings (H1-H6)
- Rich Text - Formatted HTML content
- Image - Images with responsive sizing
- List - Ordered and unordered lists
- SVG - Externally-generated SVG graphics (charts, barcodes, diagrams)
Data Components
Display and manipulate data:
- Table - Data tables with 5 column types
- Chart - Visualizations (PDF + Excel)
- Loop - Repeat content for arrays
- Conditional - Show/hide based on conditions
Interactive Components
PDF-specific interactive elements:
- Button - Call-to-action buttons (links in PDFs)
- QR Code - QR codes for tickets, URLs, etc.
Template Type Support
| Component | Excel | Notes | |
|---|---|---|---|
| Rich Text | ✅ | ✅ | Primary text component (recommended) |
| Text | ✅ | ✅ | Basic text (deprecated - use Rich Text) |
| Heading | ✅ | ✅ | H1-H6 headings (deprecated - use Rich Text) |
| Button | ✅ | ❌ | PDF only (clickable links) |
| Image | ✅ | ✅ | Responsive images |
| Container | ✅ | ✅ | Layout wrapper |
| Columns | ✅ | ✅ | Multi-column layouts |
| List | ✅ | ✅ | Ordered/unordered lists |
| Table | ✅ | ✅ | Data tables |
| Table Layout | ✅ | ✅ | Grid layout |
| Divider | ✅ | ✅ | Horizontal line |
| Spacer | ✅ | ✅ | Vertical spacing |
| Chart | ✅ | ✅ | Data visualizations (rendered images in PDFs, native in Excel) |
| Loop | ✅ | ✅ | Iterate over arrays |
| Conditional | ✅ | ✅ | Conditional rendering |
| QR Code | ✅ | ❌ | PDF only (scannable codes) |
| Barcode | ✅ | ❌ | PDF only (Code128, EAN, UPC, etc.) |
| SVG | ✅ | ✅ | Externally-generated SVG graphics |
The text and heading components are deprecated. Use rich-text instead for all text content.
Layout Components
Container
Wrapper component with background, padding, and styling. Use to group and style related content.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
backgroundColor | string | No | transparent | Background color (hex, rgb, rgba, named) |
padding | string | No | "0px" | CSS padding value (e.g., "20px", "10px 20px") |
maxWidth | string | No | none | Maximum width (e.g., "600px", "100%") |
borderRadius | string | No | "0px" | Border radius (e.g., "8px", "50%") |
border | string | No | none | CSS border value (e.g., "1px solid #000") |
align | enum | No | left | Alignment: "left", "center", "right" |
margin | string | No | "0px" | CSS margin value |
children | array | No | [] | Child components |
Example
{
"type": "container",
"id": "welcome-section",
"props": {
"backgroundColor": "#f8f9fa",
"padding": "40px 20px",
"maxWidth": "600px",
"borderRadius": "8px",
"align": "center"
},
"children": [
{
"type": "heading",
"id": "welcome-heading",
"props": { "level": 1 },
"content": "Welcome {{userName}}!",
"style": { "textAlign": "center" }
},
{
"type": "text",
"id": "welcome-text",
"content": "Thanks for joining us. Your account is ready.",
"style": { "textAlign": "center" }
}
]
}
Use Cases
- Group related content with consistent styling
- Create card-like sections in documents
- Add background colors to highlight sections
- Control maximum width for better readability
Columns
Multi-column layout component for side-by-side content (2-4 columns).
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
columnCount | number | No | 2 | Number of columns (1-4) |
gap | string/number | No | "20px" | Gap between columns |
columnWidths | array | No | equal | Array of width values (e.g., ["50%", "50%"]) |
backgroundColor | string | No | transparent | Background color |
padding | string | No | "0px" | CSS padding value |
verticalAlign | enum | No | top | Alignment: "top", "middle", "bottom" |
stackOnMobile | boolean | No | true | Stack columns on small screens |
children | array | No | [] | Child components (one per column) |
Example
{
"type": "columns",
"id": "feature-columns",
"props": {
"columnCount": 3,
"gap": "20px",
"stackOnMobile": true
},
"children": [
{
"type": "container",
"id": "feature-1",
"props": { "padding": "20px", "align": "center" },
"children": [
{
"type": "image",
"id": "icon-1",
"props": {
"source": "https://example.com/icon1.png",
"width": 64,
"height": 64,
"alignment": "center"
}
},
{
"type": "heading",
"id": "title-1",
"props": { "level": 3 },
"content": "Fast Delivery",
"style": { "textAlign": "center" }
},
{
"type": "text",
"id": "desc-1",
"content": "Same-day shipping available",
"style": { "textAlign": "center" }
}
]
},
{
"type": "container",
"id": "feature-2",
"props": { "padding": "20px", "align": "center" },
"children": [
{
"type": "image",
"id": "icon-2",
"props": {
"source": "https://example.com/icon2.png",
"width": 64,
"height": 64,
"alignment": "center"
}
},
{
"type": "heading",
"id": "title-2",
"props": { "level": 3 },
"content": "Secure Payment",
"style": { "textAlign": "center" }
},
{
"type": "text",
"id": "desc-2",
"content": "SSL encrypted checkout",
"style": { "textAlign": "center" }
}
]
},
{
"type": "container",
"id": "feature-3",
"props": { "padding": "20px", "align": "center" },
"children": [
{
"type": "image",
"id": "icon-3",
"props": {
"source": "https://example.com/icon3.png",
"width": 64,
"height": 64,
"alignment": "center"
}
},
{
"type": "heading",
"id": "title-3",
"props": { "level": 3 },
"content": "24/7 Support",
"style": { "textAlign": "center" }
},
{
"type": "text",
"id": "desc-3",
"content": "Always here to help",
"style": { "textAlign": "center" }
}
]
}
]
}
Use Cases
- Feature lists with icons
- Side-by-side product comparisons
- Contact information with labels and values
- Multi-column layouts in newsletters
Table Layout
Grid-based layout component (different from data tables). Creates a fixed grid for positioning components.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
rows | number | No | 1 | Number of rows (1-20) |
cols | number | No | 1 | Number of columns (1-10) |
borderWidth | string | No | "0px" | Border width (e.g., "1px") |
borderColor | string | No | #000000 | Border color |
cellPadding | string | No | "0px" | CSS padding for each cell |
cellBackgroundColor | string | No | transparent | Background color for cells |
cellAlign | enum | No | left | Cell alignment: "left", "center", "right" |
cellVerticalAlign | enum | No | top | Vertical alignment: "top", "middle", "bottom" |
borderCollapse | boolean | No | true | Collapse borders between cells |
width | string | No | 100% | Table width |
children | array | No | [] | Child components (one per cell) |
Example
{
"type": "table-layout",
"id": "info-grid",
"props": {
"rows": 2,
"cols": 2,
"borderWidth": "1px",
"borderColor": "#e0e0e0",
"cellPadding": "10px",
"width": "100%"
},
"children": [
{
"type": "text",
"id": "label-1",
"content": "Order Number:",
"style": { "fontWeight": "bold" }
},
{
"type": "text",
"id": "value-1",
"content": "{{orderNumber}}"
},
{
"type": "text",
"id": "label-2",
"content": "Order Date:",
"style": { "fontWeight": "bold" }
},
{
"type": "text",
"id": "value-2",
"content": "{{orderDate}}"
}
]
}
Use Cases
- Form-like layouts (label + value pairs)
- Invoice headers with structured data
- Fixed grid positioning for components
- Simple data displays without table headers
Divider
Horizontal separator line for visual separation.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
style | enum | No | solid | Line style: "solid", "dashed", "dotted" |
thickness | number | No | 1 | Line thickness in pixels (1-10) |
color | string | No | #e0e0e0 | Line color |
width | string | No | 100% | Divider width (e.g., "80%", "600px") |
margin | string | No | 20px 0 | CSS margin value |
Example
{
"type": "divider",
"id": "section-divider",
"props": {
"style": "solid",
"thickness": 2,
"color": "#cccccc",
"width": "80%",
"margin": "30px 0"
}
}
Use Cases
- Separate sections in documents
- Visual breaks between content blocks
- Footer separators
- Section headers
Spacer
Vertical spacing component for controlling whitespace.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
height | string/number | No | 20px | Vertical spacing (e.g., "40px", 60) |
Example
{
"type": "spacer",
"id": "section-spacing",
"props": {
"height": "40px"
}
}
Use Cases
- Add vertical spacing between sections
- Control whitespace in layouts
- Improve readability with breathing room
- Consistent spacing throughout template
Content Components
Text
Simple paragraph text component for body content.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
content | string | Yes | - | Text content (supports {{variables}}) |
style | object | No | - | Styling options |
style.fontSize | number | No | 16 | Font size (6-72) |
style.fontWeight | string/number | No | normal | Weight: "normal", "bold", "bolder", "lighter", 100-900 |
style.color | string | No | #000000 | Text color |
style.backgroundColor | string | No | transparent | Background color |
style.textAlign | enum | No | left | Alignment: "left", "center", "right", "justify" |
style.lineHeight | string/number | No | 1.5 | Line height |
position | object | No | - | Position in attachment (x, y coordinates) |
Example
{
"type": "text",
"id": "intro-text",
"content": "Hello {{userName}}, your order #{{orderNumber}} has been confirmed!",
"style": {
"fontSize": 16,
"color": "#333333",
"textAlign": "left",
"lineHeight": 1.6
}
}
Use Cases
- Body paragraphs
- Descriptions
- Explanatory text
- Dynamic content with variables
Heading
Heading component for section titles (H1-H6).
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
content | string | Yes | - | Heading text (supports {{variables}}) |
level | number | Yes | 1 | Heading level (1-6) |
style | object | No | - | Styling options (same as Text) |
position | object | No | - | Position in attachment (x, y coordinates) |
Example
{
"type": "heading",
"id": "page-title",
"props": {
"level": 1
},
"content": "Order Confirmation",
"style": {
"fontSize": 32,
"fontWeight": "bold",
"color": "#007bff",
"textAlign": "center"
}
}
Use Cases
- Page titles
- Section headings
- Document title headings
- Hierarchical content structure
Rich Text
Enhanced text component with HTML formatting support.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
content | string | No | "" | HTML content |
props | object | No | - | Styling options |
props.align | enum | No | left | Alignment: "left", "center", "right", "justify" |
props.color | string | No | #000000 | Text color |
props.backgroundColor | string | No | transparent | Background color |
props.fontSize | string/number | No | 16px | Font size (8-72 or CSS value) |
props.lineHeight | string/number | No | 1.5 | Line height |
props.padding | string | No | 0px | CSS padding value |
props.maxWidth | string | No | none | Maximum width |
Example
{
"type": "rich-text",
"id": "formatted-content",
"content": "<p>Your order includes:</p><ul><li><strong>Premium Plan</strong> - $99/month</li><li>24/7 Support</li><li>Unlimited API calls</li></ul>",
"props": {
"align": "left",
"fontSize": "16px",
"padding": "20px"
}
}
Use Cases
- Complex formatted content
- Lists with formatting
- Mixed content (bold, italic, links)
- Pre-formatted HTML sections
Image
Responsive image component for displaying images.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
source | string | Yes | - | Image URL or data URI (supports {{variables}}) |
alt | string | No | "" | Alt text for accessibility |
width | number/string | No | auto | Image width (pixels or CSS value, max 2000) |
height | number/string | No | auto | Image height (pixels or CSS value, max 2000) |
alignment | enum | No | left | Alignment: "left", "center", "right" |
position | object | No | - | Position (attachment): x and y coordinates |
style | object | No | - | Additional styling |
Example
{
"type": "image",
"id": "product-image",
"props": {
"source": "{{productImageUrl}}",
"alt": "{{productName}}",
"width": 400,
"height": 300,
"alignment": "center"
}
}
Use Cases
- Product images
- Logos and branding
- Illustrations
- User avatars
- Dynamic images from variables
List
Ordered or unordered list component.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
items | array | No | [] | Array of list items (strings, max 100) |
ordered | boolean | No | false | True for ordered list, false for unordered |
listStyleType | enum | No | disc/decimal | List style: "disc", "circle", "square" (unordered), "decimal", "lower-alpha", etc. (ordered) |
color | string | No | #000000 | Text color |
backgroundColor | string | No | transparent | Background color |
fontSize | string/number | No | 16px | Font size (8-72 or CSS value) |
lineHeight | string/number | No | 1.5 | Line height (0.5-3) |
padding | string | No | 0px | CSS padding value |
margin | string | No | 0px | CSS margin value |
itemSpacing | string/number | No | 8px | Spacing between items (0-50) |
indent | string/number | No | 20px | List indentation (0-100) |
Example
{
"type": "list",
"id": "feature-list",
"props": {
"ordered": false,
"listStyleType": "disc",
"items": [
"Free shipping on all orders",
"30-day money-back guarantee",
"24/7 customer support",
"Lifetime warranty"
],
"color": "#333333",
"fontSize": 16,
"itemSpacing": "12px"
}
}
Use Cases
- Feature lists
- Benefit lists
- Instructions or steps
- Table of contents
- Bullet points
SVG
Embed externally-generated SVG graphics from any programming language. Use Python, R, Go, Node.js, or any tool that can produce SVG to create custom charts, barcodes, diagrams, and more.
Template Support: Both PDF and Excel templates
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
content | string | Yes | - | SVG markup or variable reference (supports {{variables}}) |
encoding | enum | No | raw | "raw" for plain SVG, "base64" for encoded SVG |
width | number/string | No | 200 | Width (pixels or percentage, e.g., "100%", 400) |
height | number/string | No | 150 | Height (pixels or percentage) |
align | enum | No | left | Alignment: "left", "center", "right" |
preserveAspectRatio | string | No | - | SVG preserveAspectRatio attribute (e.g., "xMidYMid meet") |
Example - Basic SVG
{
"type": "svg",
"id": "custom-diagram",
"props": {
"content": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 200 100\"><rect x=\"10\" y=\"10\" width=\"80\" height=\"80\" fill=\"#007bff\"/><circle cx=\"150\" cy=\"50\" r=\"40\" fill=\"#28a745\"/></svg>",
"width": 200,
"height": 100,
"align": "center"
}
}
Example - Dynamic SVG from Variable
The recommended approach is to generate the SVG externally and pass it as a variable:
{
"type": "svg",
"id": "python-chart",
"props": {
"content": "{{chartSvg}}",
"encoding": "base64",
"width": 600,
"height": 400,
"align": "center"
}
}
Then pass the SVG when generating the document:
// Node.js example
const chartSvg = Buffer.from(svgString).toString('base64');
await client.documents.generate({
templateId: 'my-template',
variables: {
chartSvg: chartSvg
}
});
# Python example
import base64
chart_svg = base64.b64encode(svg_string.encode()).decode()
client.documents.generate(
template_id="my-template",
variables={"chartSvg": chart_svg}
)
Base64 Encoding
Use base64 encoding for SVGs with special characters, unicode, or complex content:
{
"type": "svg",
"id": "encoded-svg",
"props": {
"content": "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSIjMDA3YmZmIi8+PC9zdmc+",
"encoding": "base64",
"width": 100,
"height": 100
}
}
Security
SVG content is automatically sanitized to prevent security vulnerabilities:
Elements Removed:
<script>tags<foreignObject>elements- Event handlers (onclick, onload, etc.)
- External URL references
Allowed Image Sources in SVG:
- Base64 data URIs:
data:image/png;base64,... - Rynko assets:
assets://asset_id(references your uploaded assets) - Internal references:
#id(for internal SVG elements)
External URLs (http://, https://) are blocked to prevent SSRF attacks.
Example - SVG with Embedded Image
{
"type": "svg",
"id": "svg-with-logo",
"props": {
"content": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"300\" height=\"100\"><image href=\"assets://company-logo\" x=\"0\" y=\"0\" width=\"80\" height=\"80\"/><text x=\"100\" y=\"50\" font-size=\"24\">Company Name</text></svg>",
"width": 300,
"height": 100,
"align": "center"
}
}
Use Cases
- Custom charts from Python (matplotlib, plotly, seaborn)
- Data visualizations from R (ggplot2)
- Custom barcodes from specialized libraries
- Architecture diagrams from D3.js or other tools
- Floor plans and technical drawings
- Custom gauges and meters
- Infographics with dynamic data
Data Components
Table
Powerful data table component with 5 column types. See the Variables & Dynamic Content guide for complete details.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
dataSource | string | Yes | - | Variable name containing array data |
columns | array | Yes | - | Array of column definitions |
showHeader | boolean | No | true | Show table header row |
showBorder | boolean | No | true | Show table borders |
showTotalsRow | boolean | No | false | Show totals row (attachment only) |
style | object | No | - | Table styling options |
Column Types
1. Simple Field Column: Display a field directly from data
{
"header": "Product Name",
"field": "name",
"width": "40%",
"align": "left"
}
2. Calculated Column: JavaScript expression calculated per row
{
"header": "Total",
"isCalculated": true,
"expression": "quantity * unitPrice",
"format": {
"type": "number",
"preset": "CURRENCY",
"currency": "USD",
"decimals": 2
}
}
3. Calculated Column: JavaScript expressions for computed values
{
"header": "Total",
"isCalculated": true,
"expression": "row.quantity * row.unitPrice",
"format": {
"type": "number",
"preset": "CURRENCY",
"currency": "USD"
}
}
4. Component-Based Column: Render components in cells (PDF only)
{
"header": "Actions",
"renderType": "component",
"component": {
"type": "button",
"props": {
"text": "View",
"url": "https://example.com/products/{{id}}"
},
"contentField": "id"
}
}
Example - Order Items Table
{
"type": "table",
"id": "order-items",
"props": {
"dataSource": "{{orderItems}}",
"showHeader": true,
"showBorder": true,
"columns": [
{
"header": "Item",
"field": "name",
"width": "40%",
"align": "left"
},
{
"header": "Qty",
"field": "quantity",
"width": "15%",
"align": "center",
"format": {
"type": "number",
"preset": "DECIMAL",
"decimals": 0
}
},
{
"header": "Price",
"field": "unitPrice",
"width": "20%",
"align": "right",
"format": {
"type": "number",
"preset": "CURRENCY",
"currency": "USD",
"decimals": 2
}
},
{
"header": "Total",
"isCalculated": true,
"expression": "quantity * unitPrice",
"width": "25%",
"align": "right",
"format": {
"type": "number",
"preset": "CURRENCY",
"currency": "USD",
"decimals": 2
}
}
],
"style": {
"headerBackgroundColor": "#f8f9fa",
"headerTextColor": "#333333",
"rowBackgroundColor": "#ffffff",
"alternateRowColor": "#f8f9fa",
"borderColor": "#dee2e6"
}
}
}
Totals Row (Attachment Only)
For Excel and PDF attachments, you can add a totals row with aggregation formulas:
{
"type": "table",
"id": "sales-report",
"props": {
"dataSource": "{{salesData}}",
"showTotalsRow": true,
"totalsConfig": {
"label": "Total",
"labelColumn": "product",
"aggregations": {
"quantity": "SUM",
"revenue": "SUM",
"profit": "SUM"
}
},
"columns": [
{ "header": "Product", "field": "product" },
{ "header": "Quantity", "field": "quantity" },
{ "header": "Revenue", "field": "revenue" },
{ "header": "Profit", "field": "profit" }
]
}
}
Supported Aggregations: SUM, AVERAGE, COUNT, MIN, MAX
Use Cases
- Order summaries
- Invoice line items
- Product catalogs
- Price lists
- Sales reports
- Inventory lists
Chart
Data visualization component for creating charts (bar, line, pie, doughnut, area, scatter).
Template Support: Both PDF and Excel templates
- PDFs: Charts are rendered as static images via QuickCharts API (high resolution, transparent backgrounds)
- Attachments (PDF/Excel): Charts are rendered natively with full interactivity in Excel
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
chartType | enum | Yes | - | Chart type: "bar", "line", "pie", "doughnut", "area", "scatter" |
dataSource | string | Yes | - | Variable name containing chart data |
xAxis | string | Yes | - | Field name for X-axis |
yAxis | string | Yes | - | Field name for Y-axis |
title | string | No | "" | Chart title |
width | number | No | 600 | Chart width in pixels |
height | number | No | 400 | Chart height in pixels |
position | object | No | - | Position in attachment: x and y coordinates |
style | object | No | - | Chart styling options |
legend | object | No | - | Legend configuration |
xAxisLabel | string | No | "" | X-axis label |
yAxisLabel | string | No | "" | Y-axis label |
pdfRendering | enum | No | image | PDF rendering mode (image recommended for reliability) |
excelRendering | enum | No | native | Excel rendering: "native", "image" |
Chart Styles
{
"style": {
"colors": ["#007bff", "#28a745", "#ffc107", "#dc3545", "#6f42c1"],
"showLegend": true,
"showGridLines": true,
"backgroundColor": "#ffffff",
"borderColor": "#dee2e6"
}
}
Legend Configuration
{
"legend": {
"show": true,
"position": "bottom"
}
}
Position Options: "top", "bottom", "left", "right"
PDF-Specific Rendering
How it works in PDFs:
- Charts are converted to static PNG images via QuickCharts API
- High resolution (2x pixel ratio) for crisp display
- Transparent backgrounds blend with document design
- Standard fonts (Arial, Helvetica) for maximum compatibility
- Static images ensure consistent rendering
Recommended sizing for PDFs:
- Width: 600px or less (fits standard A4/Letter width)
- Height: 300-400px (optimal readability)
Example - Sales Chart (PDF + Excel)
{
"type": "chart",
"id": "monthly-sales",
"props": {
"chartType": "bar",
"dataSource": "{{monthlySales}}",
"xAxis": "month",
"yAxis": "revenue",
"title": "Monthly Sales Performance",
"width": 600,
"height": 400,
"xAxisLabel": "Month",
"yAxisLabel": "Revenue ($)",
"style": {
"colors": ["#007bff"],
"showLegend": false,
"showGridLines": true,
"backgroundColor": "transparent"
}
}
}
Example - Pie Chart
{
"type": "chart",
"id": "revenue-breakdown",
"props": {
"chartType": "pie",
"dataSource": "{{revenueByCategory}}",
"xAxis": "category",
"yAxis": "amount",
"title": "Revenue by Category",
"width": 600,
"height": 400,
"legend": {
"show": true,
"position": "right"
},
"style": {
"colors": ["#007bff", "#28a745", "#ffc107", "#dc3545", "#6f42c1", "#17a2b8"]
}
}
}
Chart Type Guide
Bar Chart: Compare values across categories
- Use for: Sales by product, revenue by region, etc.
- Best for: Comparing discrete categories
Line Chart: Show trends over time
- Use for: Monthly sales, growth trends, etc.
- Best for: Time-series data
Pie Chart: Show proportions of a whole
- Use for: Market share, revenue breakdown, etc.
- Best for: Percentage distributions (5-7 categories max)
Doughnut Chart: Similar to pie, with center hole
- Use for: Same as pie chart, with modern aesthetic
- Best for: Highlighting a key metric in the center
Area Chart: Show cumulative trends
- Use for: Cumulative revenue, stacked categories
- Best for: Volume and trends combined
Scatter Chart: Show correlation between variables
- Use for: Price vs. quantity, correlation analysis
- Best for: Identifying relationships in data
Attachment-Specific Properties
For PDF and Excel attachments, additional rendering options are available:
{
"pdfRendering": "image", // Renders chart as high-quality PNG for reliable cross-platform display
"excelRendering": "native", // "native" or "image" (native creates Excel charts)
"position": { // Absolute positioning (attachments only)
"x": 50,
"y": 100
}
}
Use Cases
PDF Templates:
- Weekly performance summaries
- Marketing campaign results
- Monthly sales reports
- Customer engagement metrics
- Newsletter analytics
Attachment Templates:
- Quarterly financial reports
- Sales performance dashboards
- Annual business reviews
- Analytics reports with drill-down
- KPI dashboards
Loop
Repeat content for each item in an array variable.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
dataSource | string | Yes | - | Variable name containing array data |
itemVariable | string | Yes | - | Variable name for each item (must be valid JS identifier) |
indexVar | string | No | "index" | Variable name for index (must be valid JS identifier) |
children | array | No | [] | Components to repeat for each item |
Valid Nested Components
In PDF Templates:
- text, heading, button, image, table, table-layout, divider, spacer, columns
In Attachment Templates:
- text, heading, image, table, table-layout, divider, spacer, chart, columns
Not Allowed: Loop and Conditional components cannot be nested inside loops.
Example - Product List
{
"type": "loop",
"id": "product-loop",
"props": {
"dataSource": "{{products}}",
"itemVariable": "product",
"indexVar": "i"
},
"children": [
{
"type": "container",
"id": "product-card-{{i}}",
"props": {
"padding": "20px",
"margin": "10px 0",
"backgroundColor": "#f8f9fa",
"borderRadius": "8px"
},
"children": [
{
"type": "heading",
"id": "product-name-{{i}}",
"props": { "level": 3 },
"content": "{{product.name}}"
},
{
"type": "text",
"id": "product-desc-{{i}}",
"content": "{{product.description}}",
"style": { "color": "#666666" }
},
{
"type": "text",
"id": "product-price-{{i}}",
"content": "Price: ${{product.price}}",
"style": { "fontSize": 18, "fontWeight": "bold", "color": "#007bff" }
},
{
"type": "button",
"id": "view-button-{{i}}",
"props": {
"text": "View Details",
"href": "https://example.com/products/{{product.id}}",
"backgroundColor": "#007bff",
"color": "#ffffff"
}
}
]
},
{
"type": "divider",
"id": "divider-{{i}}",
"props": {
"style": "solid",
"thickness": 1,
"color": "#e0e0e0",
"margin": "10px 0"
}
}
]
}
Example - Order Items Loop
{
"type": "loop",
"id": "order-items-loop",
"props": {
"dataSource": "{{orderItems}}",
"itemVariable": "item"
},
"children": [
{
"type": "columns",
"id": "item-row",
"props": {
"columnCount": 3,
"gap": "10px"
},
"children": [
{
"type": "text",
"id": "item-name",
"content": "{{item.name}}"
},
{
"type": "text",
"id": "item-qty",
"content": "Qty: {{item.quantity}}",
"style": { "textAlign": "center" }
},
{
"type": "text",
"id": "item-total",
"content": "${{item.total}}",
"style": { "textAlign": "right", "fontWeight": "bold" }
}
]
}
]
}
Use Cases
- Product lists
- Order item listings
- Team member profiles
- Event schedules
- FAQ lists
- Blog post summaries
Conditional
Show or hide content based on a condition.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
condition | string | Yes | - | JavaScript boolean expression |
children | array | No | [] | Components to show if condition is true |
Valid Nested Components
In PDF Templates:
- text, heading, button, image, table, table-layout, divider, spacer, columns, container
In Attachment Templates:
- text, heading, image, table, table-layout, divider, spacer, chart, columns, container
Not Allowed: Conditional and Loop components cannot be nested inside conditionals.
Condition Syntax
Conditions are JavaScript boolean expressions evaluated at render time:
Comparison Operators:
===,!==,>,>=,<,<=
Logical Operators:
&&(AND),||(OR),!(NOT)
Examples:
"isPremium === true"
"orderTotal > 100"
"quantity >= 10 && status === 'active'"
"!isExpired"
"membershipLevel === 'gold' || membershipLevel === 'platinum'"
Example - Premium Member Badge
{
"type": "conditional",
"id": "premium-badge",
"props": {
"condition": "isPremium === true"
},
"children": [
{
"type": "container",
"id": "badge-container",
"props": {
"backgroundColor": "#ffd700",
"padding": "10px 20px",
"borderRadius": "20px",
"align": "center"
},
"children": [
{
"type": "text",
"id": "badge-text",
"content": "⭐ Premium Member",
"style": {
"fontSize": 14,
"fontWeight": "bold",
"color": "#000000",
"textAlign": "center"
}
}
]
}
]
}
Example - Discount Notice
{
"type": "conditional",
"id": "discount-notice",
"props": {
"condition": "orderTotal >= 100"
},
"children": [
{
"type": "container",
"id": "discount-banner",
"props": {
"backgroundColor": "#d4edda",
"padding": "15px",
"borderRadius": "4px",
"border": "1px solid #c3e6cb"
},
"children": [
{
"type": "text",
"id": "discount-text",
"content": "🎉 Congratulations! You've qualified for free shipping on orders over $100.",
"style": {
"color": "#155724",
"fontSize": 16,
"textAlign": "center"
}
}
]
}
]
}
Example - Status-Based Content
{
"type": "conditional",
"id": "shipping-status",
"props": {
"condition": "status === 'shipped'"
},
"children": [
{
"type": "heading",
"id": "shipped-heading",
"props": { "level": 2 },
"content": "Your Order Has Shipped! 📦",
"style": { "color": "#28a745", "textAlign": "center" }
},
{
"type": "text",
"id": "tracking-info",
"content": "Track your package: {{trackingNumber}}",
"style": { "textAlign": "center" }
},
{
"type": "button",
"id": "track-button",
"props": {
"text": "Track Package",
"href": "https://example.com/tracking/{{trackingNumber}}",
"backgroundColor": "#28a745",
"alignment": "center"
}
}
]
}
Use Cases
- Premium/VIP content
- Discount notifications
- Shipping status messages
- Membership tier benefits
- Conditional calls-to-action
- Personalized content sections
Interactive Components
Button
Call-to-action button with clickable link.
Template Support: PDF templates only (not available in Excel)
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
text | string | Yes | - | Button text (supports {{variables}}) |
href | string | Yes | - | Button URL (supports {{variables}}) |
alignment | enum | No | left | Alignment: "left", "center", "right" |
backgroundColor | string | No | #007bff | Background color |
color | string | No | #ffffff | Text color |
borderRadius | string | No | "4px" | Border radius |
fontSize | number | No | 16 | Font size (8-48) |
fontWeight | string | No | "normal" | Font weight: "normal", "bold", etc. |
padding | string | No | "12px 24px" | CSS padding value |
textDecoration | string | No | "none" | Text decoration: "none", "underline" |
Example - Primary CTA
{
"type": "button",
"id": "get-started-btn",
"props": {
"text": "Get Started",
"href": "https://example.com/signup",
"alignment": "center",
"backgroundColor": "#007bff",
"color": "#ffffff",
"borderRadius": "8px",
"fontSize": 18,
"fontWeight": "bold",
"padding": "16px 32px"
}
}
Example - Dynamic URL
{
"type": "button",
"id": "view-order-btn",
"props": {
"text": "View Order #{{orderNumber}}",
"href": "https://example.com/orders/{{orderId}}",
"alignment": "center",
"backgroundColor": "#28a745",
"color": "#ffffff"
}
}
Button Styling Presets
Primary Button (default):
{
"backgroundColor": "#007bff",
"color": "#ffffff",
"borderRadius": "4px",
"padding": "12px 24px"
}
Success Button:
{
"backgroundColor": "#28a745",
"color": "#ffffff",
"borderRadius": "4px",
"padding": "12px 24px"
}
Danger/Alert Button:
{
"backgroundColor": "#dc3545",
"color": "#ffffff",
"borderRadius": "4px",
"padding": "12px 24px"
}
Secondary/Outline Button:
{
"backgroundColor": "transparent",
"color": "#007bff",
"border": "2px solid #007bff",
"borderRadius": "4px",
"padding": "10px 22px"
}
Use Cases
- Call-to-action buttons
- Order confirmation links
- Account activation
- Password reset links
- Survey/feedback links
- Download buttons
QR Code
QR code component for scannable information.
Template Support: PDF templates only (not available in Excel)
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
value | string | Yes | - | QR code content (max 2,953 chars, supports {{variables}}) |
size | number/string | No | 200 | QR code size (50-1000 pixels or CSS value) |
errorCorrectionLevel | enum | No | M | Error correction: "L" (7%), "M" (15%), "Q" (25%), "H" (30%) |
margin | number | No | 4 | Quiet zone margin (0-10) |
color | string | No | #000000 | Foreground color |
backgroundColor | string | No | #ffffff | Background color |
align | enum | No | left | Alignment: "left", "center", "right" |
alt | string | No | "" | Alt text for accessibility |
style | object | No | - | Additional styling |
Error Correction Levels
- L (Low): 7% error correction - smallest QR code, best for clean environments
- M (Medium): 15% error correction - balanced size and reliability (recommended)
- Q (Quartile): 25% error correction - good for printed materials
- H (High): 30% error correction - largest code, best for damaged/dirty environments
Example - Event Ticket
{
"type": "qr-code",
"id": "ticket-qr",
"props": {
"value": "TICKET:{{ticketId}}:{{eventId}}:{{attendeeEmail}}",
"size": 250,
"errorCorrectionLevel": "H",
"margin": 4,
"align": "center",
"alt": "Event Ticket QR Code"
}
}
Example - vCard Contact
{
"type": "qr-code",
"id": "contact-qr",
"props": {
"value": "BEGIN:VCARD\nVERSION:3.0\nFN:{{fullName}}\nEMAIL:{{email}}\nTEL:{{phone}}\nEND:VCARD",
"size": 200,
"errorCorrectionLevel": "M",
"align": "center"
}
}
Example - WiFi Credentials
{
"type": "qr-code",
"id": "wifi-qr",
"props": {
"value": "WIFI:T:WPA;S:{{networkName}};P:{{password}};;",
"size": 200,
"errorCorrectionLevel": "H",
"margin": 4,
"align": "center",
"alt": "WiFi Network QR Code"
}
}
Example - Payment Link
{
"type": "qr-code",
"id": "payment-qr",
"props": {
"value": "https://example.com/pay/{{invoiceId}}?amount={{amount}}¤cy={{currency}}",
"size": 300,
"errorCorrectionLevel": "M",
"align": "center"
}
}
Common QR Code Formats
URL:
https://example.com/path
PDF:
mailto:support@example.com?subject=Support%20Request
Phone:
tel:+1234567890
SMS:
sms:+1234567890?body=Hello
vCard (Contact):
BEGIN:VCARD
VERSION:3.0
FN:John Doe
EMAIL:john@example.com
TEL:+1234567890
END:VCARD
WiFi:
WIFI:T:WPA;S:NetworkName;P:Password;;
Geo Location:
geo:37.7749,-122.4194
Use Cases
- Event tickets
- Contact information sharing
- WiFi access
- Payment links
- Product authentication
- Mobile app downloads
- Survey links
- Loyalty program enrollment
Advanced Components
Component Nesting Rules
Allowed Nesting:
- Container → any component (except itself)
- Columns → any component per column
- Table Layout → any component per cell
- Loop → most components (no nested loops or conditionals)
- Conditional → most components (no nested conditionals or loops)
Forbidden Nesting:
- Loop inside Loop
- Loop inside Conditional
- Conditional inside Loop
- Conditional inside Conditional
- Button inside Button
- QR Code inside QR Code
Component Positioning (Attachments Only)
For PDF and Excel attachments, most components support absolute positioning:
{
"position": {
"x": 100,
"y": 200
}
}
x: Horizontal position in pixelsy: Vertical position in pixels (or "auto" for flow layout)
Variable References in Components
All text-based properties support Handlebars syntax:
Simple Variables:
{{userName}}
{{orderNumber}}
{{companyName}}
Nested Properties:
{{user.firstName}}
{{order.shippingAddress.city}}
{{product.pricing.amount}}
Array Elements (in loops):
{{item.name}}
{{product[0].price}}
Constants:
{{COMPANY_NAME}}
{{SUPPORT_EMAIL}}
{{TAX_RATE}}
Best Practices
Design Principles
1. Mobile-First Design
- Use
stackOnMobile: truefor columns - Limit image widths (max 600px for standard page width)
- Use readable font sizes (16px minimum)
- Provide adequate spacing and padding
2. Accessibility
- Always include
alttext for images - Use semantic heading levels (H1 → H2 → H3)
- Ensure sufficient color contrast (4.5:1 minimum)
- Provide descriptive button text
3. Performance
- Optimize image sizes before uploading
- Limit nested component depth (max 5 levels)
- Use calculated columns instead of loops when possible
4. Consistency
- Use consistent colors throughout template
- Maintain uniform spacing between sections
- Apply consistent button styling
- Use standard font sizes for hierarchy
Component Selection Guide
When to use Container:
- Group related content
- Apply consistent styling to sections
- Create visual cards or panels
- Control maximum width
When to use Columns:
- Side-by-side layouts
- Feature grids
- Responsive layouts that stack on mobile
When to use Table Layout:
- Fixed grid positioning
- Label-value pairs
- Simple structured data without headers
When to use Table:
- Tabular data with headers
- Dynamic data from arrays
- Calculations and formulas
- Sortable/filterable data
When to use Loop:
- Repeating content blocks
- Product listings
- Dynamic item counts
- Personalized content per item
When to use Conditional:
- Show/hide based on user attributes
- Personalized content
- Status-dependent sections
- Feature toggles
Common Patterns
Pattern: Product Grid
{
"type": "columns",
"id": "product-grid",
"props": { "columnCount": 3, "gap": "20px", "stackOnMobile": true },
"children": [
{
"type": "loop",
"id": "product-loop",
"props": { "dataSource": "{{products}}", "itemVariable": "product" },
"children": [
{
"type": "container",
"id": "product-card",
"props": { "padding": "20px", "backgroundColor": "#f8f9fa", "borderRadius": "8px" },
"children": [
{
"type": "image",
"id": "product-image",
"props": { "source": "{{product.imageUrl}}", "width": 200, "alignment": "center" }
},
{
"type": "heading",
"id": "product-name",
"props": { "level": 4 },
"content": "{{product.name}}"
},
{
"type": "text",
"id": "product-price",
"content": "${{product.price}}"
},
{
"type": "button",
"id": "buy-button",
"props": { "text": "Buy Now", "href": "{{product.buyUrl}}", "alignment": "center" }
}
]
}
]
}
]
}
Pattern: Invoice Header
{
"type": "columns",
"id": "invoice-header",
"props": { "columnCount": 2, "gap": "20px" },
"children": [
{
"type": "container",
"id": "company-info",
"children": [
{
"type": "image",
"id": "logo",
"props": { "source": "{{companyLogo}}", "width": 150 }
},
{
"type": "text",
"id": "company-name",
"content": "{{companyName}}"
},
{
"type": "text",
"id": "company-address",
"content": "{{companyAddress}}"
}
]
},
{
"type": "table-layout",
"id": "invoice-details",
"props": { "rows": 3, "cols": 2, "cellPadding": "8px" },
"children": [
{ "type": "text", "id": "invoice-label", "content": "Invoice #:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "invoice-num", "content": "{{invoiceNumber}}" },
{ "type": "text", "id": "date-label", "content": "Date:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "date-value", "content": "{{invoiceDate}}" },
{ "type": "text", "id": "due-label", "content": "Due Date:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "due-value", "content": "{{dueDate}}" }
]
}
]
}
Pattern: Status Card with Conditional
{
"type": "container",
"id": "status-card",
"props": {
"padding": "20px",
"borderRadius": "8px",
"backgroundColor": "#ffffff",
"border": "2px solid #dee2e6"
},
"children": [
{
"type": "heading",
"id": "status-title",
"props": { "level": 2 },
"content": "Order Status"
},
{
"type": "conditional",
"id": "pending-status",
"props": { "condition": "status === 'pending'" },
"children": [
{
"type": "container",
"id": "pending-container",
"props": { "backgroundColor": "#fff3cd", "padding": "15px", "borderRadius": "4px" },
"children": [
{
"type": "text",
"id": "pending-text",
"content": "⏳ Your order is being processed.",
"style": { "color": "#856404" }
}
]
}
]
},
{
"type": "conditional",
"id": "shipped-status",
"props": { "condition": "status === 'shipped'" },
"children": [
{
"type": "container",
"id": "shipped-container",
"props": { "backgroundColor": "#d4edda", "padding": "15px", "borderRadius": "4px" },
"children": [
{
"type": "text",
"id": "shipped-text",
"content": "📦 Your order has shipped! Track: {{trackingNumber}}",
"style": { "color": "#155724" }
},
{
"type": "button",
"id": "track-button",
"props": {
"text": "Track Package",
"href": "{{trackingUrl}}",
"backgroundColor": "#28a745",
"alignment": "center"
}
}
]
}
]
}
]
}
Complete Examples
Example 1: Order Confirmation Document
{
"subject": "Order Confirmation #{{orderNumber}}",
"preheader": "Thank you for your order!",
"body": [
{
"type": "container",
"id": "header",
"props": {
"backgroundColor": "#007bff",
"padding": "30px 20px",
"maxWidth": "600px"
},
"children": [
{
"type": "image",
"id": "logo",
"props": {
"source": "https://example.com/logo-white.png",
"width": 200,
"alignment": "center"
}
}
]
},
{
"type": "container",
"id": "main-content",
"props": {
"padding": "40px 20px",
"maxWidth": "600px",
"backgroundColor": "#ffffff"
},
"children": [
{
"type": "heading",
"id": "thank-you",
"props": { "level": 1 },
"content": "Thank You for Your Order!",
"style": { "textAlign": "center", "color": "#333333" }
},
{
"type": "text",
"id": "confirmation-message",
"content": "Hi {{customerName}}, we've received your order and will send you shipping confirmation as soon as your order ships.",
"style": { "textAlign": "center", "fontSize": 16, "color": "#666666" }
},
{
"type": "spacer",
"id": "spacer-1",
"props": { "height": "30px" }
},
{
"type": "table-layout",
"id": "order-info",
"props": {
"rows": 3,
"cols": 2,
"borderWidth": "0px",
"cellPadding": "10px",
"width": "100%"
},
"children": [
{ "type": "text", "id": "order-label", "content": "Order Number:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "order-value", "content": "{{orderNumber}}" },
{ "type": "text", "id": "date-label", "content": "Order Date:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "date-value", "content": "{{orderDate}}" },
{ "type": "text", "id": "total-label", "content": "Total:", "style": { "fontWeight": "bold" } },
{ "type": "text", "id": "total-value", "content": "${{orderTotal}}", "style": { "fontWeight": "bold", "color": "#007bff" } }
]
},
{
"type": "spacer",
"id": "spacer-2",
"props": { "height": "30px" }
},
{
"type": "divider",
"id": "divider-1",
"props": { "thickness": 2, "color": "#e0e0e0" }
},
{
"type": "spacer",
"id": "spacer-3",
"props": { "height": "30px" }
},
{
"type": "heading",
"id": "items-heading",
"props": { "level": 2 },
"content": "Order Items",
"style": { "color": "#333333" }
},
{
"type": "table",
"id": "order-items",
"props": {
"dataSource": "{{orderItems}}",
"showHeader": true,
"columns": [
{ "header": "Item", "field": "name", "width": "50%", "align": "left" },
{ "header": "Qty", "field": "quantity", "width": "15%", "align": "center" },
{ "header": "Price", "field": "unitPrice", "width": "20%", "align": "right", "format": { "type": "number", "preset": "CURRENCY", "currency": "USD" } },
{ "header": "Total", "isCalculated": true, "expression": "quantity * unitPrice", "width": "15%", "align": "right", "format": { "type": "number", "preset": "CURRENCY", "currency": "USD" } }
]
}
},
{
"type": "spacer",
"id": "spacer-4",
"props": { "height": "30px" }
},
{
"type": "button",
"id": "view-order-button",
"props": {
"text": "View Order Details",
"href": "https://example.com/orders/{{orderId}}",
"alignment": "center",
"backgroundColor": "#007bff",
"padding": "16px 32px",
"fontSize": 18
}
}
]
},
{
"type": "container",
"id": "footer",
"props": {
"backgroundColor": "#f8f9fa",
"padding": "30px 20px",
"maxWidth": "600px"
},
"children": [
{
"type": "text",
"id": "footer-text",
"content": "Questions? Contact us at support@example.com",
"style": { "textAlign": "center", "fontSize": 14, "color": "#666666" }
}
]
}
]
}
Example 2: Sales Report (PDF Attachment)
{
"title": "Monthly Sales Report",
"body": [
{
"type": "heading",
"id": "report-title",
"props": { "level": 1 },
"content": "Sales Report - {{reportMonth}}",
"style": { "fontSize": 24, "fontWeight": "bold", "color": "#333333" }
},
{
"type": "text",
"id": "generated-date",
"content": "Generated: {{generatedDate}}",
"style": { "fontSize": 12, "color": "#666666" }
},
{
"type": "spacer",
"id": "spacer-1",
"props": { "height": "20px" }
},
{
"type": "columns",
"id": "summary-cards",
"props": { "columnCount": 3, "gap": "20px" },
"children": [
{
"type": "container",
"id": "revenue-card",
"props": { "padding": "20px", "backgroundColor": "#e7f3ff", "borderRadius": "8px" },
"children": [
{ "type": "text", "id": "revenue-label", "content": "Total Revenue", "style": { "fontSize": 14, "color": "#666666" } },
{ "type": "text", "id": "revenue-value", "content": "${{totalRevenue}}", "style": { "fontSize": 28, "fontWeight": "bold", "color": "#007bff" } }
]
},
{
"type": "container",
"id": "orders-card",
"props": { "padding": "20px", "backgroundColor": "#d4edda", "borderRadius": "8px" },
"children": [
{ "type": "text", "id": "orders-label", "content": "Total Orders", "style": { "fontSize": 14, "color": "#666666" } },
{ "type": "text", "id": "orders-value", "content": "{{totalOrders}}", "style": { "fontSize": 28, "fontWeight": "bold", "color": "#28a745" } }
]
},
{
"type": "container",
"id": "avg-card",
"props": { "padding": "20px", "backgroundColor": "#fff3cd", "borderRadius": "8px" },
"children": [
{ "type": "text", "id": "avg-label", "content": "Avg Order Value", "style": { "fontSize": 14, "color": "#666666" } },
{ "type": "text", "id": "avg-value", "content": "${{avgOrderValue}}", "style": { "fontSize": 28, "fontWeight": "bold", "color": "#ffc107" } }
]
}
]
},
{
"type": "spacer",
"id": "spacer-2",
"props": { "height": "30px" }
},
{
"type": "chart",
"id": "revenue-chart",
"props": {
"chartType": "bar",
"dataSource": "{{dailySales}}",
"xAxis": "date",
"yAxis": "revenue",
"title": "Daily Revenue",
"width": 800,
"height": 400,
"xAxisLabel": "Date",
"yAxisLabel": "Revenue ($)",
"style": {
"colors": ["#007bff"],
"showGridLines": true,
"backgroundColor": "#ffffff"
}
}
},
{
"type": "spacer",
"id": "spacer-3",
"props": { "height": "30px" }
},
{
"type": "heading",
"id": "products-heading",
"props": { "level": 2 },
"content": "Top Products",
"style": { "fontSize": 20, "fontWeight": "bold" }
},
{
"type": "table",
"id": "top-products",
"props": {
"dataSource": "{{topProducts}}",
"showHeader": true,
"showTotalsRow": true,
"totalsConfig": {
"label": "Total",
"labelColumn": "productName",
"aggregations": {
"unitsSold": "SUM",
"revenue": "SUM"
}
},
"columns": [
{ "header": "Product", "field": "productName", "width": "40%", "align": "left" },
{ "header": "Units Sold", "field": "unitsSold", "width": "20%", "align": "center" },
{ "header": "Revenue", "field": "revenue", "width": "20%", "align": "right", "format": { "type": "number", "preset": "CURRENCY", "currency": "USD" } },
{ "header": "% of Total", "isCalculated": true, "expression": "(revenue / totalRevenue) * 100", "width": "20%", "align": "right", "format": { "type": "number", "preset": "PERCENT", "decimals": 1 } }
]
}
}
]
}
Example 3: Event Invitation with QR Code
{
"subject": "You're Invited: {{eventName}}",
"preheader": "{{eventDate}} at {{eventLocation}}",
"body": [
{
"type": "container",
"id": "hero",
"props": {
"backgroundColor": "#667eea",
"padding": "60px 20px",
"maxWidth": "600px"
},
"children": [
{
"type": "heading",
"id": "event-title",
"props": { "level": 1 },
"content": "{{eventName}}",
"style": { "fontSize": 32, "fontWeight": "bold", "color": "#ffffff", "textAlign": "center" }
},
{
"type": "text",
"id": "event-tagline",
"content": "{{eventTagline}}",
"style": { "fontSize": 18, "color": "rgba(255,255,255,0.9)", "textAlign": "center" }
}
]
},
{
"type": "container",
"id": "main-content",
"props": {
"padding": "40px 20px",
"maxWidth": "600px",
"backgroundColor": "#ffffff"
},
"children": [
{
"type": "text",
"id": "greeting",
"content": "Hi {{attendeeName}},",
"style": { "fontSize": 18, "fontWeight": "bold", "color": "#333333" }
},
{
"type": "spacer",
"id": "spacer-1",
"props": { "height": "15px" }
},
{
"type": "text",
"id": "invitation-text",
"content": "You're invited to join us for {{eventName}}! We're excited to have you there.",
"style": { "fontSize": 16, "color": "#666666", "lineHeight": 1.6 }
},
{
"type": "spacer",
"id": "spacer-2",
"props": { "height": "30px" }
},
{
"type": "divider",
"id": "divider-1",
"props": { "thickness": 1, "color": "#e0e0e0" }
},
{
"type": "spacer",
"id": "spacer-3",
"props": { "height": "30px" }
},
{
"type": "columns",
"id": "event-details",
"props": { "columnCount": 2, "gap": "20px" },
"children": [
{
"type": "container",
"id": "details-left",
"children": [
{ "type": "text", "id": "date-label", "content": "📅 Date", "style": { "fontSize": 14, "fontWeight": "bold", "color": "#999999" } },
{ "type": "text", "id": "date-value", "content": "{{eventDate}}", "style": { "fontSize": 16, "color": "#333333", "marginTop": "5px" } },
{ "type": "spacer", "id": "detail-spacer-1", "props": { "height": "15px" } },
{ "type": "text", "id": "time-label", "content": "🕐 Time", "style": { "fontSize": 14, "fontWeight": "bold", "color": "#999999" } },
{ "type": "text", "id": "time-value", "content": "{{eventTime}}", "style": { "fontSize": 16, "color": "#333333", "marginTop": "5px" } }
]
},
{
"type": "container",
"id": "details-right",
"children": [
{ "type": "text", "id": "location-label", "content": "📍 Location", "style": { "fontSize": 14, "fontWeight": "bold", "color": "#999999" } },
{ "type": "text", "id": "location-value", "content": "{{eventLocation}}", "style": { "fontSize": 16, "color": "#333333", "marginTop": "5px" } },
{ "type": "spacer", "id": "detail-spacer-2", "props": { "height": "15px" } },
{ "type": "text", "id": "dress-label", "content": "👔 Dress Code", "style": { "fontSize": 14, "fontWeight": "bold", "color": "#999999" } },
{ "type": "text", "id": "dress-value", "content": "{{dressCode}}", "style": { "fontSize": 16, "color": "#333333", "marginTop": "5px" } }
]
}
]
},
{
"type": "spacer",
"id": "spacer-4",
"props": { "height": "30px" }
},
{
"type": "divider",
"id": "divider-2",
"props": { "thickness": 1, "color": "#e0e0e0" }
},
{
"type": "spacer",
"id": "spacer-5",
"props": { "height": "30px" }
},
{
"type": "heading",
"id": "ticket-heading",
"props": { "level": 2 },
"content": "Your Ticket",
"style": { "fontSize": 20, "textAlign": "center", "color": "#333333" }
},
{
"type": "text",
"id": "ticket-instructions",
"content": "Present this QR code at the entrance for quick check-in",
"style": { "fontSize": 14, "textAlign": "center", "color": "#666666" }
},
{
"type": "spacer",
"id": "spacer-6",
"props": { "height": "20px" }
},
{
"type": "qr-code",
"id": "ticket-qr",
"props": {
"value": "EVENT:{{eventId}}:ATTENDEE:{{attendeeId}}:TICKET:{{ticketId}}",
"size": 250,
"errorCorrectionLevel": "H",
"align": "center",
"alt": "Event Ticket QR Code"
}
},
{
"type": "text",
"id": "ticket-number",
"content": "Ticket #{{ticketId}}",
"style": { "fontSize": 12, "textAlign": "center", "color": "#999999", "marginTop": "10px" }
},
{
"type": "spacer",
"id": "spacer-7",
"props": { "height": "30px" }
},
{
"type": "button",
"id": "add-calendar-button",
"props": {
"text": "Add to Calendar",
"href": "{{calendarLink}}",
"alignment": "center",
"backgroundColor": "#667eea",
"padding": "14px 28px"
}
}
]
},
{
"type": "container",
"id": "footer",
"props": {
"backgroundColor": "#f8f9fa",
"padding": "30px 20px",
"maxWidth": "600px"
},
"children": [
{
"type": "text",
"id": "footer-text",
"content": "Can't make it? Let us know at {{eventEmail}}",
"style": { "textAlign": "center", "fontSize": 14, "color": "#666666" }
}
]
}
]
}
Summary
This guide covered all 18 available template components across 4 categories:
- 5 Layout Components: Container, Columns, Table Layout, Divider, Spacer
- 6 Content Components: Rich Text, Text (deprecated), Heading (deprecated), Image, List, SVG
- 4 Data Components: Table, Chart, Loop, Conditional
- 3 Interactive Components: Button, QR Code, Barcode
Each component includes detailed property specifications, examples, and use cases. Combined with the Variables & Dynamic Content guide, you have everything needed to create powerful, dynamic templates for PDF and Excel documents.
For more information:
- Variables & Dynamic Content - Variables, calculated variables, and data tables
- Template Designer - Visual PDF and Excel template editor
- Templates - Template management overview
Need Help? Contact support at support@rynko.dev