Documentation
Architecture Overview
High-level overview of PaperCast rendering flow.
PaperCast is built on a declarative, schema-first approach. Instead of manually pushing React components into a DOM and hoping they fit on a PDF page, PaperCast defines the entire document as a JSON Abstract Syntax Tree (AST).
This AST is validated, measured, paginated, and finally rendered.
The PaperCast Pipeline
1. Document Store (Zustand)
The source of truth is the JSON AST (Abstract Syntax Tree). The user edits the JSON string (via the Monaco editor), and the store parses it into a strongly-typed DocumentSchema object.
{
"version": 1,
"meta": {
"pageSize": "A4",
"orientation": "portrait",
"baseUnit": "px",
"dpi": 96
},
"theme": {
"defaults": {
"base": {
"fontFamily": "Inter, sans-serif",
"fontSizePx": 14,
"color": "#333333",
"lineHeight": 1.5
}
}
},
"data": {
"invoiceNumber": "INV-2023-001",
"customer": { "name": "Acme Corp" }
},
"document": {
"headers": {
"main-header": {
"condition": "all",
"root": {
"id": "header-root",
"type": "row",
"layout": { "paddingBottom": 20 },
"children": [
{
"id": "logo",
"type": "image",
"props": { "urlLiteral": "logo.png" }
}
]
}
}
},
"body": {
"id": "body-root",
"type": "column",
"layout": {
"paddingTop": 40,
"paddingRight": 40,
"paddingBottom": 40,
"paddingLeft": 40
},
"children": [
{
"id": "title",
"type": "text",
"props": { "literal": "Invoice" },
"style": { "fontSizePx": 24 }
}
]
},
"footers": {}
}
}
2. Validation & Registration
Every update to the AST is strictly validated against docframe.schema.json in @papercast/core. The architecture is cleanly split into two halves:
- Core Engine (
@papercast/engine): A standalone, framework-agnostic engine that calculates pagination, evaluates variables, and resolves templates without any knowledge of the DOM. It uses a Schema Registry to track node properties and validation behaviors. - Headless Binding (
@papercast/react): A React-specific adapter that implements DOM requirements (like measuring node heights) and acts as the Component Registry, mapping AST node types to actual visual React components.
3. Offscreen Measurement
Before anything is shown to the user, OffscreenMeasurer.tsx (an implementation of the engine's IMeasurer adapter) silently renders the nodes in the DOM to measure their physical heights in pixels.
4. Pagination Engine
With the height data available, PaginationEngine.ts inside @papercast/engine splits the AST into discrete pages, injecting Headers and Footers based on conditions (first page, even, odd).
5. Rendering
The DocumentPreview inside the web app maps the paginated AST nodes back to React components via the React Component Registry.
Why Offscreen Measurement?
Browsers are inherently dynamic. To guarantee that a PDF matches the screen exactly, we must measure how the browser renders specific fonts and line heights before we can mathematically decide where to insert a page break.