# react-pdf creates files, and a different library of the same name displays them

> The React renderer from diegomura builds PDF files from components, in a browser or on a server, and its README spends its first line steering readers away from the viewer library that shares its name. Behind the short README is a yarn and lerna monorepo that publishes each package separately and versions through changesets.

**diegomura/react-pdf** — 📄  Create PDF files using React

- Repository: https://github.com/diegomura/react-pdf
- Website: https://react-pdf.org
- Stars: 16,816 · Forks: 1,344
- Language: TypeScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/diegomura-react-pdf

## The name collides with a viewer library, so the first section is a warning

The README does not open with a feature list. It opens with a heading called Lost, and it draws a line between two projects that share the name react-pdf. This one creates PDFs using React. The other one, hosted at wojtekmaj on the same host, displays existing PDFs. That single paragraph is the most useful thing in the file, because a search for react-pdf returns both, and the import paths are not similar enough to catch the mistake: the creating package is scoped as @react-pdf/renderer, while the viewing package is a different project with its own repository and its own versions. If you are porting an example from a blog post, check which of the two you copied before you install anything, because the failure will not show up as a type error, it will show up as a missing viewer or a missing generator.

## One document tree, and two different places to put the result

The library gives you a small component vocabulary: Document, Page, Text, View, and a StyleSheet for the layout rules. What the tree produces depends on the entry point, and the README labels both paths as siblings. The Web path mounts the document in the DOM as a live viewer, wrapped in PDFViewer and attached to a root element with ReactDOM. The Node path calls ReactPDF.render with an element and a destination path built from __dirname, which writes the file. The document itself is unchanged between the two, so the same component can be previewed during development and emitted on the server. That is the design decision worth knowing: rendering is separated from output, and you choose the destination by choosing which function you import.

## Installation is a single yarn line, and the repository assumes yarn throughout

The whole install instruction is one command:

```sh
yarn add @react-pdf/renderer
```

There is no npm variant and no alternative package manager named anywhere in the README, which matters more than it sounds because the repository itself is built around yarn. The root manifest declares workspaces at packages/* and apps/examples, the lockfile is yarn.lock, and the dev script is written as a yarn workspace invocation rather than a generic run. There is also a .yarn directory and a .nvmrc at the top level, so the Node version and the package manager are both pinned by files a contributor never edits by hand. The practical consequence is that this is a yarn monorepo first: a team standardised on npm and pnpm will still be able to consume the published package, but cloning the repository to work on it means adopting the toolchain the project already chose.

## The root manifest is private, so its version number is not the one you install

The repository root package.json is named @react-pdf/root, is marked private, and sits at version 2.0.0. None of that describes what lands in your dependency tree, because a private manifest is never published and the version on it is the monorepo's own line. The versions you consume are per package, and the recent release history shows that: @react-pdf/types went to 2.14.0, @react-pdf/ui appeared at 1.0.0, and @react-pdf/tailwind is at 0.2.0, with all three published on the same day in late August 2026. So the packages are not in lockstep, and a project can hold 2.x of the types package while sitting on 0.x of the Tailwind package. Read versions from the individual packages, and expect the repository root to tell you nothing about the artifact in your lockfile.

## Publishing runs through changesets, which is why package versions move independently

The script block in the root manifest shows how the pipeline is wired. Builds go through lerna with run build, the watch and typecheck scripts fan out in parallel across workspaces, and prepublish runs the build again so a published package is never stale. Releasing is a three-step changesets flow: a changeset script to describe a change, version-packages to apply it, and release to publish. The repository carries a .changeset directory to hold those descriptions, so a version bump is a committed file rather than an edit to a manifest. Husky runs from the prepare script, which means a commit hook is installed on clone, and lint is scoped to the packages directory only, so the example application is built and typechecked but not held to the same lint rules as the library itself.

## Tests run on vitest across workspaces, with a native canvas binding in the toolchain

The test script is vitest, and the repository ships both vitest.config.js and vitest.workspace.js, which is the pattern for running several suites rather than one. Testing library packages that render React components needs @testing-library/react, and that is a dev dependency here alongside @napi-rs/canvas, a native binding for canvas work. The build path is rollup, assembled from plugins for Babel, CommonJS, JSON, node resolve, alias, replace, terser and TypeScript, and babel.config.js at the root holds the presets and transform plugins including class properties, optional chaining and nullish coalescing. The practical reading is that this is a component library with real output artefacts, not a wrapper over a single dependency, so its build cost sits with you when you upgrade, and its test coverage is organised per workspace rather than as one integration suite.

## Styles are created once as plain objects and handed to Page and View

The example in the README builds its layout with StyleSheet.create, which returns an object of named style objects rather than inline literals. The page style sets flexDirection to row and a background colour, and the section style sets margin, padding and flexGrow of 1. Two View children then use the same section style, which is the flexbox layout rule doing the work: two equally growing columns inside a row. Page takes a size prop with A4 as the value in the example. Nothing in that snippet requires a separate class name, a CSS file, or a build step, because the styles are objects that belong to the component tree. The consequence for a team is that a PDF layout cannot borrow the stylesheet the web view already has, so shared design tokens have to be converted into style objects, and any layout that depends on browser behaviour the renderer does not implement has to be rewritten rather than inherited.

## Conclusion

Use this package when a React application has to emit a PDF, in a page or on a server, and you want layout expressed with the same component model as the rest of your interface. Do not reach for it to show an existing document, because the README itself points you to a separate library for that, and the two packages share a name with opposite jobs. Before you commit, check which package you actually install and read the version there rather than the repository root, which is a private manifest at 2.0.0 that is never published, and check the date of the last commit on your default branch, which was 2026-09-23.

## FAQ

### What is react pdf renderer?

It is the scoped package @react-pdf/renderer, a React renderer for creating PDF files in the browser and on the server, built around Document, Page, Text, View and StyleSheet components. The README states plainly that it creates PDFs rather than displaying them.

### how to install react pdf renderer

The README gives a single command, yarn add @react-pdf/renderer. No npm command and no alternative package manager are named in the documentation.

### how to use react pdf renderer

Build a document component with Document, Page, Text and View plus styles from StyleSheet.create, then either mount it in the DOM inside PDFViewer through ReactDOM for the browser, or call ReactPDF.render with a destination path to write a file on the server.

### How to view a PDF in React?

For showing an existing PDF the README sends you to a separate project, react-pdf hosted at wojtekmaj, rather than this renderer. This package can render its own documents in a DOM viewer through PDFViewer, but it is not the library for displaying files you did not generate.

## Sources

- [diegomura/react-pdf on GitHub](https://github.com/diegomura/react-pdf)
- [License: MIT](https://github.com/diegomura/react-pdf/blob/master/LICENSE)
- [Project website](https://react-pdf.org)
- [README](https://github.com/diegomura/react-pdf/blob/master/README.md)
- [Releases](https://github.com/diegomura/react-pdf/releases)

---

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