Embeddable report designer · React & Angular
Your users design the report. You ship the PDF.
BroadPaper drops a visual report designer into your product. You declare the data; your users lay out the document; BroadPaper handles layout, branding, pagination and a print-perfect PDF, in the browser, with no server.
npm i @broadpaper/react @broadpaper/forme
A report designer that lives inside your product, not beside it.
Every serious business application ends up needing customer-facing documents: reviews, statements, factsheets, certificates, invoices. Every team ends up building a report designer for them, badly, twice. BroadPaper is the one you were going to build anyway, finished.
- 01
You declare the data
Describe your data sources with a typed schema, hand over sample data, and mount the designer in a
div. About thirty lines. - 02
Your users design the document
Drag blocks, bind fields, set conditions, pick a brand. They see real data on real pages as they work, and they cannot break the grid.
- 03
BroadPaper produces the file
A saved template is JSON you keep. Render it with live data to a vector PDF, in the browser, in Node, or behind the render service.
Blocks, not a canvas.
Page, section, row, column, block. The structure is what makes the output predictable: a heading cannot be nudged three pixels off its grid, and a table always knows which column it is in. The palette is searchable, the properties panel is declarative, and every bound field is a chip you can read. A new document starts empty, with your schemas already on the left.
Your schema is the palette.
You declare data sources with a typed schema; the designer shows them as a tree. Drag a scalar onto the page and it becomes a field. Drag a list and it becomes a table. Type two braces in any text block and the expression autocomplete offers your fields, with types checked against the schema before anything is saved.
Read about bindings in the docs.
One template. Any brand.
Nothing in a saved template names a colour or a font. It names theme tokens, and a theme resolves them. The same JSON renders as Meridian Wealth or as Hartwell & Kane with one option changed, which is how a white-label product serves every customer from one design.
Read about themes in the docs.
A vector PDF, rendered in the browser.
Selectable text, vector charts, embedded fonts, repeated table headers. The WebAssembly engine draws it in the user's own browser; the same engine runs in Node, on the edge, or behind the render service. Nothing leaves your infrastructure unless you send it.
Download the four-page example PDF the demo produces.
What you see is what breaks.
Browsers paginate for printing inconsistently and invisibly. PDF libraries paginate their own way. Either way, the page break your user sees on screen is a guess about the one in the file.
BroadPaper refuses to let either of them decide. A section is measured once as a continuous galley, a pure paginator assigns clip windows to pages, and both the canvas and the PDF engine are handed pages that are already decided. Point the canvas at the same measurer as the PDF and the two cannot disagree.
Everything a commercial report designer needs. Nothing it doesn't.
Twelve things it does, and the reason each one is hard. The documentation is where the detail lives.
- 01
Structured document model
Page, section, row, column, block. A tree your users cannot break, not a canvas they can.
- 02
Pagination we own
Keep-together, orphans and widows, repeated table headers, running headers with page numbers.
- 03
What you see is what breaks
The canvas measures with the engine that draws the file. A break on screen is a break in the PDF.
- 04
One template, any brand
Templates name theme tokens, never colours. Re-brand a saved document with one option.
- 05
Browserless vector PDF
A WebAssembly engine draws selectable text and vector charts in Node, at the edge, or in the browser.
- 06
Bindings with a type system
A hand-written expression language. No eval, checked against your schemas, with autocomplete.
- 07
Tables, repeaters, charts
Sorting, limits, conditional formatting, headers that repeat. Charts interactive on screen, identical in print.
- 08
Custom blocks, first class
A declarative inspector and a pure render function. Yours drag, bind, theme and print like ours.
- 09
Data stays yours
Schemas in, JSON out. Nothing is uploaded and the SDK makes no network calls of its own.
- 10
React, Angular, .NET
A framework-free core, thin wrappers, a render service behind HTTP and a .NET 8 client for it.
- 11
Versioned and migratable
Saved templates carry a schema version and migrate forward. Today's report opens next year.
- 12
Safe by design
Structured rich text instead of HTML, URL validation, SSRF-guarded fetching, feature flags for tiering.
Thirty lines to a designer. One call to a PDF.
Declare a schema, hand over sample data, mount. The designer gives you back a template as JSON; the renderer turns a template and live data into a file.
- @broadpaper/react and @broadpaper/angular, thin wrappers over one mount API.
- @broadpaper/forme, the browserless PDF engine, in the browser or in Node.
- @broadpaper/server, either PDF backend behind HTTP with a queue, a token and a Dockerfile.
- BroadPaper.Client for .NET 8, when the host is not JavaScript.
import { ReportDesigner } from "@broadpaper/react";
import { renderPdfPaginated } from "@broadpaper/forme";
const client = {
id: "client", label: "Client",
schema: {
fullName: { type: "string", label: "Full name" },
value: { type: "currency", label: "Portfolio value", currency: "GBP" },
holdings: { type: "array", label: "Holdings", itemSchema: holding }
}
};
export function Designer() {
return (
<ReportDesigner
dataSources={[client]}
sampleData={samples}
theme={meridian}
themes={[meridian, hartwell]}
onSave={(template) => api.save(template)}
/>
);
}
// Later, anywhere: the saved template plus live data → a vector PDF.
const { pdf } = await renderPdfPaginated({ template, data, theme: meridian, registry, dataSources }); Try it. No account, no upload.
A finished report, a blank page, three brands, a custom block, and a PDF rendered in your own browser.