Skip to content

Installation

Use this guide to get a correct setup on the first try.

  • Core API running in Node.js or browser.
  • React viewer running with a valid worker and WASM source.
  • A quick verification step you can run before building features.
Terminal window
pnpm add @scaryterry/pdfium

React users also need peers:

Terminal window
pnpm add react react-dom lucide-react
EnvironmentRequired setup
Node.js core APINo extra asset wiring needed for basic PDFium.init()
Browser core APIProvide wasmUrl or wasmBinary to PDFium.init(...)
React viewer (PDFiumProvider)Provide workerUrl and (wasmUrl or wasmBinary)
Worker mode with core APICreate worker entry module and pass workerUrl
import { PDFium } from '@scaryterry/pdfium';
using pdfium = await PDFium.init();
import { PDFium } from '@scaryterry/pdfium';
const wasmBinary = await fetch('/pdfium.wasm').then((r) => r.arrayBuffer());
using pdfium = await PDFium.init({ wasmBinary });

You can also pass wasmUrl directly:

using pdfium = await PDFium.init({ wasmUrl: '/pdfium.wasm' });

5. Canonical Worker Module (React + Worker Mode)

Section titled “5. Canonical Worker Module (React + Worker Mode)”

Create a worker entry in your app:

src/pdfium.worker.ts
import '@scaryterry/pdfium/worker';

Resolve its URL:

const workerUrl = new URL('./pdfium.worker.ts', import.meta.url).toString();
import wasmUrl from '@scaryterry/pdfium/pdfium.wasm?url';
import { PDFiumProvider, PDFViewer } from '@scaryterry/pdfium/react';
const workerUrl = new URL('./pdfium.worker.ts', import.meta.url).toString();
function App() {
return (
<PDFiumProvider wasmUrl={wasmUrl} workerUrl={workerUrl}>
<PDFViewer />
</PDFiumProvider>
);
}
Section titled “Strategy A: Bundler-managed asset URLs (recommended)”

Use your bundler to emit both worker and WASM URLs.

Vite example:

vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
optimizeDeps: { exclude: ['@scaryterry/pdfium'] },
assetsInclude: ['**/*.wasm'],
});
import wasmUrl from '@scaryterry/pdfium/pdfium.wasm?url';
const workerUrl = new URL('./pdfium.worker.ts', import.meta.url).toString();

Copy the WASM file into your public assets:

Terminal window
cp node_modules/@scaryterry/pdfium/dist/vendor/pdfium.wasm public/pdfium.wasm

Then use:

const wasmUrl = '/pdfium.wasm';

Keep the worker as a bundled module (src/pdfium.worker.ts) and pass the emitted workerUrl. Do not copy only dist/worker.js; it imports sibling modules.

Enable async WASM in webpack:

next.config.js
module.exports = {
webpack: (config) => {
config.experiments = { ...config.experiments, asyncWebAssembly: true };
return config;
},
};

If you serve from public, copy:

Terminal window
cp node_modules/@scaryterry/pdfium/dist/vendor/pdfium.wasm public/pdfium.wasm

Install platform package(s):

Terminal window
pnpm add @scaryterry/pdfium-darwin-arm64
pnpm add @scaryterry/pdfium-darwin-x64
pnpm add @scaryterry/pdfium-linux-x64-gnu
pnpm add @scaryterry/pdfium-linux-arm64-gnu
pnpm add @scaryterry/pdfium-win32-x64-msvc

Then request native:

import { PDFium } from '@scaryterry/pdfium';
const pdfium = await PDFium.init({ useNative: true });
import { PDFium, VERSION } from '@scaryterry/pdfium';
console.log('version', VERSION);
using pdfium = await PDFium.init();
console.log('ok');

If this script prints a version and ok, your base setup is valid.