A free, open source LaTeX editor with real-time preview capabilities. Think Overleaf, but without compilation limits, completely free, and self-hostable.
- Real-time Preview: See your LaTeX document rendered as you type (optional auto-compile)
- No Compilation Limits: Compile as many documents as you want, whenever you want
- Multi-file Projects: Upload ZIP files with multiple .tex files, images, and fonts
- CV/Resume Support: Full rendering of CV-class documents (russell.cls) with sections, entries, skills tables
- Project Management: Save, open, rename, and delete projects from a sidebar drawer
- SQLite Persistence: Projects stored in a SQLite database on the backend (survives container restarts)
- GitHub Integration: Push/pull projects to/from GitHub repositories with PAT authentication
- Syntax Highlighting: Full LaTeX syntax highlighting for easier editing
- File Management: Add, rename, and delete files directly in the browser
- Free & Open Source: No paywalls, no subscriptions, no restrictions
- Self-Hostable: Run it locally with Docker or deploy to your own server
- Client-side Processing: LaTeX-to-HTML rendering happens in your browser
docker compose build --no-cache && docker compose up -d
# Open http://localhost# Clone the repository
git clone https://github.com/mbianchidev/latex-editor.git
cd latex-editor
# Start with Docker Compose
docker compose up --build -d
# Open http://localhost in your browser# Serve the frontend folder with any static server
cd frontend
python3 -m http.server 8080
# Open http://localhost:8080| Panel | Description |
|---|---|
| Header Bar | Projects drawer, new document, upload ZIP, download .tex/.zip/PDF buttons |
| Projects Drawer (left slide-in) | Manage saved projects β open, rename, delete, GitHub settings |
| File Tree (left) | Shown when a ZIP project is loaded β manage files here |
| Editor (center-left) | Write your LaTeX code with syntax highlighting |
| Preview (right) | Live rendered preview of your document |
| Status Bar | Compilation status and cursor position |
| Shortcut | Action |
|---|---|
Ctrl+Enter |
Compile document |
Tab |
Insert 2 spaces |
- Upload a ZIP file containing your LaTeX project β you'll be prompted for a project name
- Files starting with
._or in__MACOSXfolders are automatically filtered - Use the file tree to navigate between files
- Right-click files for rename/delete options
- The main .tex file is auto-detected (or set manually)
- Projects are auto-saved to the SQLite backend every 5 seconds
- Click Projects in the header to open the projects drawer
- All projects are persisted in a SQLite database on your host machine at
~/.latex-editor/data/(customisable β see Data Storage) - Project names must be unique β duplicates are rejected
- Open, rename, or delete projects from the drawer
- The storage path and database size are shown at the bottom of the projects drawer
- Click Projects β GitHub Settings in the drawer footer
- Enter a GitHub Personal Access Token (PAT) with
reposcope - Enter a repository name (
owner/repo) - Push: Saves all project files as a commit to the repo (creates it if needed)
- Pull: Fetches files from a GitHub repo and loads them as a new project
The "Auto" checkbox controls automatic compilation:
- Off (default): Manual compile only - click βΆ or press
Ctrl+Enter - On: Auto-compile 3 seconds after you stop typing
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\title{My Document}
\author{Your Name}
\date{\today}
\begin{document}
\maketitle
\section{Introduction}
Your content here.
\end{document}\begin{equation}
E = mc^2
\end{equation}
\begin{equation}
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
\end{equation}\begin{itemize}
\item First item
\item Second item
\begin{itemize}
\item Nested item
\end{itemize}
\end{itemize}- Frontend: HTML5, CSS3, Vanilla JavaScript (ES6+)
- Libraries: MathJax 3, jsPDF, html2canvas, JSZip
- Backend: Python/Flask with SQLite, rate limiting (flask-limiter)
- Database: SQLite (bind-mounted to host filesystem)
- Container: Docker with nginx (reverse proxy + CSP headers)
Projects are stored in a SQLite database that lives on your host machine, not inside the Docker container. This means your data survives docker compose down, image rebuilds, and container restarts.
Default path: ~/.latex-editor/data/projects.db
To use a custom path, create a .env file in the project root (see .env.example):
# .env
LATEX_EDITOR_DATA=/path/to/your/dataThe storage path is visible in the projects drawer footer.
latex-editor/
βββ frontend/ # Main application
β βββ index.html # HTML structure + project drawer + GitHub modal
β βββ styles.css # Design system + drawer/modal styles
β βββ app.js # Application logic + project management + GitHub integration
β βββ nginx.conf # Web server config + CSP headers
βββ backend/ # Flask API + SQLite project storage
β βββ app.py # API endpoints (health, documents, projects)
β βββ test_app.py # 43 tests (health, documents, projects CRUD)
β βββ Dockerfile # Backend container with /data volume
β βββ requirements.txt
βββ docker-compose.yml # Container orchestration with backend-data volume
βββ CONTRIBUTING.md # Contribution guidelines
βββ README.md # This file
We welcome contributions! See CONTRIBUTING.md for guidelines.
Quick start for contributors:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
MIT License - see LICENSE for details.
Found a vulnerability? See SECURITY.md for reporting guidelines.
- XSS Prevention: All user-controlled LaTeX content is HTML-escaped before rendering
- Sandboxed Preview: Preview iframe uses
sandbox="allow-scripts"β isolated from the parent page - Content Security Policy: Nginx enforces CSP headers restricting script/style sources
- Rate Limiting: Backend API endpoints are rate-limited via flask-limiter
- Input Validation: Request body size limits, document count caps, filename sanitization
- No Direct Backend Exposure: Backend is only accessible through the nginx reverse proxy
Need help? Check SUPPORT.md for resources.