# htmldocs renders PDF pages in Chromium instead of a layout engine

> htmldocs is a Next.js based template tool that builds PDF documents as React components, and its differentiator is that the output is produced by a real browser engine, which is what makes CSS features the alternatives cannot support work at all.

**htmldocs-js/htmldocs** — The modern alternative to LaTeX. Create PDF documents templates using React, JSX, and Tailwind

- Repository: https://github.com/htmldocs-js/htmldocs
- Website: https://htmldocs.com
- Stars: 749 · Forks: 30
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/htmldocs-js-htmldocs

## The pitch is that document generation is stuck in the past

The readme opens with a claim about the state of the field, that PDF document creation is stuck in the past, from clunky Word docs to complex LaTeX to outdated tools, and that htmldocs brings document generation into 2025 with a modern developer experience using React, TypeScript and Tailwind. The description of what the tool is, is precise. It is a local document editor and preview server to help you create PDFs with React, providing the structural benefits of LaTeX with the familiarity of HTML and CSS. You build document templates, such as invoices, reports or contracts, in JSX and generate PDFs by passing data as props. The listed capabilities are the latest CSS features such as margin boxes and flexbox, a collection of unstyled components to help you lay out the document, a JSX templating system, full TypeScript support, dynamic data integration through props and APIs, and a real-time preview server with hot reloading.

## The document is a React component with data as props

The example shows a dynamic invoice template, and the point of it is that changing the data does not mean changing the template. To change the customer details, you render the Invoice component with different props.

```tsx
<Invoice 
  customer={{
    name: "John Doe",
    address: "456 Main St",
    city: "Anytown",
    state: "CA",
    zip: "12345",
    phone: "123-456-7890",
  }}
  items={items}
/>
```

That is the whole programming model, and it is the same one a developer already uses for a web page, with two differences that matter for documents. The first is that the data is the variable part and the layout is the fixed part, which is what makes a document template reusable across customers. The second is the TypeScript support, so a change to the props of a document component is a compile error rather than a blank field in a PDF. The readme also shows a variables editor and a resume example in the screenshots, which is the same idea applied to a different kind of document.

## Chromium is the renderer, and that is the whole difference

The mechanism section is the most important part of the readme for anyone deciding between tools. htmldocs is built upon Chromium's rendering engine, which means it can render any HTML, CSS and JavaScript, and the readme contrasts this with other tools such as wkhtmltopdf, WeasyPrint and Prince, which only support a subset of HTML and CSS. That is a bigger difference than it sounds, because a subset implementation has to choose, and its choices are not the ones a web developer would expect. The project also uses the Paged.js library under the hood, and Paged.js is used for layout and chunking as well as for more modern features such as margin boxes, which are not fully supported by the W3C's CSS standard. So the pipeline is a browser, plus a paged media polyfill on top of it, and the output is a paginated PDF.

## Six layout components, deliberately unstyled

The component set is small, and the readme is explicit that these are unstyled components to help you lay out and style your documents. There is Document, which sets up the page frame, Head, Page, Footer, MarginBox for the running content in the page margins, and Spacer. MarginBox is the one that only exists because of the Chromium approach, since it is the feature that the W3C CSS standard does not fully support and that Paged.js supplies. The screenshots show a resume example and a variables editor, so the intended workflow appears to be authoring a document in a local editor with live preview and filling the variables from data rather than editing the document by hand for each run.

## A monorepo with Turborepo, pnpm and changesets

The repository is a pnpm workspace with Turborepo, an apps/ directory, a packages/ directory, a turbo.json, a global.css and a pnpm-workspace.yaml. The root package.json names the package htmldocs, marks it private and sets the type to module, with the build running turbo across the packages and explicitly filtering out the htmldocs-starter package, the dev running turbo dev, the lint running turbo lint, and the test running turbo test. Formatting is prettier over TypeScript, TSX and Markdown files, and releases go through changesets, with the version script running changeset version followed by an install with a non-frozen lockfile. The publish configuration points the registry at the GitHub npm registry rather than the public one, which is a detail that matters if you are trying to install the published package. Node 20 or newer is required, and the test stack is Vitest with happy-dom and V8 coverage, so the components are tested in a simulated DOM rather than in a browser.

## Where this is the wrong choice

The first limit is the one the readme's own comparison table states. Traditional documents and freeform design tools have a simple learning curve and live preview, but limited template variables, limited version control and limited automation, while htmldocs wins on template variables, type safety, version control and CI/CD integration, and LaTeX matches it on structure and external library support but has a complex learning curve. Where LaTeX beats it is the point: htmldocs gives you structured content in a familiar language, and it gives up the reproducibility and the typographic depth of a dedicated typesetting system. A long book or an academic paper with complex cross-references is not what this tool is for. The second limit is the dependency on a browser engine, since a headless Chromium is a heavy runtime to require in a CI job that generates thousands of documents, and the readme does not describe a headless mode, a container image or a throughput figure. The third is that the component set is a layout kit rather than a design system, so an organisation that already has house typography will find little here to reuse, and the fourth is maturity, with the default branch named canary and no tagged releases, so the published npm version and the working tree are not the same thing.

## Conclusion

htmldocs suits a developer who already writes React and wants to generate an invoice, a report or a contract from a component rather than from a Word template, and it suits anyone who needs CSS features that a print-oriented renderer would not implement. It is the wrong tool for a publishing pipeline that needs a LaTeX document or a reproducible long book, since the output depends on a browser rendering rather than a fixed typesetting engine, and it is the wrong choice if you need to match a Word template pixel for pixel. Before adopting it, check the component list against the document you have to produce, since the built in components are a small set of layout primitives rather than a full design system, and read the Getting Started guide before integrating it into an existing project. The last push was on 2026-08-18 and the repository publishes no releases.

## FAQ

### How do I create a project with htmldocs?

Run npx htmldocs@latest init to create your first htmldocs project. For further instructions or to integrate htmldocs into an existing project, the README points at the Getting Started guide in the documentation.

### Which components does htmldocs provide?

A standard set of unstyled components for laying out documents: Document, Head, Page, Footer, MarginBox and Spacer. MarginBox exists because margin boxes are not fully supported by the W3C CSS standard and are supplied through Paged.js.

### How does htmldocs differ from wkhtmltopdf or WeasyPrint?

htmldocs is built on Chromium's rendering engine, so it can render any HTML, CSS and JavaScript, while wkhtmltopdf, WeasyPrint and Prince only support a subset of HTML and CSS. It also uses Paged.js under the hood for layout, chunking and margin boxes.

## Sources

- [htmldocs-js/htmldocs on GitHub](https://github.com/htmldocs-js/htmldocs)
- [Issues](https://github.com/htmldocs-js/htmldocs/issues)
- [License: MIT](https://github.com/htmldocs-js/htmldocs/blob/canary/LICENSE)
- [Project website](https://htmldocs.com)
- [README](https://github.com/htmldocs-js/htmldocs/blob/canary/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/htmldocs-js-htmldocs
