A web-based LaTeX editor with real-time preview, syntax highlighting, and PDF compilation.
# Start the server
cd backend
go run .Then open http://localhost:8080 in your browser.
# Build and run
docker-compose up -d
# Access at http://localhost:8080Data is persisted in a Docker volume.
┌─────────────────────────────────────────────────────────────────┐
│ Browser · Frontend │
├───────────────┬────────────────┬────────────────┬───────────────┤
│ Monaco │ Sidebar │ Topbar │ PDF Viewer │
│ Editor │ (files) │ (actions) │ │
└───────────────┴────────────────┴────────────────┴───────────────┘
│
HTTP API · port 8080
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Go Backend · Port 8080 │
├───────────────────┬──────────────────┬──────────────────────────┤
│ Handlers │ SQLite │ Temp Dir │
│ routes.go │ db.go │ (compile) │
└────────┬──────────┴────────┬─────────┴──────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────────────────────────────────┐
│ compile/ │ │ data/ │
│ latex.go │ │ texleaf.db ◄── all data stored here │
└─────────────────┘ └─────────────────────────────────────────────┘
All project data is stored in a single SQLite database (data/texleaf.db):
- Projects table: Project metadata (id, uuid, name, main_file, timestamps)
- Project files table: All project files (project_id, filename, content as BLOB)
- Output PDF: Stored in DB as binary
- Compile logs: Stored in DB as text
No file system storage for project content - everything is in SQLite.
- User clicks "Compile" in the editor
- Backend receives request with project UUID
- Step 1: All files are fetched from SQLite and written to a temp directory
- Step 2: pdftex is executed in the temp directory with the main .tex file
- Step 3: The generated PDF is read from temp dir and stored in SQLite
- Step 4: Compile log is stored in SQLite
- Step 5: Temp directory is cleaned up
- Browser receives PDF via GET /output.pdf
- Draft mode: Runs pdftex with
-draftmodeflag (fast, no PDF output, just checks for errors) - Full mode: Generates actual PDF, may run twice for cross-references
- Backend: Go
- Database: SQLite
- Editor: Monaco Editor
- PDF: PDF.js
- Local: Go 1.23+, TeX Live or MacTeX
- Docker: Docker + Docker Compose
| Test | Description | Time (s) |
|---|---|---|
| T1 | 10000 macro expansions (\foreach, integer print only) |
0.19 |
| T2 | 3000 blocks of text using \lipsum[1] (no page breaks) |
9.2 |
| T3 | 1500 iterations of multi-paragraph \lipsum[1-4] |
1.07 |
| T4 | 500 sections with forced \newpage after each block |
0.61 |
| T5 | 400 blocks with itemize lists + horizontal rules | 0.47 |
| T6 | 300 mixed blocks (sections + paragraphs + lists + pages) | 6.8 |
