React PDF Viewer

A plugin-based React component, built on pdf.js, for viewing and interacting with PDF documents.

Library
npm
v3.12.0
2,604stars
Commercial (source-available, requires purchased license)

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance44
Community48
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture84
Code Quality85
Innovation78
Learning Curve55

React PDF Viewer’s core package renders PDF documents inside React applications by wrapping Mozilla’s pdf.js. It exposes a single Viewer component that consumers extend through a plugin system: separate npm packages (toolbar, zoom, search, thumbnail, print, bookmark, and more) each register lifecycle hooks and share state through a lightweight pub/sub store, so an app can compose exactly the reader features it needs rather than pulling in a monolithic viewer.

The library is written entirely in TypeScript with React hooks, supports SSR, virtualized page rendering, password-protected documents, theming and dark mode, RTL layouts, and localization. It’s free to use in the source-available repository, but the project’s license requires purchasing a commercial license for use, distinguishing it from typical MIT-licensed React libraries.

What You Get

  • A core Viewer component that loads and renders PDF pages from a URL or byte array, with virtualized rendering so only visible pages mount
  • Two dozen official plugin packages (toolbar, default-layout, zoom, search, thumbnail, print, bookmark, attachment, rotate, highlight, and others) that can be mixed and matched per app
  • A typed Plugin interface (install/uninstall, renderViewer, renderPageLayer, onDocumentLoad, onViewerStateChange) for writing custom plugins against the same lifecycle the official ones use
  • Built-in support for password-protected PDFs, print, full-screen mode, dark/light theming, right-to-left layouts, and string localization
  • SSR-safe rendering, verified against both Webpack and Next.js demo apps included in the monorepo

Common Use Cases

  • Embedding an in-app document viewer for reports, invoices, or contracts without leaving the page
  • Building a custom PDF toolbar (zoom, page navigation, search, download) by composing only the plugins an app needs
  • Viewing password-protected or access-controlled PDFs with custom authentication headers
  • Adding PDF preview to admin dashboards, document-management tools, or content platforms
  • Rendering PDFs inside SSR frameworks like Next.js where the viewer must hydrate cleanly on the client

Under The Hood

Architecture The core Viewer component (packages/core/src/Viewer.tsx) composes a DocumentLoader (which owns the pdf.js document-loading state machine — loading, password-prompt, failure, completed) with an Inner layout that virtualizes page rendering via PageSizeCalculator and a render-range callback. Extensibility comes from a Plugin interface (packages/core/src/types/Plugin.ts) with optional install/uninstall/renderViewer/renderPageLayer/onDocumentLoad/onViewerStateChange hooks; each of the ~20 sibling packages (toolbar, zoom, search, thumbnail, print, bookmark, etc.) is an independently published plugin exposing a factory function (e.g. defaultLayoutPlugin()) that returns a Plugin object, optionally declaring dependencies on other plugins. Cross-plugin communication happens through a minimal pub/sub store (packages/core/src/store/createStore.ts) that plugin instances subscribe to and update, avoiding a shared global state library. This gives a genuinely modular, event-driven composition where an app only pays for the plugins it imports.

Tech Stack Entirely TypeScript with React (peer dependency >=16.8.0) built on React hooks; pdf.js is injected by the consumer through a PdfJsApiContext rather than bundled directly, keeping the core package decoupled from a specific pdf.js version. The monorepo (20+ packages under packages/*) is orchestrated with Turborepo and npm workspaces, built per-package with Rollup plus esbuild, and styled with CSS Modules processed through PostCSS. Demo apps under demo/webpack and demo/nextjs exercise both a plain Webpack setup and Next.js SSR to validate real-world integration.

Code Quality The repo has extensive test coverage — 92+ Jest test files across packages, including Puppeteer-driven end-to-end tests (jest-e2e.config.ts) that render real PDFs from the samples/ directory and assert on DOM/visual behavior (rotation, zoom, password prompts, strict-mode compatibility, RTL). Per-package tsconfig.json files enable strict: true, and ESLint is configured with @typescript-eslint plus plugin:react/recommended. Naming and file organization are consistent across all plugin packages (each mirrors the same src/ layout), and error states (load failure, missing PDF, wrong password) are modeled as explicit typed states rather than caught-and-swallowed exceptions.

What Makes It Unique Most React PDF-rendering libraries expose one large configurable component; this project instead ships each toolbar feature (zoom, search, thumbnails, printing, bookmarks, attachments, highlighting) as its own independently installable plugin package sharing one small store contract, letting consumers assemble a custom reader UI with only the code paths they use. The trade-off is the project’s licensing: unlike most npm libraries, using it beyond evaluation requires purchasing a commercial license from the maintainer.

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

Search