██████╗ ██████╗ ███████╗██╗███╗ ██╗███████╗ ██╔══██╗██╔══██╗██╔════╝██║████╗ ██║██╔════╝ ██████╔╝██║ ██║█████╗ ██║██╔██╗ ██║█████╗ ██╔═══╝ ██║ ██║██╔══╝ ██║██║╚██╗██║██╔══╝ ██║ ██████╔╝██║ ██║██║ ╚████║███████╗ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝
Edit PDFs directly in the browser — typography preserved, privacy guaranteed.
All parsing, editing, reflow, and export happen 100% client-side.
No uploads. No accounts. No backend.
Clean, luminous landing with animated gradient orbs, 3D tilt upload widget, and shine-sweep hover effect
|
Your files never leave your device. All parsing, editing, and exporting happen entirely in the browser. No server. No telemetry. Nothing leaves localhost. |
Edit text while keeping the original fonts, sizes, weights, and colors intact. Automatic text reflow with PDF-native line heights and per-line character widths — text stays exactly where it was. |
No accounts. No installations. No backend to deploy. Open the page, drop a PDF, start editing. That's it. |
|
Canvas-based rendering with character-level precision. What you see is exactly what you get in the exported PDF. |
Cursor navigation, text selection, copy/paste, undo/redo, IME input (CJK), and keyboard shortcuts. Enter to confirm, Shift+Enter for new lines, Escape to cancel. |
Save your edits as a new PDF with embedded fonts, preserving the original document structure and visual fidelity. |
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ React 19 │ │ TS 5.9 │ │ Vite 7 │ │Zustand 5 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ ┌────┴──────────────┴─────────────┴──────────────┴────┐ │
│ │ Canvas Rendering Engine │ │
│ └────┬──────────────┬─────────────┬───────────────────┘ │
│ │ │ │ │
│ ┌────┴─────┐ ┌─────┴────┐ ┌────┴─────┐ │
│ │ pdfjs- │ │ pdf-lib │ │ opentype │ │
│ │ dist │ │ │ │ .js │ │
│ │ (parse) │ │ (export) │ │ (fonts) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ Tailwind CSS 4 · Vitest · Playwright · ESLint 9 │
│ │
└─────────────────────────────────────────────────────────────┘
- Node.js >= 18
- pnpm (recommended) or npm
# Clone
git clone https://github.com/12og3r/Pdfine.git && cd Pdfine
# Install dependencies
pnpm install
# Start dev server
pnpm devOpen http://localhost:5173 — drop a PDF and start editing.
Live demo: 12og3r.github.io/Pdfine
pnpm build # Production build → dist/
pnpm preview # Preview locallypnpm test # Unit tests
pnpm test:watch # Watch mode
npx playwright test # E2E (Chromium)User types → hidden <textarea> → InputHandler → EditCommand
→ CommandHistory (undo/redo) → DocumentModel update
→ EventBus 'textChanged' → LayoutEngine reflow
→ RenderEngine re-render → Canvas update
Module overview
src/core/
├── EditorCore.ts # Central orchestrator — wires all modules
├── parser/ # PDF parsing, text block extraction
├── model/ # Document data model (outside React state)
├── layout/ # Text reflow, Greedy + Knuth-Plass line breaking
├── render/ # Canvas rendering pipeline, hit testing
├── editor/ # Input handling, IME, cursor, selection, undo/redo
├── font/ # Font extraction, metrics, fallback chain
├── export/ # PDF export with white overlay + redraw strategy
├── infra/ # EventBus, CoordinateTransformer, Logger
└── interfaces/ # I-prefixed contracts for all modules
Key design decisions
| Decision | Rationale |
|---|---|
| Document model lives outside React | Real-time editing performance (100+ updates/sec) |
| Typed EventBus for module communication | Decoupled modules, no circular dependencies |
Hidden <textarea> for input capture |
Industry pattern (Google Docs, VS Code) for keyboard + IME |
| Canvas rendering (not DOM) | Character-level positioning precision |
| White overlay export strategy | Simplicity over PDF content stream editing |
Pdfine is a fully static site — no backend, no env vars. Deploy anywhere:
┌──────────────┐
pnpm build ───▶ │ dist/ │ ───▶ Any static host
└──────────────┘
| Platform | How |
|---|---|
| Vercel | vercel --prod |
| Netlify | Connect repo or drag dist/ |
| GitHub Pages | Push dist/ to gh-pages |
| Cloudflare Pages | Build: pnpm build, output: dist |
| Docker | COPY dist/ /usr/share/nginx/html/ |
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
# Development workflow
pnpm dev # Start dev server
pnpm test:watch # Run tests in watch mode
pnpm lint # Lint before committingThis project is licensed under the GNU General Public License v3.0 — see the LICENSE file for details.
You are free to use, modify, and distribute this software, provided that any derivative work is also distributed under the same license.