# Installation

Install compatible dependencies, configure the worker, and prepare a browser-only viewer.

Source: https://anara.com/lector/docs/installation

These docs describe the source deployed with this site, tracking main rather than a versioned npm release. Check your installed @anaralabs/lector and pdfjs-dist versions before applying examples.

## Install the packages

Use React 19 or later. The current Lector source expects `pdfjs-dist` `^5.5.207`; keep the PDF.js runtime and worker on the **same exact version**.

```bash
npm install @anaralabs/lector pdfjs-dist@^5.5.207
```

With pnpm, use `pnpm add @anaralabs/lector pdfjs-dist@^5.5.207`. Lector is an ES module package. Import it with `import`, and render the viewer in the browser.

## Configure the worker

The worker parses PDFs off the main thread. Configure it **before mounting `Root`**, using the same legacy PDF.js build that Lector loads internally.

The following setup works without a bundler-specific worker loader. From your application's directory, copy the worker into its public assets:

```bash
mkdir -p public/pdfjs
cp node_modules/pdfjs-dist/legacy/build/pdf.worker.min.mjs public/pdfjs/
```

Create `pdf-setup.ts` alongside your viewer:

```ts title="pdf-setup.ts"
import { GlobalWorkerOptions } from "pdfjs-dist/legacy/build/pdf.mjs";
import "pdfjs-dist/web/pdf_viewer.css";

GlobalWorkerOptions.workerSrc = "/pdfjs/pdf.worker.min.mjs";
```

Import `./pdf-setup` in your viewer module. Recopy the worker whenever you upgrade PDF.js, ideally as part of your app's build. If the app is served below a path prefix, include that prefix in `workerSrc`. Confirm that the worker URL returns JavaScript, not your app's HTML fallback.

### Let your bundler emit the worker

If your bundler supports package-relative asset URLs, you can replace the `workerSrc` assignment with:

```ts
GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/legacy/build/pdf.worker.mjs",
  import.meta.url,
).toString();
```

For Vite, an explicit asset import is another option:

```ts
import workerUrl from "pdfjs-dist/legacy/build/pdf.worker.min.mjs?url";

GlobalWorkerOptions.workerSrc = workerUrl;
```

Use one approach. The public-file approach is useful when your framework cannot resolve the package-relative URL. Check both development and production builds.

## Next.js: keep the viewer out of server rendering

A `"use client"` directive alone does not prevent a component from being prerendered on the server. Put your viewer and its `./pdf-setup` import in `pdf-viewer.tsx`, then load it from a separate Client Component:

```tsx title="pdf-viewer-client.tsx"
"use client";

import dynamic from "next/dynamic";

const PDFViewer = dynamic(() => import("./pdf-viewer"), {
  ssr: false,
  loading: () => <p role="status">Preparing PDF viewer…</p>,
});

export default PDFViewer;
```

Your route can import `PDFViewer` from this wrapper. Keep the PDF.js setup import inside the dynamically loaded viewer, so it is not evaluated on the server. In the Pages Router, import the PDF.js global stylesheet from `pages/_app.tsx` instead of `pdf-setup.ts`.

Next.js requires `ssr: false` to live in a Client Component. See [Next.js lazy loading](https://nextjs.org/docs/app/guides/lazy-loading#skipping-ssr) for the framework's rules.

## Styles and PDF assets

`pdfjs-dist/web/pdf_viewer.css` positions text and annotations over the canvas. Without it, text selection and links can be misplaced even when the PDF image looks correct.

The examples use inline styles for their layout; they do not require an application UI kit. Some optional Lector components, including the colored-highlight tools, use Tailwind utility classes internally. If you use those components, include the library's distributed JavaScript in your Tailwind content sources, or supply equivalent styles.

The worker is separate from PDF.js's fonts, character maps, image decoders, and color profiles. Lector defaults these auxiliary resources to versioned jsDelivr URLs. To serve all PDF assets from your own origin, follow [self-hosting PDF.js assets](https://anara.com/lector/docs/document-loading#self-host-pdfjs-assets).

## Verify the setup

Put a PDF at `public/sample.pdf` and open `/sample.pdf` directly to check that it is served correctly. Then follow [your first viewer](https://anara.com/lector/docs/basic-usage). You should see pages inside a scrollable container and be able to select text in a text-based PDF.

If you see an empty viewer or a worker error, use the [troubleshooting guide](https://anara.com/lector/docs/troubleshooting).
