# typst-leaf 🍂 A completely self-hostable, high-performance editor for [Typst](https://typst.app/), built on the philosophy of "Git as the Database." **Features:** * **Instant Preview:** Sub-50ms incremental compilation using `tinymist`. * **Live diagnostics & autocomplete** from the Typst language server. * **Git Native:** No hidden databases. Your projects are just folders. * **Hybrid:** Run it in a browser, or as a native desktop app via Tauri. ## 📂 Repository Structure ```text typst-leaf/ ├── typst-leaf-backend/ # Node.js/TS server (spawns tinymist, REST + WS) ├── typst-leaf-frontend/ # React + Monaco frontend (includes Tauri) ├── VISION.md # Project philosophy and architecture └── AGENTS.md # Guidelines for AI coding assistants ``` ## Prerequisites * **Node.js 20+** * **pnpm** (10+) * **Rust** (only required for the Tauri desktop wrapper) * **`tinymist`** on your `PATH` — the Typst language server & preview engine: ```bash cargo install --git https://github.com/Myriad-Dreamin/tinymist --bin tinymist --locked tinymist-cli ``` ## 🚀 Quick Start (Development) ```bash # 1. Install workspace dependencies pnpm install # 2. Start the backend (port 4000) pnpm --filter typst-leaf-backend dev # 3. Start the web frontend (port 1420 — mandated by Tauri) pnpm --filter typst-leaf-frontend dev # 4. (Optional) Launch the Tauri desktop wrapper pnpm --filter typst-leaf-frontend tauri dev ``` Then open in your browser. A `hello` project is auto-seeded on first run. ### Environment variables | Var | Default | Description | | --- | --- | --- | | `PROJECTS_ROOT` | `/projects` | Directory under which project folders live. The backend refuses to read or write outside this root. | | `TINYMIST_PREVIEW_HOST` | `127.0.0.1` | Host the tinymist preview server binds to. | | `TINYMIST_PREVIEW_PORT` | `23635` | Port the tinymist preview server binds to. | | `PORT` (backend) | `4000` | Backend HTTP/WS port. | | `FRONTEND_ORIGIN` (backend) | `http://localhost:1420` | CORS origin allowed to call the REST API. | ## 🏗️ Architecture * **Editor:** Monaco Editor * **LSP:** `tinymist` over a WebSocket thin proxy * **Preview:** Backend spawns `tinymist preview ` on demand; the frontend iframes its webview for live SVG updates. * **Data plane:** * `ws://localhost:4000/lsp` → `tinymist lsp` (single active connection, takeover on reconnect) * `GET /api/projects`, `GET/PUT /api/projects/:p/file?path=…`, `POST /api/projects/:p/focus?path=…`