# Your first viewer

A complete viewer with selectable text, page and zoom controls, and explicit layout.

Source: https://anara.com/lector/docs/basic-usage

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.

Complete the [installation](https://anara.com/lector/docs/installation) first. This example imports the `pdf-setup.ts` you created there and loads `public/sample.pdf`. In Next.js, render it through the browser-only wrapper from that guide.

## A viewer you can build on

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

import {
  CanvasLayer,
  CurrentPage,
  CurrentZoom,
  Page,
  Pages,
  Root,
  TextLayer,
  TotalPages,
  ZoomIn,
  ZoomOut,
} from "@anaralabs/lector";
import "./pdf-setup";

export default function PDFViewer() {
  return (
    <Root
      source="/sample.pdf"
      isZoomFitWidth
      style={{ height: 600, display: "flex", flexDirection: "column" }}
      loader={<p role="status">Loading PDF…</p>}
    >
      <div
        role="group"
        aria-label="PDF controls"
        style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: 8, padding: 8 }}
      >
        <label>
          Page <CurrentPage style={{ width: 56 }} />
        </label>
        <span>of</span>
        <TotalPages />
        <ZoomOut type="button" aria-label="Zoom out">−</ZoomOut>
        <label>
          Zoom <CurrentZoom style={{ width: 56 }} /> %
        </label>
        <ZoomIn type="button" aria-label="Zoom in">+</ZoomIn>
      </div>
      <div style={{ flex: 1, minHeight: 0 }}>
        <Pages>
          <Page>
            <CanvasLayer />
            <TextLayer />
          </Page>
        </Pages>
      </div>
    </Root>
  );
}
```

`CurrentPage` and `CurrentZoom` are editable inputs, so they need labels. The zoom buttons have no default text; supply their children. `CurrentPage` commits when the input loses focus or you press Enter.

## How the pieces fit

```text
Root                     Loads one document and provides its store
├── Your toolbar         Reads and changes that document's state
└── Pages                Owns the scroll container and virtualizes pages
    └── Page             A template cloned for each visible page
        ├── CanvasLayer  Paints the page
        └── TextLayer    Adds selectable text over the canvas
```

Pass **one `Page` template** to `Pages`. It supplies the page number; you do not map over the document yourself. Page numbers in Lector's public navigation APIs start at **1**.

`Root` only mounts its children after the document and page viewports are ready. Components using `usePdf`, `usePdfJump`, or other viewer hooks must be descendants of `Root`. Page-specific layers and `usePDFPageNumber` also need a `Page` ancestor. A hook in the same component that *returns* `Root` is still outside that provider.

## Give the pages room to scroll

`Pages` defaults to `height: 100%` and owns its scrolling. Give its parent a definite height. With a toolbar, use a flex column and put `Pages` in a `flex: 1; min-height: 0` wrapper, as above. In a sidebar layout, also set `min-width: 0` on the viewer column.

Avoid overriding `Page` dimensions or applying your own scale transform: Lector uses its viewports to align canvas, text, and highlights.

## Choose your layers

| Layer                   | Adds                                             | Guide                                                                                                   |
| ----------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| `CanvasLayer`           | Visible PDF content                              | [Basic example](https://anara.com/lector/docs/code/basic)                                               |
| `TextLayer`             | Selection and copying when the PDF contains text | [Text selection](https://anara.com/lector/docs/code/select)                                             |
| `AnnotationLayer`       | Existing PDF links and form widgets              | [Links](https://anara.com/lector/docs/code/links), [forms](https://anara.com/lector/docs/code/pdf-form) |
| `HighlightLayer`        | Rectangles from the viewer's `highlights` state  | [Highlights](https://anara.com/lector/docs/code/highlight)                                              |
| `ColoredHighlightLayer` | Selection color tools and colored highlights     | [Text selection](https://anara.com/lector/docs/code/select#saving-highlights)                           |

Place canvas first, then text, then the interaction or highlight layers you need. Loading failures need application UI outside `Root`; see [loading and errors](https://anara.com/lector/docs/document-loading#show-errors-and-retry).

Next, add [page navigation](https://anara.com/lector/docs/code/page-navigation), [search](https://anara.com/lector/docs/code/search), or [dark mode](https://anara.com/lector/docs/dark-mode).
