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.
<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 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 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 | Scrolling, zoom, layouts, page navigation | @embedpdf/svelte/stage |
| Render | Sharp pages at every zoom, deep-zoom tiles | @embedpdf/svelte/render |
| Links | Clickable links to pages and websites | @embedpdf/svelte/link |
| Selection | Selecting and copying text | @embedpdf/svelte/selection |
| Search | Finding text, and showing every match | @embedpdf/svelte/search |
| Annotations | Highlights, notes, shapes, free text, and your own tools | @embedpdf/svelte/annotation |
| Stamps | Libraries of stamps, placed by click or by code | @embedpdf/svelte/stamp |
| Measurements | Distances, perimeters and areas at a real scale | @embedpdf/svelte/measurement |
| Redaction | Removing content for good | @embedpdf/svelte/redaction |
| Forms | Filling and building PDF forms | @embedpdf/svelte/form |
| Signatures | Signing documents and checking signatures | @embedpdf/svelte/signature |
| Page edit | Rotating, reordering, inserting and deleting pages | @embedpdf/svelte/page-edit |
| Metadata | A document’s title, author and your own fields | @embedpdf/svelte/metadata |
| Actions | What a PDF does by itself: buttons, scripts, printing | @embedpdf/svelte/actions |
| View manager | Several documents side by side | @embedpdf/svelte/view-manager |
| Interaction | The active tool, cursors and touch | @embedpdf/svelte/interaction |
| Commands | Named actions with labels, icons and shortcuts | @embedpdf/svelte/commands |
| Shell | Which panels, dialogs and menus are open | @embedpdf/svelte/shell |
| 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.
Next steps#
Your feedback goes directly to the documentation team.