How to Build a PDF Viewer and Annotator in Vue.js with Dynamsoft Document Viewer

Dynamsoft Document Viewer is an SDK providing a set of viewers for document images. We can use it to incorporate PDF creating, viewing and annotating into our web apps. In this article, we are going to build a fully functional PDF viewer and annotator with Vue.

What you’ll build: A Vue 3 application that can create, open, view, and annotate PDF documents in the browser using Dynamsoft Document Viewer SDK.

Key Takeaways

  • Dynamsoft Document Viewer provides a drop-in Edit Viewer component for Vue that supports PDF viewing, annotation, and image editing out of the box.
  • The SDK loads a WebAssembly engine at runtime, so the WASM resources must be copied to your project’s public directory during the build step.
  • Annotation support (stamps, text notes, drawing) is enabled by passing includeAnnotationSet: true when creating the viewer’s UI config.
  • This approach works for any Vue 3 + TypeScript + Vite project and exports annotated documents as standard PDF files.

Common Developer Questions

  • How do I add a PDF viewer with annotation support to a Vue 3 app?
  • How do I initialize Dynamsoft Document Viewer in a Vue component with TypeScript?
  • Why does Dynamsoft Document Viewer require copying WASM resources to the public folder?

Prerequisites

Step 1: Create a New Vue + TypeScript Project

Create a new Vue + TypeScript project with Vite:

npm create vite@latest pdf-app -- --template vue-ts

Step 2: Install Dynamsoft Document Viewer

First, install Dynamsoft Document Viewer via npm.

npm install dynamsoft-document-viewer

Then, we need to copy the resources of Dynamsoft Document Viewer to the public folder.

  1. Create a new folder under public/assets/ddv-resources.
  2. Install ncp: npm install ncp --save-dev.
  3. Modify package.json to copy the resources from node_modules to the public folder.

    - "dev": "vite",
    - "build": "tsc -b && vite build",
    + "dev": "ncp node_modules/dynamsoft-document-viewer/dist public/assets/ddv-resources && vite",
    + "build": "ncp node_modules/dynamsoft-document-viewer/dist public/assets/ddv-resources && tsc -b && vite build",
    

Step 3: Initialize Dynamsoft Document Viewer with a License

Let’s rewrite App.vue. When it is mounted, initialize Dynamsoft Document Viewer with the license obtained in the Prerequisites section.

<script setup lang="ts">
import { DDV, UiConfig } from 'dynamsoft-document-viewer';
import { onMounted, ref } from 'vue';

const initialized = ref(false);
onMounted(()=>{
  if (initialized.value === false) {
    initDDV();
  }
})

const initDDV = async () => {
  DDV.Core.license = "LICENSE-KEY"; // Public trial license which is valid for 24 hours
  DDV.Core.engineResourcePath = "assets/ddv-resources/engine";// Lead to a folder containing the distributed WASM files
  await DDV.Core.loadWasm();
  await DDV.Core.init(); 
  // Configure image filter feature which is in edit viewer
  DDV.setProcessingHandler("imageFilter", new DDV.ImageFilter());
  initialized.value = true;
}
</script>

Step 4: Create an Edit Viewer for PDF Annotation

  1. Use the following in the template:

    <template>
      <div id="app">
        <h2>Document Viewer Demo</h2>
        <div v-if="!initialized">Initializing...</div>
        <div id="container"></div>
      </div>
    </template>
    

    CSS:

    #app {
      display: flex;
      align-items: center;
      flex-direction: column;
      width: 100%;
    }
    
    #container {
      max-width: 80%;
      width: 1280px;
      height: 480px;
    }
    
  2. Initialize an instance of Edit Viewer and bind it to a container via its ID.

    const config = DDV.getDefaultUiConfig("editViewer", {includeAnnotationSet: true}) as UiConfig;
    // Create an edit viewer
    editViewer.current = new DDV.EditViewer({
      container: "container",
      uiConfig: config,
    });
    
  3. Import the CSS of Dynamsoft Document Viewer.

    import "dynamsoft-document-viewer/dist/ddv.css";
    

All right, we’ve incorporated Dynamsoft Document Viewer in our Vue app.

Demo screenshot

The viewer provides a toolbar, a thumbnail viewer and a main viewer for the document. We can click the buttons on the toolbar to load a new image, edit images, add PDF annotations and save the document as a PDF file.

Apart from the UI, we can also manipulate the document via code. Read the docs to learn more.

Common Issues & Edge Cases

  • WASM files not found at runtime: If the viewer fails to initialize with a resource-loading error, verify that the ncp copy step in package.json runs before the dev server starts. The public/assets/ddv-resources folder must contain the engine subdirectory with .wasm files.
  • License key expired or invalid: A LICENSE-KEY placeholder or an expired trial key causes a silent initialization failure. Replace it with a valid key from the Dynamsoft customer portal and ensure DDV.Core.license is set before calling loadWasm().
  • Edit Viewer container has zero height: The viewer renders inside a <div> and requires explicit CSS dimensions. If the container’s height is 0 or auto without content, the viewer will not be visible. Always set a fixed or min-height on the container element.

Frequently Asked Questions

How do I add a PDF viewer with annotation support to a Vue 3 app?

Install dynamsoft-document-viewer via npm, copy the WASM engine resources to your public directory, initialize the SDK with a license key, and create an EditViewer instance bound to a container element. This tutorial walks through each step.

Can I export annotated PDFs from the viewer?

Yes. Dynamsoft Document Viewer’s Edit Viewer includes a built-in save button that exports the current document — including all annotations — as a standard PDF file.

Why does the SDK require copying WASM files to the public folder?

Dynamsoft Document Viewer uses a WebAssembly engine for PDF rendering and image processing. Browsers load WASM files at runtime via HTTP, so they must be served as static assets from your project’s public directory rather than bundled by Vite.

Source Code

Check out the source code of the demo to have a try.

https://github.com/tony-xlh/document-viewer-samples/tree/main/frameworks/vue/pdf-app