0

Installation

How to install dependencies and structure your app.

pdfcn is distributed through shadcn/ui's registry system. Set up shadcn/ui in your project first by following the official installation guide for your framework.

Requirements

  • A project set up with shadcn/ui (Tailwind CSS v4 and React 19).
  • Components are built on embedpdf plugins and compose core shadcn/ui components. Both are installed for you by the CLI.
  • A bundler that can serve a .wasm file. The engine loads PDFium from your public/ folder.

Installing components

Every component can be installed with the shadcn CLI by pointing at this registry:

pnpm dlx shadcn@latest add pdfcn/viewer

Installing viewer pulls in its dependencies automatically — the use-engine hook, the pdfium.wasm binary, and the shadcn/ui components it composes. Each component's documentation page includes its exact install command, along with a manual installation option if you prefer to copy the source directly.

Rendering a document

<PdfViewer> provides the engine and the plugin registry; <PdfViewerContent> renders the page stack against it.

pnpm dlx shadcn@latest add pdfcn/viewer-content
import { PdfViewer } from "@/components/pdf-viewer";
import { PdfViewerContent } from "@/components/pdf-viewer-content";
 
export function MyViewer() {
  return (
    <PdfViewer documents={[{ url: "/sample.pdf" }]} className="h-[720px]">
      <PdfViewerContent />
    </PdfViewer>
  );
}

<PdfViewer /> fills its parent, so give it a height — it collapses to nothing without one.

The WASM binary

The use-engine item copies pdfium.wasm into your project's public/ folder, and usePdfEngine fetches it from /pdfium.wasm by default. Pass a wasmUrl to load it from somewhere else, such as a CDN:

const { engine } = usePdfEngine({
  wasmUrl: "https://cdn.example.com/pdfium.wasm",
});

How the engine runs PDFium in a Web Worker and loads that binary is embedpdf's; usePdfEngine is a thin shim over its usePdfiumEngine hook, documented in full there.

Adding chrome

Toolbars and sidebars read the active document from <PdfViewer>'s context, so they can be added anywhere inside the tree without extra props:

pnpm dlx shadcn@latest add pdfcn/toolbar pdfcn/zoom-controls
<PdfViewer documents={[{ url: "/sample.pdf" }]} className="h-[720px]">
  <PdfToolbar>
    <PdfPageNavigation />
    <PdfToolbarSeparator />
    <PdfZoomControls />
  </PdfToolbar>
  <PdfViewerContent />
</PdfViewer>

See Components for what's available and how each one is registered.