react-pdf

Build complex, print-ready PDF documents in React using familiar components and a flexbox-based layout engine, in the browser and on Node.

Library
npm
v4.9.0
16,841 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
90 /100 Excellent
Development Activity 96
Maintenance 96
Community 68
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
88 /100 Excellent
Architecture 85
Code Quality 85
Innovation 90
Learning Curve 90

react-pdf renders declarative React component trees — Document, Page, View, Text, Image, Svg — into PDF files, using a custom React reconciler (@react-pdf/reconciler) and a Yoga-style flexbox layout engine (@react-pdf/layout) to produce print-ready output. It runs identically in the browser (rendering to a Blob/iframe via PDFViewer, BlobProvider, PDFDownloadLink, or usePDF) and on Node/server (streaming or writing a file directly), backed by pdfkit for the underlying PDF primitives.

The library is split into a dozen focused sub-packages inside one Yarn/Lerna workspace — layout, render, font, svg, stylesheet, textkit, paginate, hyphenate — each handling one piece of the pipeline: measuring text, embedding fonts, wrapping content across pages, drawing borders/backgrounds, and rasterizing SVG. This modularity keeps @react-pdf/renderer itself a thin orchestration layer while the supporting packages do the heavy lifting, giving teams with invoicing, reporting, and document-generation needs a React-native way to produce PDFs without learning a separate templating DSL.

What You Get

  • Declarative document API - Document, Page, View, Text, Image, Svg, and Link components map directly to areas of a print-ready PDF.
  • Flexbox-based layout engine - automatic pagination, text wrapping, and orphan/widow control powered by @react-pdf/layout and @react-pdf/textkit.
  • Dual-runtime rendering - render to a Blob/iframe in the browser (PDFViewer, BlobProvider, PDFDownloadLink, usePDF) or stream/save a file on Node (ReactPDF.render, renderToStream, renderToFile).
  • Custom font embedding - register TTF/OTF/WOFF fonts, including bold/italic variants and Unicode/emoji/RTL support, via @react-pdf/font and @react-pdf/hyphenate.
  • SVG and vector drawing primitives - Svg, Path, Circle, Rect, and related components for charts, logos, and custom graphics inside a document.

Common Use Cases

  • Invoices and receipts - generate itemized, branded PDF invoices server-side from order data at checkout or on a billing cron job.
  • Report and dashboard export - let users download a formatted PDF snapshot of a data view or analytics dashboard straight from the browser.
  • Certificates and letters - produce personalized certificates, contracts, or form letters by templating one Document per recipient.
  • Resume/CV and proposal builders - power WYSIWYG document builders where the React component tree is the single source of truth for both the on-screen preview and the exported PDF.

Under The Hood

Architecture

A pdf() call creates a container and mounts the React tree through createRenderer (a react-reconciler instance backed by @react-pdf/reconciler); calling render() then hands that mounted tree to layoutDocument (@react-pdf/layout), which computes flexbox measurement and pagination, and the resulting layout is walked by renderPDF (@react-pdf/render) to issue drawing calls into a pdfkit PDFDocument. The whole pipeline is exposed through toBlob/toBuffer/toString/an on('change') emitter for browser live-preview or Node file/stream output. The structure is a modular pipeline — renderer (thin orchestration) → reconciler (tree mounting) → layout (measurement/pagination) → render (drawing) → font/svg/stylesheet/textkit (support services) — each its own workspace package with a narrow contract; the internal layout-tree shape is shared across reconciler, layout, and render, so changing that representation ripples through all three packages’ test suites, while the React-facing component API stays decoupled and stable.

Tech Stack

TypeScript-oriented via hand-maintained ambient declarations (index.d.ts) over Babel-transformed JS source, Yarn 1 workspaces plus Lerna for monorepo versioning, Rollup for building each package’s ESM/CJS/browser bundles, Changesets for release notes and publishing, Vitest (with a separate browser-mode Vitest config) and @testing-library/react for testing, pdfkit as the low-level PDF writer, a peer dependency on React ^16–^19 keeping it version-agnostic across React majors, and GitHub Actions workflows (lint, test, release, docs-site deploy) for CI.

Code Quality

An extensive Vitest suite in packages/renderer/tests/ covers dozens of scenarios — transforms, pagination/resume, DOM components, named destinations, floats, text wrapping, emoji, borders, images, orphan text, links, srcSet, and PDF conformance — exercising both Node rendering and browser/DOM behavior (BlobProvider, PDFViewer, PDFDownloadLink). ESLint (typescript-eslint, eslint-plugin-react) and Prettier run via Husky/lint-staged pre-commit hooks and a dedicated CI lint job; error handling favors explicit deprecation warnings and a guarded options object over silent failures. Overall a tested, linted, CI-gated codebase.

API Design The public API mirrors plain React/DOM idioms almost exactly — Document, Page, View, Text, Image, Link, Svg — so anyone who already knows React can produce a PDF without learning a new templating syntax. StyleSheet.create plus a CSS-flexbox-subset stylesheet format reuses familiar web styling mental models, and helpers like usePDF, PDFViewer, BlobProvider, and PDFDownloadLink cover common browser integration boilerplate so most consumers never touch the imperative render()/toBlob()/toBuffer() calls directly. On Node, ReactPDF.render/renderToStream/renderToFile mirror ReactDOM’s naming for consistency across environments — the same React mental model on both the browser-preview side and the server-generation side is the library’s core differentiator versus screenshot-based or templating-language approaches to PDF generation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers