Skip to content
Back to blog
typst latex pdf generation engineering

Typst vs LaTeX for Generating Documents from Data

pdfs.build Team

Most Typst vs LaTeX comparisons are written by and for people writing papers. That is a fine debate, but it is not the one that matters if you are picking a typesetting engine for a system: something that takes JSON and produces ten thousand invoices, certificates, or reports a month without a human looking at each one. We run Typst in production for exactly that job, and this is the comparison we wish had existed when we chose.

Where the two come from

LaTeX is fifty years of accumulated typesetting wisdom. It is the reason the bar for “what a professionally set document looks like” is as high as it is, and for academic publishing it remains the standard for good reasons: journals accept it, every citation style exists for it, and its mathematical typesetting has been polished for decades.

Typst is a modern reimplementation of the same ambition: a compiled markup language with real typographic quality, designed this decade, written in Rust. It is not a LaTeX clone. It is what you get when you keep the goals and drop the legacy.

For interactive writing, taste can decide. For generating documents from data, the differences stop being taste and start being operational.

Compile speed changes what you can build

A LaTeX document compiles in seconds, and multi-pass resolution (references, tables of contents) can mean compiling more than once. That is fine for a paper you compile a hundred times a day by hand. It is a problem for an API that renders on request: seconds per document means queues, workers, and capacity planning.

Typst compiles typical business documents in milliseconds and resolves layout incrementally. That single property is what makes a synchronous render endpoint feasible: POST the data, get the PDF in the same request. It also makes a live preview practical, recompiling on every keystroke, which LaTeX tooling approximates but never quite reaches.

Data is a native concept, not an import

The job “take this array of line items and make table rows” looks like this in Typst:

table(
  columns: (1fr, auto, auto),
  table.header[Description][Qty][Price],
  ..items.map(i => (i.description, str(i.qty), str(i.price))).flatten()
)

Typst has real data structures: arrays, dictionaries, functions, string methods. JSON maps onto it directly. Loops and conditionals are ordinary code, not macro expansion.

LaTeX can do all of this, but honestly assessed, it does it through layers: macro programming with its famously opaque expansion rules, or escaping out to an external templating language that pastes strings into .tex source and hopes the escaping holds. Every LaTeX-based generation pipeline we have seen ends up with that second layer, and the second layer is where the injection bugs and the mystery compile errors live.

Error messages you can act on

When generated LaTeX fails, it fails with the error messages LaTeX is famous for: an overfull hbox here, a cryptic Undefined control sequence pointing somewhere other than the actual mistake. A human can develop intuition for these. A system cannot: if your pipeline generates a broken document at 3am, the error had better say what is wrong and where.

Typst produces compiler errors with source spans, in the tradition of modern language tooling. This matters doubly when an LLM writes template code: our repair loop feeds compiler diagnostics back to the model, and that loop works largely because Typst’s diagnostics are precise enough to act on mechanically.

Operational weight

A full TeX Live installation is measured in gigabytes, and “which packages does this template actually need” is a real question with real wrong answers. Reproducing an identical environment across a build server, a preview environment, and a developer laptop is its own project.

Typst is a single binary with packages fetched on demand. We run the same engine version in three different forms, as a native library, a Node compiler, and WebAssembly in the browser, and keeping them aligned is a discipline we maintain deliberately, but it is a discipline measured in version pins, not in gigabytes of TeX distribution.

Where LaTeX still wins

An honest comparison has a column for this.

Academic publishing. If the output goes to a journal, LaTeX is the format the journal accepts and the ecosystem is built around that. Use LaTeX.

Depth of mathematical typesetting. Typst’s math mode is genuinely good and improving fast, but LaTeX’s coverage of edge cases, niche notation, and decades of package solutions is not matched yet.

Ecosystem breadth. There is a LaTeX package for everything, including things there probably should not be a package for. Typst Universe is growing quickly but it is years, not months, from that surface area.

Institutional templates. Thesis classes, conference styles, government document classes: if a required template exists only as a .cls file, that decides it.

None of these columns matter much for invoices, quotes, reports, and certificates generated from application data. That is not a knock on LaTeX; it is just not the job LaTeX’s strengths line up with.

What we chose and why

pdfs.build compiles every document with Typst: it is what makes millisecond renders, schema-validated data binding, browser-side live preview, and machine-actionable compile errors possible in one coherent system. The Typst API page covers what running it as a service looks like, and if your starting point is HTML-to-PDF rather than LaTeX, the headless browser comparison is the companion piece to this one.

If you are already writing Typst by hand, you can bring your templates to the API as they are. And if you are maintaining a LaTeX generation pipeline that mostly works, we would never tell you to rewrite it today. But if you are choosing fresh in 2026, for documents driven by data, we think this comparison only points one way.

Back to blog