> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/get-started/libraries-and-frameworks/frameworks.md).

# Compatible JavaScript Frameworks for PDF Viewer

Learn how to integrate WebViewer into any JavaScript framework with ease. Follow three simple steps: Importing, Instantiating, and Calling APIs. Start using WebViewer today! The Apryse Web SDK streaml

WebViewer is compatible with any JavaScript framework because it only needs a DOM element to place the document-viewing component. The following pre-built samples are available for quick integration, but it's easy to setup WebViewer with any framework.

<a href="/web/get-started/libraries-and-frameworks/react.md" class="button secondary">React</a><a href="/web/get-started/libraries-and-frameworks/angular.md" class="button secondary">Angular</a><a href="/web/get-started/libraries-and-frameworks/vue.md" class="button secondary">Vue</a><a href="/web/get-started/libraries-and-frameworks/nextjs.md" class="button secondary">NextJS</a><a href="/web/get-started/libraries-and-frameworks/nuxt.md" class="button secondary">NuxtJS</a><a href="/web/get-started/libraries-and-frameworks/electron.md" class="button secondary">Electron</a><a href="/web/get-started/libraries-and-frameworks/svelte.md" class="button secondary">Svelte</a><a href="/web/get-started/libraries-and-frameworks/vite.md" class="button secondary">Vite</a><a href="/web/get-started/readme/cordova.md" class="button secondary">Cordova</a><a href="/web/get-started/libraries-and-frameworks/blazor.md" class="button secondary">Blazor</a><a href="/core/get-started/frameworks/nodejs.md" class="button secondary">Node.js</a>

## Integrating Into Other Frameworks

Integrating WebViewer into a JavaScript framework (any framework) is broken down to three steps:

1. Importing
2. Instantiating
3. Calling APIs

## Importing

WebViewer can be integrated into your application in several ways, depending on your project setup. The main difference between these approaches is how WebViewer is loaded and how your project is structured.

{% hint style="info" %}
**Choosing an approach**

* **Script tag** – Simplest setup, loads everything directly in the browser.
* **npm** – Fully managed by your build system.
* **Hybrid** – Combines both approaches by using a bundler for your code while hosting WebViewer files manually.
  {% endhint %}

**Import using a script tag**

This approach is best when you're working with plain HTML and JavaScript projects and want a quick setup with no build tools. For example, this could mean you're following a [manual installation](/web/get-started/manually.md) path that involves downloading the SDK. The integration doesn't require Node Package Manager (npm) or any build tools, and it's the fastest way to get started with the WebViewer library.

The import looks similar to this in your HTML:

{% tabs %}
{% tab title="HTML" %}
{% code lineNumbers="true" %}

```html
<script src='PATH_TO_WEBVIEWER/lib/webviewer.min.js'></script>
```

{% endcode %}
{% endtab %}
{% endtabs %}

This method is not ideal for large applications and lacks built-in module or dependency management.

**Import using npm (recommended)**

This approach is best when you're building a modern web application and want to manage dependencies using a package manager. For example, this could mean you're using a framework such as React, Angular, or Vue, or a build tool like Webpack, Vite, or Parcel. By [installing WebViewer via npm](/web/get-started/npm.md), you download WebViewer from the npm registry. Both the JavaScript API and runtime assets are managed through the npm package. You can then import WebViewer directly into your JavaScript files using ES module syntax (`import`).

The integration looks similar to this in your JavaScript:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
import WebViewer from '@pdftron/webviewer';
```

{% endcode %}
{% endtab %}
{% endtabs %}

This method requires a build tool and a module-based setup, but provides better scalability, maintainability, and dependency management for larger applications.

**Import using a hybrid approach**

This approach is best when you're using a bundler but still need to host the WebViewer runtime files (`lib` folder) manually. For example, your application may use a build tool like Webpack, Vite, or Parcel, while the WebViewer SDK is downloaded and served from your own server. In this setup, WebViewer is installed from locally downloaded SDK files instead of the npm registry:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
npm install PATH_TO_WEBVIEWER/lib
```

{% endcode %}
{% endtab %}
{% endtabs %}

You can then use ES module syntax (`import`) in your application code, while WebViewer’s runtime files (UI assets, workers, etc.) are loaded separately from the manually hosted `lib` folder:

{% tabs %}
{% tab title="JavaScript" %}
{% code title="main.js" lineNumbers="true" %}

