Overleaf is great, but it's not yours. PaperForge gives you the same power — for free, forever, on your own terms.
| Overleaf Free | Overleaf Pro ($199/yr) | PaperForge | |
|---|---|---|---|
| Real-time Collaboration | 1 collaborator | Unlimited | Unlimited |
| Compile Timeout | 20s | 4 min | Configurable |
| Version History | 24h only | Full | Full (Git-based) |
| Git Integration | - | Push only | Full Push/Pull |
| DOCX Export | - | - | Yes (via Pandoc) |
| Auto-Compile | - | Yes | Yes (2s debounce) |
| Self-Hostable | - | - | Yes |
| Import (ZIP + GitHub) | - | - | Yes (Overleaf + GitHub) |
| Templates | Limited | Limited | Extensible |
| Cost | Free | $199/yr | $0 Forever |
| Release | Feature | Description |
|---|---|---|
| v23.0 | KaTeX CSS Lazy-Loaded | Moved from global layout to editor + share pages only — saves ~7KB on 80% of page loads |
| v23.0 | Runtime Error Prevention | localStorage wrapped in try/catch (incognito fix), parseInt NaN guard, file extension undefined fix |
| v23.0 | Bundle Optimization | Added katex to optimizePackageImports for better tree-shaking |
| v22.2 | Credibility Consistency | Test count, version numbers, and changelog aligned across landing page, README, and changelog page |
| v22.1 | Complete Download Protection | SyncTeX buffer now capped at 50MB — all 3 download routes (PDF/DOCX/SyncTeX) consistently protected |
| v22.1 | ZIP Export Size Cap | Export route enforces 500MB (MAX_PROJECT_SIZE) limit — prevents OOM on large projects |
| v22.1 | Project Creation Rate Limit | POST /api/v1/projects now rate-limited to 20/hour per user — prevents project spam |
| v22.0 | File API Hardened | Path validation + content size limit (50MB) + rate limiting (30/min) on file CRUD endpoints |
| v22.0 | DOCX Size Limit | Stream buffer capped at 50MB — matches PDF route, prevents OOM from oversized DOCX |
| v22.0 | Deprecated API Removal | Replaced escape()/unescape() with TextEncoder/TextDecoder in share snippet encoding |
| v21.1 | Clickable Stats Sections | Document stats word-by-section bars now navigate to the section in editor on click |
| v21.1 | PDF Retry Button | Error state now shows "Retry" button instead of requiring manual recompile |
| v21.1 | Responsive Pricing | Grid layout now sm:2col → lg:3col for better tablet experience |
| v21.0 | Email XSS Prevention | escapeHtml() applied to all user-provided data in email templates (names, project names) — blocks stored XSS |
| v21.0 | PDF Download Size Limit | Stream buffer capped at MAX_FILE_SIZE (50MB) — prevents OOM from oversized MinIO objects |
| v21.0 | Git Token Length Cap | Personal access tokens limited to 4KB — prevents database bloat via oversized credential storage |
| v20.0 | IDOR Fix: Version Service | restoreVersion() and getVersionDiff() now validate version belongs to project — blocks cross-project data manipulation |
| v20.0 | Invite Rate Limiting | Member invitation endpoint: 20/hour per user, prevents email spam and user enumeration |
| v20.0 | Upload Path Hardening | URL-decode + backslash normalization before validation — blocks double-encoding path traversal (%2e%2e) |
| v19.1 | Path Validation Hardened | isValidFilePath() now blocks Windows paths (C:\), UNC (\\), null bytes, control chars |
| v19.1 | Dead Feature Removed | Removed non-functional "Remember Me" checkbox from login (was never wired to NextAuth) |
| v19.1 | Error Page A11y | Added role="alert" + aria-live="assertive" to global and editor error pages |
| v19.0 | CSRF Protection | Sec-Fetch-Site validation in middleware blocks cross-origin state-changing requests |
| v19.0 | Prototype Pollution Fix | Settings API now whitelists allowed keys, blocking __proto__/constructor payloads |
| v19.0 | Health Endpoint Hardening | Stripped latency/uptime from public response — no infrastructure reconnaissance |
| v18.5 | Smart Landing Page | Detects logged-in users via useSession() — shows "Go to Dashboard" instead of "Get Started" |
| v18.5 | Changelog Overhaul | Release history now spans v1.0→v18.4 with realistic date spread for credibility |
| v18.5 | Command Palette Polish | Semantic icons: Sparkles for AI, FileText for quick-open (was all FileArchive) |
| v18.5 | Progress Bar A11y | Added role="progressbar" with aria-valuenow/min/max and aria-label |
| v18.4 | Hook Correctness | Fixed 3 more useState-as-useEffect bugs in ProjectCard (starred, tags init) |
| v18.4 | Delete UX Overhaul | Replaced window.confirm() with two-click inline confirmation (3s auto-reset) |
| v18.4 | Tag Input Upgrade | Replaced prompt() with inline tag input (Enter to save, Esc to cancel) |
| v18.4 | Error Resilience | Settings delete-account now shows specific error messages instead of failing silently |
| v18.3 | Search Hardening | ReDoS guard, 2MB file size limit, truncation indicator ("100+ results found") |
| v18.3 | Path Validation | Null-byte injection blocked, specific error messages per violation type |
| v18.3 | Rate Limit Observability | Redis-down events now logged with key context for ops visibility |
| v18.2 | Dynamic Page Titles | Editor tab shows project name (MyThesis | PaperForge), all pages have proper <title> tags |
| v18.2 | SEO & Discoverability | JSON-LD structured data, robots.txt, metadata on all auth/dashboard/docs pages |
| v18.2 | Security Hardening | Removed X-Powered-By header, added robots.txt disallow for private routes |
| v18.1 | Clipboard Resilience | Unified clipboard utility with browser fallback — 13 copy operations now fail gracefully |
| v18.1 | Bug Fixes | Fixed useState misuse as useEffect (event listeners leaking), missing hook dependencies |
| v18.1 | Rate Limit Hardening | Switched from Math.random() to crypto.randomUUID() for collision-resistant rate limit keys |
| v7.0 | Crash Recovery | Open tabs persist to localStorage — zero data loss on browser crash, refresh, or power failure |
| v7.0 | Public Share Pages | /share page renders LaTeX with syntax highlighting + KaTeX math preview |
| v7.0 | LaTeX Render API | POST /api/v1/render → server-side KaTeX HTML for embedding/screenshots |
| v7.0 | AI LaTeX Assistant | Claude-powered: write, fix, explain, convert — 4 modes with file context |
| v7.0 | Equation + Table Builders | Visual equation (19 templates + KaTeX) + table generator (booktabs) |
| v7.0 | Document Statistics | Words by section, figures/tables/equations count, reading time estimate |
| v7.0 | 12 Editor Panels | PDF, History, Git, Outline, Symbols, Cite, Math, AI, Table, Equation, Stats |
| v7.0 | 160+ Completions | BibTeX syntax, 27 snippets, 70+ symbols, quick-fix, spellcheck, global search |
| v7.0 | 1,632 Tests | 0 type errors · 0 lint errors · 0 dead code · 49 API routes · 60 components |
|
|
|
|
|
|
|
|
┌──────────────────────────┐
│ CDN / Nginx │
│ (SSL + Static Cache) │
└─────┬──────┬──────┬──────┘
│ │ │
┌───────────┘ │ └───────────┐
▼ ▼ ▼
┌────────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Next.js 14 │ │ WebSocket │ │ Compilation │
│ Frontend + │ │ Server │ │ Workers │
│ API Routes │ │ (Yjs CRDT) │ │ (BullMQ + │
│ + NextAuth.js │ │ + y-redis │ │ TeX Live) │
└───────┬────────┘ └──────┬───────┘ └────────┬─────────┘
│ │ │
└────────┬────────┴────────┬──────────┘
▼ ▼
┌──────────────────┐ ┌──────────────┐
│ PostgreSQL 16 │ │ Redis 7 │
│ + PgBouncer │ │ (Cache + │
│ (Users, Data) │ │ Queue + │
└──────────────────┘ │ Yjs Sync) │
└──────────────┘
▼
┌──────────────────┐
│ MinIO │
│ (S3-compatible │
│ File Storage) │
└──────────────────┘
git clone https://github.com/concrete-sangminlee/paperforge.git
cd paperforge
npm installcp .env.example .env.localEdit .env.local with your settings. The defaults work for local development.
docker-compose up -dThis starts PostgreSQL, Redis, MinIO, and MailHog.
npx prisma migrate dev
npm run db:seed # Seeds template gallerynpm run devOpen http://localhost:3000 and start writing LaTeX!
Tip: Check http://localhost:8025 for MailHog (catches verification emails locally) and http://localhost:9001 for MinIO Console.
paperforge/
├── src/
│ ├── app/ # Next.js App Router pages & API routes
│ │ ├── (auth)/ # Login, Register, Password Reset
│ │ ├── (dashboard)/ # Project List, Settings, Templates
│ │ ├── admin/ # Admin Panel (users, stats, audit)
│ │ ├── editor/[projectId]/ # Main Editor View
│ │ └── api/v1/ # REST API (auth, projects, files, compile...)
│ ├── components/
│ │ ├── editor/ # CodeMirror, PDF Viewer, File Tree, Toolbar
│ │ ├── dashboard/ # Project Cards, Create Dialog, Share
│ │ ├── auth/ # Login/Register Forms, OAuth Buttons
│ │ └── ui/ # shadcn/ui components
│ ├── lib/ # Core: Prisma, Redis, MinIO, Auth, Encryption
│ ├── services/ # Business logic: Projects, Files, Compilation
│ └── store/ # Zustand state management
├── websocket/ # Yjs WebSocket server (standalone)
├── worker/ # LaTeX compilation worker (BullMQ)
├── prisma/ # Database schema & migrations
├── texlive/ # Custom TeX Live Docker image
├── nginx/ # Reverse proxy configuration
└── docker-compose.yml # Full dev stack orchestration
Authentication
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/auth/register |
Register new user |
POST |
/api/v1/auth/[...nextauth] |
NextAuth.js (login, OAuth) |
POST |
/api/v1/auth/forgot-password |
Request password reset |
POST |
/api/v1/auth/reset-password |
Reset with token |
GET |
/api/v1/auth/verify-email/:token |
Verify email |
POST |
/api/v1/auth/change-password |
Change password (authenticated) |
Projects
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/projects |
List user's projects |
POST |
/api/v1/projects |
Create project |
GET |
/api/v1/projects/:id |
Get project details |
PATCH |
/api/v1/projects/:id |
Update project |
DELETE |
/api/v1/projects/:id |
Soft-delete project |
POST |
/api/v1/projects/:id/clone |
Clone project |
POST |
/api/v1/projects/from-template/:id |
Create from template |
POST |
/api/v1/projects/import |
Import from ZIP (multipart) |
POST |
/api/v1/projects/import-url |
Import from GitHub URL |
Files
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/projects/:id/files |
List files |
GET |
/api/v1/projects/:id/files/:path |
Read file |
PUT |
/api/v1/projects/:id/files/:path |
Write file |
DELETE |
/api/v1/projects/:id/files/:path |
Delete file |
POST |
/api/v1/projects/:id/files/upload |
Upload binary |
User & Account
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/user/profile |
Get user profile |
PATCH |
/api/v1/user/profile |
Update name, institution, bio |
GET |
/api/v1/user/settings |
Get user preferences |
PATCH |
/api/v1/user/settings |
Update editor/notification settings |
DELETE |
/api/v1/user/account |
Delete account (cascading) |
GET |
/api/v1/user/git-credentials |
List git credentials |
POST |
/api/v1/user/git-credentials |
Add encrypted credential |
DELETE |
/api/v1/user/git-credentials/:id |
Remove credential |
Compilation & Export
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/projects/:id/compile |
Trigger compilation |
GET |
/api/v1/projects/:id/compile/:cid/status |
Check status |
GET |
/api/v1/projects/:id/compile/:cid/pdf |
Download PDF |
GET |
/api/v1/projects/:id/compile/:cid/synctex |
Get SyncTeX |
POST |
/api/v1/projects/:id/export/docx |
Export as DOCX |
Collaboration & Sharing
| Method | Endpoint | Description |
|---|---|---|
GET/POST |
/api/v1/projects/:id/members |
List/invite members |
PATCH/DELETE |
/api/v1/projects/:id/members/:uid |
Update/remove member |
POST |
/api/v1/projects/:id/share-link |
Create share link |
GET |
/api/v1/join/:token |
Join via link |
Version History & Git
| Method | Endpoint | Description |
|---|---|---|
GET/POST |
/api/v1/projects/:id/versions |
List/create version |
GET |
/api/v1/projects/:id/versions/:vid/diff |
View diff |
POST |
/api/v1/projects/:id/versions/:vid/restore |
Restore version |
POST |
/api/v1/projects/:id/git/link |
Link remote repo |
POST |
/api/v1/projects/:id/git/push |
Push to remote |
POST |
/api/v1/projects/:id/git/pull |
Pull from remote |
vercel --prodSet environment variables in Vercel dashboard. Use external managed services:
- Database: Neon or Supabase
- Redis: Upstash
- Storage: AWS S3 or Cloudflare R2
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -dIncludes all services: Next.js app, WebSocket server, compilation workers, PostgreSQL, Redis, MinIO, Nginx with SSL.
| Optimization | Details |
|---|---|
| Static Asset Caching | 365-day max-age headers for immutable assets via CDN/Nginx |
| Code Splitting & Lazy Loading | Route-based chunking with Next.js dynamic imports for editor components |
| Database Connection Pooling | PgBouncer manages PostgreSQL connections to minimize overhead |
| Debounced Auto-Save | 2-second debounce prevents excessive writes during active editing |
| Redis Caching | Session data, rate-limit counters, and compilation results cached in Redis |
| Optimized PDF Rendering | PDF.js web worker offloads rendering from the main thread |
| Feature | Implementation |
|---|---|
| Security Headers | HSTS, X-Content-Type-Options, X-Frame-Options, CSP, Permissions-Policy |
| CORS Middleware | Request-level CORS validation with origin whitelist |
| Request Tracing | Unique X-Request-ID header on every response for debugging |
| Compilation Sandbox | Process isolation with temp directories, resource limits |
| Authentication | NextAuth.js v5 with JWT, OAuth (Google, GitHub), bcrypt |
| Encryption | AES-256-GCM for OAuth tokens & Git credentials |
| Rate Limiting | Redis sliding window (100 req/min API, 10 compiles/min) |
| Brute Force Protection | Progressive delay + account lockout after 20 failures |
| Input Validation | Zod schemas with XSS prevention on all endpoints |
| CSRF/XSS Prevention | NextAuth CSRF tokens, React escaping, CSP headers |
| File Upload Guards | MIME whitelist, extension blocking, 50MB/file, 500MB/project, 2GB/user |
- LaTeX editor with syntax highlighting
- Real-time compilation & PDF preview
- Real-time collaboration (Yjs CRDT)
- User authentication (email + OAuth)
- Project management & file manager
- Version history (Git-based)
- Git integration (GitHub/GitLab)
- Template gallery
- Admin panel with audit log
- Real-time auto-compile with debounce
- DOCX export via Pandoc
- Security headers & CORS middleware
- Health check endpoint with dependency monitoring
- Standardized API error responses
- Command palette (Cmd+K) with fuzzy search
- Toast notifications across all operations
- Error boundaries with graceful recovery
- Custom 404 and error pages
- Editor preferences persistence (localStorage)
- WebSocket connection status indicator
- Real-time admin dashboard with health monitoring
- PWA manifest for installability
- Streaming SSR loading skeletons
- Worker graceful shutdown & error recovery
- LaTeX formatting toolbar with Cmd+K command palette
- Rate limiting on all auth endpoints (register, forgot/reset password)
- Unsaved changes warning (beforeunload)
- Standardized API responses with rate limit headers
- Contributing guide & robots.txt
- 100% API standardization (all routes use consistent response format)
- File upload validation (size limits, blocked extensions, path traversal)
- Admin real-time dashboards (15s auto-refresh)
- Comprehensive test suite (1,632 tests — linting, completions, error parsing, API, services, E2E)
- Email error handling (graceful SMTP failure recovery)
- LaTeX syntax highlighting (custom StreamLanguage parser)
- LaTeX autocomplete (70+ commands, Greek letters, environments)
- Editor status bar (word count, line count, file type)
- Tab context menu (close others, close all)
- Bracket auto-closing for LaTeX
- GitHub Actions CI/CD pipeline
- Dynamic sitemap generation
- Document outline panel with section navigation
- LaTeX snippet templates (12 common patterns)
- LaTeX error parser with structured diagnostics
- Keyboard shortcuts dialog
- Project ZIP export (download entire project)
- 100 unit tests across 13 suites
- Login rate limiting + cookie hardening
- Find in Project (Ctrl+Shift+F) with cross-file search
- Clickable compilation errors (jump to source line)
- Dynamic imports for code splitting (lazy-loaded panels)
- Word count goal with progress bar
- Smart LaTeX-aware word counting
- Find in Project via command palette
- BibTeX entry type autocomplete (@article, @book, etc.)
- Inline LaTeX linter (unclosed braces, mismatched environments, typos)
- LaTeX comment toggle (Ctrl+/)
- LaTeX code folding (environments + sections)
- 126 tests across 17 suites
- Rich text / WYSIWYG mode
- Spell check & grammar
- Bibliography manager (BibTeX GUI)
- Beamer presentation mode
- Mobile-responsive editor
- Plugin/extension system
- AI-assisted writing
- Institutional SSO (SAML/LDAP)
Contributions are welcome! Please read our Contributing Guide before submitting PRs.
- Fork the repository
- Create your feature branch (
git checkout -b feat/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feat/amazing-feature) - Open a Pull Request
Found a vulnerability? Please see our Security Policy for responsible disclosure guidelines.
Distributed under the MIT License. See LICENSE for more information.
PaperForge is built on the shoulders of outstanding open-source projects:
- CodeMirror -- Extensible code editor engine powering the LaTeX editing experience
- Yjs -- CRDT framework enabling real-time collaborative editing
- PDF.js -- Mozilla's PDF rendering library for in-browser preview
- Next.js -- React framework for the full-stack application
- shadcn/ui -- Beautifully designed, accessible UI components
- TailwindCSS -- Utility-first CSS framework for rapid styling
- Pandoc -- Universal document converter powering DOCX export
Built with determination by concrete-sangminlee
230+ source files · 1,632 tests (134 suites) · 49 API routes · 25 pages · 8 Docker services · v23.0.0 · Live Demo
Pricing · Getting Started · Docs · API · Symbols · Templates · Status · Changelog
If PaperForge helps your research, consider giving it a star!