Overview and architecture

Report Designer has three packages:

PackageWhat it isRuns in
@rd/designerThe <report-designer> web component, where template authors design documents. It emits template JSONThe browser, inside your web app (any framework)
@rd/serverThe render service. POST /api/v1/render with { template, data } returns application/pdf. Also contains the rd-render CLIYour servers (Docker or Node.js 20+)
@rd/coreThe engine: template validation, the expression language, layout, fonts and PDF output. Used by both of the aboveBrowser 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.