```js
// Import WebViewer from node_modules (installed from local SDK files, not npm)
// This is a UMD build, so it exposes WebViewer on the global `window` object
import 'webviewer/webviewer.min.js';

// Access the global WebViewer instance
const WebViewer = window.WebViewer;

WebViewer({ path: '/WebViewer/lib' }, document.getElementById('viewer'));
```

{% endcode %}
{% endtab %}
{% endtabs %}

Because `import` is used, your HTML must load the JavaScript file with `<script type="module">` for the browser to execute it correctly:

{% tabs %}
{% tab title="HTML" %}
{% code lineNumbers="true" %}

```html
<script type="module" src="/main.js"></script
```

{% endcode %}
{% endtab %}
{% endtabs %}

This approach can be useful in restricted or enterprise environments where direct npm installation is not preferred. While it offers flexibility, it's more complex than the script tag or full npm methods. It's typically recommended only for advanced or specialized use cases.

## Instantiating

The WebViewer constructor takes two arguments: options and a DOM element. Regardless of the framework, you must pass a DOM element which will contain WebViewer's iframe.

Given the instantiation code:

<pre class="language-js" data-line-numbers><code class="lang-js">WebViewer({
  path: 'PATH_TO_WEBVIEWER/lib',
  licenseKey: '<code class="expression">visitor.claims.wvKey || "YOUR_LICENSE_KEY"</code>',
  initialDoc: 'path/to/doc.pdf'
}, HTML_DIV_ELEMENT);
</code></pre>

you can reference a DOM element based on your framework:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
// Vanilla JS
WebViewer({ ... }, document.getElementById('viewer'));
// React
WebViewer({ ... }, this.viewerRef.current);
// Angular
WebViewer({ ... }, this.viewer.nativeElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Calling APIs

Before calling APIs, you should wait for appropriate events to be fired from WebViewer.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
// Vanilla JS
WebViewer(...)
  .then(instance => {
    onReady();

    const { documentViewer } = instance.Core;
    documentViewer.addEventListener('documentLoaded', onDocumentLoaded);
  });
  
// React
useEffect(() => {
    WebViewer(...).then(instance => {
      onReady(instance);

      const { documentViewer } = instance.Core;
      documentViewer.addEventListener('documentLoaded', () => {
        onDocumentLoaded(instance);
      });
    });
  }, []);

// Angular
ngAfterViewInit(): void {
    WebViewer(...).then(instance => {
      this.onReady(instance);

      const { documentViewer } = instance.Core;
      documentViewer.addEventListener('documentLoaded', () => {
        this.onDocumentLoaded(instance);
      });
    });
  }

```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
// Vanilla JS
WebViewer(...)
  .then(instance => {
    onReady();

    const { docViewer } = instance;
    docViewer.on('documentLoaded', onDocumentLoaded);
  });
// React and Angular
WebViewer(...)
  .then(instance => {
    this.onReady(instance);

    const { docViewer } = instance;
    docViewer.on('documentLoaded', this.onDocumentLoaded.bind(this, instance));
  });
```

{% endcode %}
{% endtab %}
{% endtabs %}

and call APIs from viewer instance:

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
// Vanilla JS
const onReady = instance => {
  // Executed when the viewer is ready
  // NOTE: Document is not loaded yet
  instance.UI.enableFilePicker();
};
const onDocumentLoaded = instance => {
  // Executed when the document is loaded
  // NOTE: Document is not rendered yet
   instance.UI.getPageCount();
}
// React and Angular
onReady(instance) {
  // Executed when the viewer is ready
  // NOTE: Document is not loaded yet
   instance.UI.enableFilePicker();
}
onDocumentLoaded(instance) {
  // Executed when the document is loaded
  // NOTE: Document is not rendered yet
   instance.UI.getPageCount();
}
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
// Vanilla JS
const onReady = instance => {
  // Executed when the viewer is ready
  // NOTE: Document is not loaded yet
  instance.enableFilePicker();
};
const onDocumentLoaded = instance => {
  // Executed when the document is loaded
  // NOTE: Document is not rendered yet
  instance.getPageCount();
}
// React and Angular
onReady(instance) {
  // Executed when the viewer is ready
  // NOTE: Document is not loaded yet
  instance.enableFilePicker();
}
onDocumentLoaded(instance) {
  // Executed when the document is loaded
  // NOTE: Document is not rendered yet
  instance.getPageCount();
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/get-started/libraries-and-frameworks/frameworks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
