Skip to content
Back to blog
engineering

Why we chose browser-based rendering

PDF libraries reimplement layout. Browsers already got it right. Here's the reasoning behind building Tupsara on Chromium instead of a custom PDF engine.

Tupsara Team

2 min read

Ask a developer who has generated PDFs from an application before, and you’ll usually get a wince. Not because PDFs are conceptually hard — a PDF is just a page of content with fixed layout — but because most PDF libraries ask you to describe that layout in a dialect that only exists inside the library. Tables that behave differently than HTML tables. A subset of CSS, undocumented at the edges. Fonts that render fine locally and subtly wrong once deployed. None of it maps cleanly to the skills a web developer already has.

We built Tupsara on the opposite assumption: don’t reimplement a layout engine. Use one that already works.

The layout engine already exists

Every developer who has ever built a web page already knows how to lay out a document with HTML and CSS. Flexbox, grid, tables, @page rules, custom fonts, SVG, background images — all of it is mature, well-documented, and battle-tested across billions of pages. A browser’s rendering engine has had decades of investment poured into getting layout, typography, and print output right.

So instead of asking developers to learn a second, PDF-specific way to describe a document, Tupsara takes the HTML and CSS they already write and renders it in a real browser engine — initially Chromium — then captures the result as a PDF. The mental model doesn’t change. If it looks right in a browser preview, it looks right in the PDF.

What this actually removes

The traditional path looks roughly like this:

Design
↓
PDF-specific layout
↓
Limited CSS
↓
Font issues
↓
Table issues
↓
Maintenance

Every one of those steps is a place where a PDF library’s abstraction leaks. Limited CSS support means you either avoid modern layout techniques or fight the library to approximate them. Font issues mean you’re debugging embedding and subsetting instead of building your product. Table issues mean a library’s table model doesn’t match what you designed in the browser. And all of it compounds into an ongoing maintenance burden, because every library upgrade risks changing how existing templates render.

The Tupsara path collapses that into three steps:

HTML
+
CSS
↓
Browser
↓
PDF

There’s no separate PDF dialect to learn, because there isn’t one. The browser is the renderer, the same as it always was.

Where this is going

Chromium is the initial rendering engine, and it’s a deliberate first choice — it’s the engine most developers already test against day to day. But the architecture isn’t tied to Chromium specifically. Tupsara is designed to support additional rendering engines over time, for teams that need to validate output against more than one browser’s rendering behavior. We’re not there yet, and we won’t claim otherwise — but the API surface (HTML and CSS in, a PDF out) doesn’t change either way.

That’s the bet: the browser was already the best PDF renderer available. We just had to put an API in front of it.