Overview and architecture
Report Designer has three packages:
| Package | What it is | Runs in |
|---|---|---|
@rd/designer | The <report-designer> web component, where template authors design documents. It emits template JSON | The browser, inside your web app (any framework) |
@rd/server | The render service. POST /api/v1/render with { template, data } returns application/pdf. Also contains the rd-render CLI | Your servers (Docker or Node.js 20+) |
@rd/core | The engine: template validation, the expression language, layout, fonts and PDF output. Used by both of the above | Browser and Node.js |
Because the designer's preview and the server use the same engine, a preview has exactly the same layout as the production PDF: the same line breaks, page breaks and barcode sizes.
Data flow#
┌──────────────────────── your web application ───────────────────────┐
│ │
template author ──────▶│ <report-designer> your back end │
│ .template ◀── load ──────────────── templates table / store │
│ .schema ◀── data contract (JSON Schema, optional) │
│ save event ─── template JSON ──────▶ store (versioned) │
└──────────────────────────────────────────────────────────────────────┘
WMS / ERP event ──▶ your service ──POST /api/v1/render { template, data }──▶ @rd/server ──▶ application/pdf
│
printers, e-mail, storage
Key properties of the design:
- The designer never receives business data. It previews with preview text, sample values stored in the template itself
(
{{ shipTo.name | Northwind Retail }}). You never need to give the browser real shipments or customer data. - Template and data are separate parameters. Store templates once, then render them with any number of data documents.
- Stateless server. The server has no database, sessions or template storage. Scale it horizontally.
- No outbound calls by default. The server fetches nothing from the network unless you allow image hosts.
- Offline licensing. A license is a signed key that the render service verifies locally. No license server is contacted. The designer needs no license.
The template#
A template is a JSON document (@rd/core type Template):
{
"version": 1,
"name": "Packing Slip",
"locale": "en-US",
"page": { "size": "Letter", "width": 612, "height": 792, "orientation": "portrait", "margins": { "top": 36, "right": 36, "bottom": 36, "left": 36 } },
"bands": {
"pageHeader": { "enabled": true, "height": 72, "printOn": "all", "elements": [ { "id": "t1", "type": "text", "x": 0, "y": 0, "width": 300, "height": 24, "text": "{{ company.name | Acme }}" } ] },
"body": { "height": 120, "elements": [ { "id": "tbl", "type": "table", "dataPath": "lines", "x": 0, "y": 0, "width": 540, "height": 60, "columns": [ ] } ] }
},
"styles": { }, "fonts": [ ], "metadata": { "title": "Packing Slip {{ orderNumber }}" }
}
All coordinates are in PDF points (1/72 in). Treat templates as opaque documents: store them, version them and pass them to the render API.
Don't generate them by hand except in tests. The structure is described by the TypeScript types in @rd/core (re-exported from @rd/designer).
Data flow#
┌──────────────────────── your web application ───────────────────────┐
│ │
template author ──────▶│ <report-designer> your back end │
│ .template ◀── load ──────────────── templates table / store │
│ .schema ◀── data contract (JSON Schema, optional) │
│ save event ─── template JSON ──────▶ store (versioned) │
└──────────────────────────────────────────────────────────────────────┘
WMS / ERP event ──▶ your service ──POST /api/v1/render { template, data }──▶ @rd/server ──▶ application/pdf
│
printers, e-mail, storage
Key properties of the design:
- The designer never receives business data. It previews with preview text, sample values stored in the template itself
(
{{ shipTo.name | Northwind Retail }}). You never need to give the browser real shipments or customer data. - Template and data are separate parameters. Store templates once, then render them with any number of data documents.
- Stateless server. The server has no database, sessions or template storage. Scale it horizontally.
- No outbound calls by default. The server fetches nothing from the network unless you allow image hosts.
- Offline licensing. A license is a signed key that the render service verifies locally. No license server is contacted. The designer needs no license.