A private, offline-capable PDF toolkit that runs 100% in your browser. Your files never leave your device — no uploads, no servers, no API keys, no LLMs.
Most "online PDF tools" upload your documents to a server. PDF-Wizard doesn't. Every operation — merge, split, compress, OCR, redact, sign, encrypt — happens on your device using JavaScript and WebAssembly running in Web Workers. There is no runtime network request, which is exactly why it can be installed as an app and run fully offline. Files never leave your device is not a marketing line here; it's an architectural constraint that shaped every decision in the codebase.
![]() |
![]() |
| The landing page — dark/light aware, drag-and-drop or picker intake. | The editor — thumbnail workspace, tool sidebar, and export inspector. |
Organize
Merge, split (→ ZIP), drag-to-reorder, delete, extract, duplicate, rotate, insert blank pages, crop, and a grouped multi-document view — all non-destructive (pages are pointers; originals are never mutated) with undo/redo, multi-select, and keyboard shortcuts.
Customize
Watermarks (diagonal / tile / banner / stamp styles), page numbers, QR codes, and headers & footers as non-destructive overlays with a live preview; add text, insert images, digital signatures, and draw/highlight as per-page annotations; password protect and unlock.
Optimize
Compress (lossless re-save or rasterize), edit/remove metadata, PDF → images, images → PDF, grayscale, extract embedded images, and a document statistics report.
Power tools
Blank-page detection, duplicate-page detection, a 2-up saddle-stitch booklet creator, batch processing (one operation across many files), and a workflow builder that chains operations and saves/loads the pipeline as JSON.
Documents & conversion
Offline multi-language OCR (adds an invisible, searchable text layer), true irreversible redaction, page-by-page visual compare, and Word / Excel / CSV → PDF conversion — all client-side.
| Keys | Action |
|---|---|
Ctrl/⌘ + Z |
Undo |
Ctrl/⌘ + Shift + Z / Ctrl/⌘ + Y |
Redo |
Ctrl/⌘ + A |
Select all pages |
Shift + Click / Ctrl/⌘ + Click |
Range / toggle select |
Delete |
Delete selected pages |
Esc |
Clear selection |
? |
Show the shortcuts reference |
Data flows one direction through swappable layers, with all heavy work off the main thread:
flowchart LR
A["UI<br/>React + Tailwind"] --> B["Zustand store<br/>SourceDoc + PageRef model"]
B --> C["Export pipeline<br/>engine/export.ts"]
C --> D["Comlink Web Worker"]
D --> E["PDF adapters<br/>pdf.js · @cantoo/pdf-lib"]
- Non-destructive document model — the store holds immutable
SourceDocs (raw bytes, loaded once) plus a list of lightweightPageRefpointers. Reorder / duplicate / delete / rotate only mutate the pointer list; original bytes are never copied until export. - Two worker roles — pdf.js handles rendering and parsing (thumbnails, page counts, rasterization); @cantoo/pdf-lib (an encryption-capable fork) runs in a Comlink worker for CPU-heavy assembly, overlays, annotations, metadata, and encryption.
- Batch & Workflow compose a shared registry of
ArrayBuffer → Uint8Arrayoperations that reuse the same worker/export pipeline.
React 19 · TypeScript · Vite · Tailwind v4 · Framer Motion · dnd-kit · Zustand · Comlink (Web Workers) · pdf.js (render/parse) · @cantoo/pdf-lib (assemble, export, encryption) · Tesseract.js (OCR) · mammoth + SheetJS (Office → PDF) · qrcode · vite-plugin-pwa (Workbox).
npm install
npm run gen:tesseract # one-time: vendor the ~74 MB offline OCR models
npm run dev # Vite dev server on http://localhost:5173Note: the OCR models are not committed to the repo. Run
npm run gen:tesseractonce (also part ofnpm run gen:assets) before the OCR tool will work.
npm run dev # start the dev server
npm run build # gen-sitemap → typecheck → build → prerender
npm run preview # serve the production build (dist/)
npm run test # run unit tests (Vitest)
npm run lint # oxlint
npm run gen:assets # regenerate the OG image, sitemap, and OCR modelsPDF-Wizard is a Progressive Web App. Open it in a Chromium browser or Safari and use Install / Add to Home Screen; after the first load it runs entirely offline. When a new build is deployed, an in-app prompt offers to reload.
npm run build emits a fully static dist/. Host it anywhere; just enable an SPA
fallback so client-side routes (e.g. /privacy) resolve to index.html. Config is
included for Netlify / Cloudflare Pages (public/_redirects) and Vercel
(vercel.json).
src/
app/ # shell: routing, theme, error boundary, PWA prompt
components/ # layout chrome + PDF workspace + UI primitives
engine/ # export pipeline, pdf.js adapter, pdf-lib worker
features/ # tools by category: organize, customize, optimize, power…
lib/ # pure, unit-tested helpers (overlays, detect, ocr, zip…)
seo/ # per-feature landing pages generated from features.json
store/ # Zustand document + UI stores
scripts/ # build-time asset/sitemap/prerender generators
CLAUDE.mdis a deep engineering guide — the architecture, the two worker roles (pdf.js vs.@cantoo/pdf-lib), and the project's non-obvious gotchas. Read it before making a substantial change.
Contributions are welcome! Please read the contributing guide first — the golden rule is that every feature must work fully client-side (no server, no runtime network). See also the code of conduct and the security policy. Changes are documented in the changelog.
MIT © Atharva Shukla


