# Getting started

Source: https://sdk.pdf.net/docs/v1/guides/getting-started



Our SDK is built around one idea: it owns the document, and you own the UI. The main component, `Viewport`, renders the pages and handles direct interaction with them (scrolling, zooming, selecting, typing). Everything around it, such as toolbars, sidebars, and shortcuts, is your own React code that drives the SDK through hooks: hooks that read document state re-render your components when that state changes, and hooks that return commands let you change the document.

> **Beta**: the SDK is in beta, and the exports and their APIs may change freely between releases. Pin the exact package version and review the changes when updating.

## Installation [#installation]

<!-- TODO: link "Registering an account" to the dashboard page where the token is issued. -->

The package is distributed through our private registry. Registering an account gets you an access token; configure npm to use it for the `@sdk-pdf` scope by adding an `.npmrc` next to your `package.json`:

```ini
@sdk-pdf:registry=https://registry.sdk.pdf.net
//registry.sdk.pdf.net/:_authToken=${PDF_NET_REGISTRY_TOKEN}
```

Keep the token out of version control: reference it through an environment variable as above. Then install:

```sh
npm install @sdk-pdf/react
```

### Other frameworks [#other-frameworks]

React is the first supported framework. Vue, Angular, and Svelte packages are coming soon. [Subscribe to the wishlist](https://forms.gle/m27HpbfwGbExcqrYA) to get notified when yours ships.

## Project setup [#project-setup]

The SDK runs in the browser and needs four things from your project:

* **The stylesheet.** Import `@sdk-pdf/react/style.css` once, in the module that renders `PdfProviders` (see the next section).
* **Client-only rendering.** With server rendering, such as the Next.js App Router, load the components that use the SDK in the browser only, for example with `next/dynamic` and `ssr: false`.
* **A canvas alias.** The package contains a Node-only code path that requires `canvas`. It never runs in the browser, but the bundler still has to resolve it, so alias `canvas` to a stub module. Other bundlers need the same alias.
* **React Strict Mode off.** Strict Mode's development double mount breaks the SDK: text styling and form widgets stop responding. Production builds are not affected, but turn it off so development behaves like production.

In Next.js, the configuration covers both bundlers:

```js
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,
  // Turbopack, the default bundler: point `canvas` at a stub module.
  turbopack: {
    resolveAlias: { canvas: './canvas-stub.js' },
  },
  // Webpack (`next build --webpack`): resolve `canvas` to an empty module.
  webpack: (config) => {
    config.resolve.alias = { ...config.resolve.alias, canvas: false }
    return config
  },
}

export default nextConfig
```

```js
// canvas-stub.js: the SDK never calls it in the browser.
export function createCanvas() {
  throw new Error('canvas is not available in the browser')
}

export default { createCanvas }
```

Then load the component that renders `PdfProviders` on the client only:

```tsx
'use client'

import dynamic from 'next/dynamic'

// ./pdf-app default-exports the component that renders PdfProviders.
const PdfApp = dynamic(() => import('./pdf-app'), { ssr: false })

export default function DocumentPage() {
  return <PdfApp />
}
```

## Set up the providers [#set-up-the-providers]

Everything in the SDK lives under `PdfProviders`. It hosts the document state and accepts the PDF application configuration, such as theming and interaction behavior (see [PdfProviders](https://sdk.pdf.net/docs/v1/reference/PdfProviders) for all props).

```tsx
import { useMemo } from 'react'
import { CONTENT_POLICY_PRESET, PdfProviders } from '@sdk-pdf/react'
import '@sdk-pdf/react/style.css'

export function App({ viewportPadding }: { viewportPadding: number }) {
  // The PDF app re-renders whenever a `PdfProviders` prop changes identity, so always
  // memoize the configuration.
  const config = useMemo(
    () => ({
      theme: { viewportPadding },
      initialInteractionTool: { type: 'textSelect' } as const,
      initialContentPolicy: CONTENT_POLICY_PRESET.PDF_VIEWER,
    }),
    [viewportPadding]
  )

  return (
    <PdfProviders {...config}>
      {/* Every SDK hook and component must be rendered inside `PdfProviders` */}
      <DocumentLoader />
    </PdfProviders>
  )
}
```

## Load a document [#load-a-document]

The document bytes can come from anywhere: a file input, a fetch, drag-and-drop. `useLoadPdf` gives you `loadPdf` to feed them in, and the load state to decide what to render while the document isn't there yet:

```tsx
import { InvalidPasswordError, useLoadPdf } from '@sdk-pdf/react'

function DocumentLoader() {
  const [loadState, loadPdf] = useLoadPdf()

  async function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.currentTarget.files?.[0]
    if (!file) return

    const data = new Uint8Array(await file.arrayBuffer())

    try {
      await loadPdf(data)
    } catch (error) {
      if (error instanceof InvalidPasswordError) {
        // The password is missing or wrong: show a password prompt
        // and retry loadPdf with the entered password.
      }
    }
  }

  if (loadState.status === 'initial') {
    return <input type="file" accept=".pdf" onChange={handleFileChange} />
  }

  if (loadState.status === 'loading') {
    return <p>Loading the document…</p>
  }

  return <PdfApplication />
}
```

## Render the viewport [#render-the-viewport]

Once the document is ready, render `Viewport`, the scrollable and zoomable area that displays and edits the pages:

```tsx
import { useViewportAutoFitScale, Viewport } from '@sdk-pdf/react'

function PdfApplication() {
  // The PDF application drives the SDK through hooks: this one keeps the page scale
  // fitted to the viewport width.
  useViewportAutoFitScale('width')

  return (
    <div style={{ height: '100vh' }}>
      {/* Throws DocumentNotLoadedError when no document is loaded, since there is nothing
          to show. Render it only when the load state is 'ready'. */}
      <Viewport />
    </div>
  )
}
```

`Viewport` fills its parent element, so give the parent an explicit size. It handles page rendering, scrolling, zooming, selection, and text editing on its own; your UI around it drives the behavior through hooks.

## Next steps [#next-steps]

* [Building a PDF application](https://sdk.pdf.net/docs/v1/guides/building-a-pdf-application): the parts of a PDF application and the hooks that serve them.
* [Working with forms](https://sdk.pdf.net/docs/v1/guides/working-with-forms): reading and creating widgets, filling fields, field formats.

