Skip to content

Sample application

A complete application using the SDK the way you would: a designer in the browser, a read-only viewer, PDF export in the tab, and the same saved template rendered on a server by a .NET back end that has no browser on it.

github.com/codingbadger/broadpaper-sample-application

It comes in Angular and in React. They are the same application twice, against one shared back end — same API, same buttons, same three render paths — so the difference between them is Angular's and React's and never BroadPaper's.

angular/Angular 22, zonelessnpm start → :4200
react/React 19 on Vitenpm run start:react → :4300
api/ASP.NET Core on .NET 10owns the schema, the data and the saved templates
render-service/@broadpaper/serverthe engine, in a Node process

What it demonstrates

The template is the contract. A user lays a report out in the browser; the designer hands back JSON; the API stores it in a column. Nothing else crosses the boundary. The server later renders that JSON with live data and gets the same document, because the same paginator decided the breaks in both places.

Three routes to the same file. Export in the browser draws the PDF in the tab with WebAssembly and no server at all. Render on the server asks the .NET API, which calls the render service over its HTTP API. The viewer's print button gives the reader a third. All three agree, because all three are the same engine.

A .NET application producing PDFs with no JavaScript on it. BroadPaper.Client is an HTTP client for the render service, which is the Node process that owns the engine. That separation is the whole reason a C# host can produce these files without a browser, a JavaScript runtime, or a native PDF library.

The read-only viewer. The saved template as the person it was written for is given it — no palette, no panels, charts that answer a pointer. See the viewer.

It consumes the packages, not the source

Everything is installed from packed npm tarballs and a packed .nupkg, not from a source checkout wired in with path aliases. That is the point of it existing separately: inside a monorepo every import resolves to source, and a packaging fault is invisible until someone installs the built artefact into a real application.

Three were found that way, and all three are fixed:

  • @broadpaper/angular was bundled with tsup and shipped no Ivy definitions, so Angular rejected it outright. It is built with ng-packagr now.
  • Reaching the engine pulled in a WebAssembly ES module import that Angular's builder refuses under Zone.js, forcing hosts to go zoneless. @broadpaper/forme has a browser entry that instantiates the engine explicitly.
  • Installing the designer downloaded 14 MB of Chromium driver a browser cannot run. Playwright is an optional peer of @broadpaper/pdf now, and the browser-side helpers live in @broadpaper/renderer.

Running it

You need Node 20.19+ or 22.12+ and the .NET 10 SDK. The repository's README has the current instructions; in outline it is three commands, and the vendor step is what packs the SDK and installs it into every project.

The shape to copy

If you are wiring BroadPaper into your own application, the seven pieces are the same whichever framework you use:

  1. A schema your application owns, describing the data a report may bind to.
  2. Sample data, so the canvas is not empty while somebody designs against it.
  3. A mount<ReportDesigner>, <bp-report-designer> or createReportDesigner.
  4. A save, which is a PUT of the JSON the designer hands you.
  5. A load, through migrateTemplate, so an older document still opens.
  6. A render, on whichever side suits the job.
  7. A viewer, if the report is something people read rather than only download.

Nothing in that list is BroadPaper's decision except the third.