DocsSvelteUnderstanding Plugins

Understanding Plugins

Plugins are the heart of EmbedPDF’s headless architecture. They are modular packages that add specific features and capabilities to your core viewer. This à la carte approach ensures your application remains lean, loading only the functionality you actually need.

Think of the <EmbedPDF> component as a smartphone: it’s powerful on its own, but it’s the apps (plugins) you install that give it new features like navigation, social media, or games.

How Plugins Work

Adding a new feature to your viewer follows a simple three-step process:

1. Install the Plugin Package

Each plugin is its own NPM package. For example, to add zooming capabilities, you would install the zoom plugin:

npm install @embedpdf/plugin-zoom

2. Register the Plugin

Next, you import the plugin’s ...PluginPackage and register it in the plugins array that you pass to the <EmbedPDF> component. This is done using the createPluginRegistration helper function.

<script lang="ts"> import { createPluginRegistration } from '@embedpdf/core'; import { EmbedPDF } from '@embedpdf/core/svelte'; // ... other imports import { DocumentManagerPluginPackage } from '@embedpdf/plugin-document-manager/svelte'; import { ZoomPluginPackage, ZoomMode } from '@embedpdf/plugin-zoom/svelte'; const plugins = [ // ... other essential plugins like DocumentManager, Viewport, etc. createPluginRegistration(DocumentManagerPluginPackage, { initialDocuments: [{ url: 'https://snippet.embedpdf.com/ebook.pdf' }], }), createPluginRegistration(ViewportPluginPackage), createPluginRegistration(ScrollPluginPackage), createPluginRegistration(RenderPluginPackage), // Add the zoom plugin to the array createPluginRegistration(ZoomPluginPackage, { defaultZoomLevel: ZoomMode.FitPage, // You can pass options here! }), ]; </script>

Registering the plugin activates its core logic and makes its features available to the rest of your application.

3. Use the Plugin’s Components and Stores

Once a plugin is registered, you can use its associated Svelte components and stores to build your UI. For example, the zoom plugin provides a <MarqueeZoom /> component for drag-to-zoom functionality and a useZoom store to control zoom levels from a toolbar.

Since EmbedPDF supports multiple documents, stores and components require a documentId parameter to know which document they’re working with. You’ll get the activeDocumentId from the <EmbedPDF> component’s snippet.

ZoomToolbar.svelte
<script lang="ts"> import { useZoom } from '@embedpdf/plugin-zoom/svelte'; interface Props { documentId: string; } let { documentId }: Props = $props(); // Pass the documentId as a getter function const zoom = useZoom(() => documentId); </script> {#if zoom.provides} <div> <span>Current Zoom: {Math.round(zoom.state.currentZoomLevel * 100)}%</span> <button onclick={() => zoom.provides?.zoomOut()}>-</button> <button onclick={() => zoom.provides?.zoomIn()}>+</button> <button onclick={() => zoom.provides?.requestZoom(1.0)}>Reset</button> </div> {/if}

This clear separation of logic (the plugin) from the view (your components) gives you complete control over your UI.

4. Add the Component to Your Viewer

Finally, import and place your new <ZoomToolbar /> component inside the <EmbedPDF> provider. This is essential, as it allows the useZoom store to access the context provided by the ZoomPluginPackage.

Since we’re working with multiple documents, you’ll need to:

  1. Get the activeDocumentId from the <EmbedPDF> snippet
  2. Use <DocumentContent> to ensure the document is loaded before rendering
  3. Pass the documentId to all components and stores that need it
PDFViewer.svelte
<script lang="ts"> import { EmbedPDF } from '@embedpdf/core/svelte'; import { DocumentContent } from '@embedpdf/plugin-document-manager/svelte'; import { Viewport } from '@embedpdf/plugin-viewport/svelte'; import { Scroller, type RenderPageProps } from '@embedpdf/plugin-scroll/svelte'; import { RenderLayer } from '@embedpdf/plugin-render/svelte'; import ZoomToolbar from './ZoomToolbar.svelte'; // 1. Import the toolbar // ... plugins array setup </script> <div style="height: 500px; border: 1px solid black; display: flex; flex-direction: column;"> <EmbedPDF engine={pdfEngine.engine} {plugins}> {#snippet children({ activeDocumentId })} {#if activeDocumentId} {@const documentId = activeDocumentId} <DocumentContent {documentId}> {#snippet children(documentContent)} {#if documentContent.isLoaded} {#snippet renderPage(page: RenderPageProps)} <div style:width="{page.width}px" style:height="{page.height}px" style:position="relative" > <RenderLayer {documentId} pageIndex={page.pageIndex} /> </div> {/snippet} <div style="display: flex; height: 100%; flex-direction: column;"> <!-- 2. Add the component here with documentId --> <ZoomToolbar {documentId} /> <div style="flex: 1; overflow: hidden;"> <Viewport {documentId}> <Scroller {documentId} {renderPage} /> </Viewport> </div> </div> {/if} {/snippet} </DocumentContent> {/if} {/snippet} </EmbedPDF> </div>

5. Live Demo

This is the result of the code above—a fully functional PDF viewer with zoom controls that you built from the ground up.

Types of Plugin Features

Plugins can provide several types of tools:

  • Core Logic: Some plugins work entirely in the background to manage state (e.g., ScrollPluginPackage).
  • Svelte Components: Most plugins offer components that you place in your viewer to add UI features (e.g., <RenderLayer />, <SelectionLayer />, <MarqueeZoom />).
  • Svelte Stores: Functions like useZoom(() => documentId) or useScroll(() => documentId) allow your custom components to access plugin data and trigger actions. Since EmbedPDF supports multiple documents, these stores require a documentId parameter (as a getter function).

By combining plugins, you can compose a feature-rich PDF experience that is perfectly tailored to your application’s design and needs.

Last updated on December 5, 2025

Need Help?

Join our community for support, discussions, and to contribute to EmbedPDF's development.