---
title: "Headless — Svelte"
description: "Build your own PDF viewer from plugins, components and hooks, in React, Vue, Svelte or Angular."
framework: "Svelte"
source: "https://www.embedpdf.com/docs/headless/svelte"
---

# Build your own PDF viewer

The headless packages give you everything a PDF viewer does, without a look of their own: pages
that scroll and zoom, crisp rendering, text selection and search, annotations, forms and
signatures. You build the interface in Svelte, and nothing appears on screen unless you put
it there.

**`overview.svelte`**

```svelte
<script lang="ts">
  import { DocumentGate, Viewer } from '@embedpdf/svelte/runtime';
  import { Stage, stagePlugin } from '@embedpdf/svelte/stage';
  import { RenderLayer, renderPlugin } from '@embedpdf/svelte/render';
  import { localEngine } from '@embedpdf/engine';

  const engine = localEngine();
  const plugins = [stagePlugin(), renderPlugin()];
</script>

<Viewer {engine} {plugins} initialDocuments={[{ source: { kind: 'url', url: '/contract.pdf' } }]}>
  <DocumentGate>
    {#snippet fallback()}
      <p>Opening…</p>
    {/snippet}
    <Stage style="height: 600px">
      <RenderLayer />
    </Stage>
  </DocumentGate>
</Viewer>
```

That's a complete viewer: the pages scroll, zoom with a pinch or Ctrl and the wheel, and stay sharp
at every zoom. Everything else is a plugin you add, and a few lines of your own UI.

## Headless or the ready-made Viewer?

EmbedPDF comes in two forms, built on the same engine and plugins:

- **The [Viewer](https://www.embedpdf.com/docs/viewer/svelte)** is finished: a toolbar, sidebars, annotation tools and search,
  ready in minutes. You configure it and theme it.
- **Headless** is the parts: you decide what the toolbar looks like, where the search box goes, and
  what happens when someone clicks an annotation.

Choose headless when the viewer is part of your product's own interface. You can start with the
Viewer and move to headless later: the plugins and their options are the same.

## How it's put together

A headless viewer has five parts. You meet them on every page:

- **The engine** opens and reads PDF files. It runs in the browser, or on your server with
  CloudPDF.
- **`<Viewer>`** starts the engine, opens documents, and holds the plugins.
- **Plugins** add one feature each: search, annotations, forms. Register the ones you need; the
  rest never reach your bundle.
- **Layers** draw inside each page: the page itself, the text selection, the annotations.
- **Functions** connect your own UI: `useSearch()`
  to search, `useSearchState()` to show the results, `useSearchEvent()` to react when something
  happens.

[How it works](concepts/how-it-works) explains each in a few minutes.

## Every plugin

Each plugin is one import line. Registering a plugin and importing its components come from the
same place:

| Plugin                                   | What it gives you                                        | Import from                     |
| :--------------------------------------- | :------------------------------------------------------- | :------------------------------ |
| [Stage](viewing/stage)                   | Scrolling, zoom, layouts, page navigation                | `@embedpdf/svelte/stage`        |
| [Render](viewing/render)                 | Sharp pages at every zoom, deep-zoom tiles               | `@embedpdf/svelte/render`       |
| [Links](viewing/links)                   | Clickable links to pages and websites                    | `@embedpdf/svelte/link`         |
| [Selection](text/selection)              | Selecting and copying text                               | `@embedpdf/svelte/selection`    |
| [Search](text/search)                    | Finding text, and showing every match                    | `@embedpdf/svelte/search`       |
| [Annotations](annotations)               | Highlights, notes, shapes, free text, and your own tools | `@embedpdf/svelte/annotation`   |
| [Stamps](annotations/stamps)             | Libraries of stamps, placed by click or by code          | `@embedpdf/svelte/stamp`        |
| [Measurements](annotations/measurements) | Distances, perimeters and areas at a real scale          | `@embedpdf/svelte/measurement`  |
| [Redaction](annotations/redaction)       | Removing content for good                                | `@embedpdf/svelte/redaction`    |
| [Forms](forms)                           | Filling and building PDF forms                           | `@embedpdf/svelte/form`         |
| [Signatures](forms/signatures)           | Signing documents and checking signatures                | `@embedpdf/svelte/signature`    |
| [Page edit](documents/pages)             | Rotating, reordering, inserting and deleting pages       | `@embedpdf/svelte/page-edit`    |
| [Metadata](documents/metadata)           | A document's title, author and your own fields           | `@embedpdf/svelte/metadata`     |
| [Actions](documents/actions)             | What a PDF does by itself: buttons, scripts, printing    | `@embedpdf/svelte/actions`      |
| [View manager](documents/tabs)           | Several documents side by side                           | `@embedpdf/svelte/view-manager` |
| [Interaction](ui/tools)                  | The active tool, cursors and touch                       | `@embedpdf/svelte/interaction`  |
| [Commands](ui/commands)                  | Named actions with labels, icons and shortcuts           | `@embedpdf/svelte/commands`     |
| [Shell](ui/panels)                       | Which panels, dialogs and menus are open                 | `@embedpdf/svelte/shell`        |
| [Translations](ui/translations)          | Your UI in the user's language                           | `@embedpdf/svelte/i18n`         |

## Local or cloud

The same viewer runs on either engine. Only how you create the engine and open a document differs;
every plugin, function and component stays the same.

The local engine runs in the browser: no server, no upload, and it works offline. It's the right
choice when the user already has the file, or when the file may not leave their device.

> **Show a 500-page PDF before it downloads**
>
> With the CloudPDF engine, the file stays on your server and pages arrive as images, so the first
> page shows at once, without downloading the whole PDF or the engine. Every call is checked on the
> server, several people can review one document together, and every change is stored as it's made.
> Your viewer stays the same: swap `localEngine()` for `cloudEngine()`.
>
> [Build your viewer on CloudPDF](https://www.cloudpdf.com/docs/headless/svelte)

## Next steps

- [Quick start](quick-start) — A viewer with text selection, a zoom control and a highlighter, step by step.
- [Setup](setup) — Install for your framework, create the engine, and render on the server.
- [How it works](concepts/how-it-works) — Plugins, how your UI talks to them, layers, and which document a component talks to.
