Escape

Documentation

quario treats a report as a definition — JSON you store, version and review — rather than as generated code. The same definition renders to four document shapes: a page, a PDF, a workbook, and a Word document.

Safe by construction

Expressions in a definition parse into closures. There is no eval, no new Function, and no code generation anywhere in the render path. That’s a property of how the engine reads a definition, not a sandbox bolted on afterwards. Trust and CSP sets out what the engine treats as trusted and what it doesn’t.

One definition, four shapes

Package Renders
@quario/html A page, styled from the definition’s own vocabulary
@quario/pdf A PDF, with no headless browser in the pipeline
@quario/xlsx A workbook, where numbers stay numbers
@quario/docx A Word document, with real tables, and a navigation outline

Install the engine with npm install quario and add the targets you render to. @quario/csv is a fifth target: a data export rather than a document shape, so it’s outside this list.

Painters, flow targets, and a fragment

Targets differ in who decides where the pages break, and it’s worth knowing which kind you render to before you declare page furniture.

A painter lays the document out itself. @quario/pdf paginates, reserves the height its page bands need, and can therefore promise where every line falls.

A flow target states the geometry and the typography and lets the reader’s application paginate. @quario/docx runs no layout of its own, so the promise is the same look rather than the same page breaks. Page bands become a Word section’s header and footer, and a bare {{ page.number }} becomes a live field Word recomputes.

A fragment has no pages at all. @quario/html returns markup for a page you already own and leaves page bands unread. It turns a group’s break into a class your print CSS may act on.

@quario/csv answers to none of these: a record has no page at all, so page declarations withdraw. @quario/xlsx is a grid rather than a page, but a reader still prints a worksheet. A group’s break opens a sheet there, and xlsx({ page }) configures the paper.

Start here

Getting started is the one to read first. It builds an invoice from a record your application already has, renders it into a page, and renders the same definition as a PDF.

Once that holds, the Diving Deeper pages go one level down, each on one thing.

Writing a definition

  • Supplying the data — where the payload comes from, and what the engine never does.
  • Scopes — what an expression can read, and where.
  • Selecting rows — choosing, filtering, ordering, and ranking the rows.
  • Bands — the report header, groups, detail, page furniture, and columns.
  • Totals — aggregates, running values, and inline reducers.
  • Formatting — presenting numbers and dates without turning them into strings.
  • Styling — the closed vocabulary, how it layers, and the box.
  • Images and splits — placing a picture, and laying cells across the width.
  • Host functions — the presentation policy the engine leaves to you.

Rendering it

Embedding it

  • The viewer — pages on screen, and the export menu.
  • The editor — your users authoring their own definitions.

Running it

  • Validating definitions — compiling one in CI, and holding it in a service.
  • Trust and CSP — the trust boundary, and rendering without unsafe-eval.
  • Licensing — offline verification, and what an unlicensed render shows.
  • quario over MCP — an agent’s tools, and the host it can’t reach.

The reference covers the engine and each package, for a signature rather than an explanation.

For task-shaped walkthroughs rather than reference, see the guides. For definitions you can copy whole, see the templates.