A lightweight PDF viewer and annotator with synced side-by-side view. Built for QC, translation checks, and version comparison. Try it online here!
- Instant web access.
- Private and local.
- Open source and ad free.
- Side by side: Compare two PDFs in the same viewer
- Synced view: Simultaneous scroll, zoom, and page navigation
- Search: Find and navigate to any string
- Bookmarks sidebar: Browse and create custom bookmarks and ToC outline
- Annotations sidebar: View all sticky notes, comments, and highlights
- View modes: Switch between page-by-page rendering or continuous scroll
- Session recovery: Comments get autosaved and restored when you come back
- Accessibility: Show alt text on hover, with an optional visual indicator
- Automation friendly: Load remote and local PDFs on the web version like this:
?a=doc1.pdf&b=doc2.pdfor use command line arguments with the desktop app
- Sticky notes: Double click to add comments anywhere on the page
- Text annotations: Select text to highlight or add comments
- Custom author: Change your name so your comments are easily identifiable
- Export: Download annotated PDFs with your changes
Twice PDF is available as a native Windows application powered by Tauri.
- CLI Support: Open PDFs via command line:
Twice-PDF.exe doc1.pdf doc2.pdf - Native I/O: Direct file access including "save to source" functionality with configurable naming patterns
- Fully offline: No online capabilities necessary to view and save PDFs
- Minimal footprint: Tauri uses the OS native web viewer, avoiding Electron-like embedding for a 95% smaller bundle size, 60-90% less memory usage, and automatic engine updates. The Windows app is under 15 MB!
| Lightweight | ~150KB gzipped. Minimal dependencies. |
| Flexible | URL and CLI parameters, env configs, extensible architecture. |
| Bespoke | Modern, sleek UI. Flat design. Easily themed. |
| Scalable | Lazy rendering with IntersectionObserver. Handles large documents. |
| Robust | Multi-proxy CORS fallback, SSRF protection, DNS pinning. |
| Secure | Private IP filtering, path traversal protection, feature flags. |
| Modular | 25+ focused modules: SearchPanel, AnnotationOverlay, useAnnotations, pdfExport, etc. |
- React 19 + Vite 7: Modern stack with fast HMR and optimized builds
- PDF.js Bundled Locally: No CDN calls—faster, private, offline-ready
- Smooth Zoom Engine: CSS transform for instant feedback + debounced re-render
- RAF-Throttled Sync:
requestAnimationFramescroll handling prevents flooding - Memory Management: Off-screen page unloading
- Canvas Size Guard: Prevents browser crashes on oversized pages
- Error Boundary: Graceful error handling with retry UI
.env in the app directory:
| Variable | Default | Description |
|---|---|---|
VITE_ENABLE_REMOTE_PDFS |
true |
Disable to block external URL loading |
VITE_ENABLE_LOCAL_BRIDGE |
true |
Disable to block local file access via dev bridge |
- SSRF Protection: IP filtering, DNS pinning, redirect validation
- Private IP Blocking: Rejects 127.x, 10.x, 172.16-31.x, 192.168.x, 169.254.x
- Path Traversal Protection: Local bridge restricted to
public/samples - Network Exposure Warning: Console alert if dev server exposed to LAN
- Auto-generate comparison views for QC processes
- Add custom action buttons (e.g., database operations)
- Autosave with preset naming patterns
- URL parameter API for programmatic loading
Remote PDFs use a fallback chain of public proxies:
- Direct fetch → 2. AllOrigins → 3. CORS.lol → 4. corsproxy.io
When direct fetch fails due to a CORS error, "Load from URL" will pass the PDF through third-party proxies. For sensitive documents, download and upload manually.
- Node.js (v16+)
git clone https://github.com/PlusKits/Twice-PDF.git
cd Twice-PDF/app
npm install
npm run dev
# For Desktop App
npm run tauri:dev # Debug mode
npm run tauri:build # Release buildOpen http://localhost:5173 in your browser.
http://localhost:5173/?a=file1.pdf&b=file2.pdf
Note
The Vite local bridge only serves files from app/public/samples for security. The base path can be configured.
Deploy as a static site on GitHub Pages, Vercel, or Netlify. Deploy as a Windows executable via our GitHub releases.
Note
Local path functionality is only available through the Vite dev server and desktop app due to browser security restrictions.
GNU Affero General Public License v3.0 (AGPLv3)
- ✅ Free to use for personal or internal purposes
- ✅ Modify and distribute with source code disclosure
⚠️ SaaS usage requires source code release under the same license
Want different terms?
If you are an open source developer, I will gladly help. Even if you don't need a license, if you are working on a PDF viewer I would love to chat! If you are a business, we can talk too.
Contact: pluskittydev [at] gmail [dot] com
See LICENSE for full details.
See CHANGELOG.md for complete version history.
Latest Updates (January 2026):
- Desktop Support: Native Windows app with Tauri (CLI args, native file access)
- Accessibility: Alt text extraction, visualization, and fallback heuristics
- Architecture: Major refactor into 25+ modular components
- Panels: New Bookmarks and Annotations sidebars
Add comments and highlights
View existing comments
Search and explore



