- 🌌 Project Overview
- 🛑 The Problem & Solution
- ⚡ Key Features
- 📐 System Architecture
- 📁 Directory Structure
- 🛠️ Tech Stack
- 🚀 Getting Started
- 🔍 Troubleshooting & FAQs
- 🤝 GirlScript Summer of Code (GSSOC) Contributors Guidelines
- 👑 Project Admins & Maintainers
- 📜 License
Glyph is an open-source, web-based collaborative LaTeX editor engineered for team productivity and speed. It provides real-time document synchronization, high-fidelity compilation inside sandboxed environment, live syntax highlighting, workspace management, and instant sharing permissions.
Whether you are writing a research paper with peers, putting together homework assignments, or designing documentation templates, Glyph offers a distraction-free space to compose and compile TeX sources directly in your browser.
- Host Security Risks: Compiling user-submitted LaTeX documents directly on a host server is highly insecure. TeX packages can execute arbitrary system commands via
\write18or perform file reads/writes, compromising host security. - Synchronization Overhead: Collaborative LaTeX writing often relies on manual Git syncs or expensive subscription models, which degrades the rapid authoring workflow.
- Clunky Setups: Setting up a complete LaTeX ecosystem locally requires downloading massive packages (~5GB for
texlive-full), configuring system environment variables, and maintaining separate compilers.
- Sandboxed compilation worker: Compilations are handled by an isolated Docker container (
ubuntubase +texlive-full) with restricted privileges, protecting the server. - CRDT-based Real-time collaboration: Integrated with Yjs and WebSocket protocols to enable seamless, low-latency, conflict-free editing, complete with active collaborator lists and cursor presence.
- Painless setup: Glyph bundles dependencies inside Docker. It offers a hybrid compile capability—using host
latexmkif installed, or falling back seamlessly to Docker compilation if not.
- Real-Time Editing & Sync: Live collaboration powered by Yjs CRDTs over WebSockets. Watch teammates make edits, select text, and move their cursors in real time.
- Sandboxed Background Compilation: Compilation jobs are managed via a database-backed transaction queue (
FOR UPDATE SKIP LOCKED) and processed in isolation. - Persistent File Explorer: Tree-structured workspace explorer supporting nested files and folders. The workspace structure is persisted inside PostgreSQL.
- Hybrid Compilation: Smart compile flow. Automatically detects local host capabilities and defaults to Docker-based sandboxed compilation if TeX Live is missing locally.
- Access Control & Shareable Links: Control permissions dynamically. Share read-only or collaborative (write-access) projects via unique Clerk-integrated tokens or invite collaborator IDs directly.
- Split Screen Previewing: View output instantly side-by-side using the built-in PDF viewer or preview compiled LaTeX documents as live HTML.
Glyph utilizes a decoupled modern architecture combining a monorepo workspace for frontend components, an API server, and a background queue worker.
graph TD
%% User Interfacing
Client[Next.js Client Client App]
Editor[CodeMirror 6 / Editor]
Client -->|WS Protocol / Cursor / Document Updates| YjsServer[Yjs WS Server Hono]
Client -->|REST HTTP Requests| APIServer[API REST Server Hono]
%% Authentication & Databases
Clerk[Clerk Auth JWT Service] <-->|Validate Auth Tokens| APIServer
APIServer -->|Read/Write Projects, Collaborators, Share Links| PostgreSQL[(PostgreSQL Database)]
YjsServer -->|Persist Binary Document State as BYTEA| PostgreSQL
%% Compilation Orchestration
APIServer -->|Enqueue Compilation Job status: queued| PostgreSQL
%% Sidecar worker polling
Worker[Compile Sidecar Worker] <-->|Transaction Poll: FOR UPDATE SKIP LOCKED| PostgreSQL
Worker -->|Write Project Source Files| TempDir[Local Workspaces: /tmp/workspaces]
%% Compiling
TempDir -->|Host Compiler| LocalTex[latexmk on Host]
TempDir -->|Fallback Mount: /workspace| DockerContainer[Docker Sandboxed Container: glyph-compiler]
LocalTex -->|Output main.pdf| Worker
DockerContainer -->|Output main.pdf| Worker
%% Save PDF back
Worker -->|Update compilation status: success, write pdf_data BYTEA| PostgreSQL
Glyph/
├── .github/ # GitHub issues, PR templates, and workflow configurations
├── docker/ # Docker container build scripts for LaTeX compilation
│ ├── Dockerfile # Standard Ubuntu 24.04 image + TeX Live full suite
│ └── worker.sh # Safe bash script parsing TeX parameters & running latexmk
├── frontend/ # Next.js Frontend application (TypeScript, Tailwind CSS v4)
│ ├── src/
│ │ ├── app/ # Application pages (Landing, Dashboard, Profile, Editor)
│ │ ├── components/ # UI components (Editor, PdfViewer, ShareModal, Sidebar)
│ │ ├── lib/ # API client, compile triggers, and network helpers
│ │ └── types/ # Core typescript interfaces (Project, File, Collaborator)
│ └── public/ # Global static files and images
├── server/ # Hono Backend REST API & WebSockets server (Node.js, TypeScript)
│ ├── src/
│ │ ├── config/ # Configurations: environment variables, DB client, Yjs sockets
│ │ ├── controllers/ # Controller handlers orchestrating database modifications
│ │ ├── routes/ # REST Endpoint declarations (Auth, Projects, Collaborators)
│ │ ├── compileWorker.ts # Queue listener sidecar polling and running LaTeX builds
│ │ └── index.ts # Server boot script listening to API requests & WebSockets
├── scripts/ # Utility scripts for development
│ └── dev.sh # Pre-flight environment verifier and auto-start manager
├── docker-compose.yml # Full-stack orchestration (DB, backend, frontend, compile-worker)
├── package.json # Root npm workspace configuration (Monorepo setup)
└── package-lock.json # Locked packages for monorepo consistency
- Framework: Next.js 16 (App Router) for rapid server-side hydration, path routing, and high-performance client applications.
- Language: TypeScript to enforce robust type-safety across components.
- Styling: Tailwind CSS v4 featuring modern utility variables, flexbox structures, and dark/light system color palettes.
- Editor Engine: CodeMirror 6 for extensible syntax highlighting, lines rendering, linting, and plugin support.
- State Sync: Yjs implementing conflict-free replicated data types (CRDTs) to sync editor models.
- API Framework: Hono v4 (Node.js) for lightweight, fast HTTP route handling and WebSockets server gateway.
- Document Synchronization: Y-Websocket server provider managing WebSocket updates, synchronizing document vectors, and writing binary states back to database.
- Database Client: node-postgres (
pg) using connection pooling for optimized, concurrent queries.
- Database: PostgreSQL storing user files, access roles, project hierarchies, and raw PDF data.
- Authentication: Clerk Auth providing secure login flow, profile controls, session persistence, and organization validation.
- Isolation: Docker creating a sandboxed, dependency-secure Linux environment (
ubuntubase +texlive-fullbuild tools) for compiling LaTeX source trees safely.
Follow the guide below to set up your local development environment.
Ensure you have the following installed:
- Node.js:
v20.xor later. - Docker Desktop: Required for PostgreSQL, LaTeX compilation, and optional full-stack deployment. Ensure Docker is running.
- Clerk Account: Free account to manage user authentication.
Note: You do not need a separate PostgreSQL installation — Docker Compose provides one automatically.
Before running Glyph, you must register a project with Clerk:
- Go to the Clerk Dashboard and create a new application.
- Select Email and GitHub/Google as social providers.
- Once created, copy the Publishable Key and Secret Key.
- In the Clerk dashboard, set your redirect URLs:
- Sign In:
http://localhost:3000/sign-in - Sign Up:
http://localhost:3000/sign-up - After Sign In:
http://localhost:3000/dashboard - After Sign Out:
http://localhost:3000/
- Sign In:
Glyph uses a single .env file at the repository root to configure all services (frontend, backend, database, and compile worker).
# Copy the template
cp .env.example .envThen open .env and fill in your keys:
# ── CLERK AUTHENTICATION ──────────────────────────────────────
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... # From Clerk Dashboard
CLERK_PUBLISHABLE_KEY=pk_test_... # Same as above
CLERK_SECRET_KEY=sk_test_... # From Clerk Dashboard
# ── GEMINI AI ASSISTANT ───────────────────────────────────────
GEMINI_API_KEY=your_gemini_api_key_here # From Google AI Studio
GEMINI_MODEL=gemini-2.5-flashAll other values (ports, database credentials, Clerk routes) have sensible defaults — you only need to set the keys above.
The easiest way to start everything. One command boots PostgreSQL + Backend + Frontend + Compile Worker:
# Build all service images
docker compose build
# Start the entire stack in detached mode
docker compose up -d| Service | URL | Description |
|---|---|---|
| Frontend | http://localhost:3000 | Next.js web application |
| Backend | http://localhost:8083 | Hono REST API + WebSocket server |
| Database | localhost:5433 |
PostgreSQL (mapped to host port 5433) |
| Compile Worker | — | Background LaTeX compilation queue |
To stop all services:
docker compose downFor hot-reloading during development, use the helper script. It loads environment variables from the root .env, installs dependencies, builds the LaTeX compiler image, and starts all dev servers concurrently:
# Make the helper script executable (first time only)
chmod +x scripts/dev.sh
# Start the dev environment
./scripts/dev.shNote: This option requires a running PostgreSQL instance. You can start one with
docker compose up db -dbefore running the script.
If you prefer full control over each step:
npm installdocker compose up db -dThis starts PostgreSQL on host port 5433 with credentials from your .env file. The database schema is auto-created on backend startup.
docker build -t glyph-compiler ./dockernpm run dev- Frontend: http://localhost:3000
- Backend: http://localhost:8083
- Cause: This happens if your
main.texfile contains compilation errors or misses structural definitions. - Resolution: Check the "Logs" pane in the editor sidebar. It details the line numbers and LaTeX compiling errors thrown by
latexmk.
- Cause: Your user account does not have sufficient permission to access the Docker daemon socket (
/var/run/docker.sock). - Resolution: Ensure Docker Desktop is running. On Linux hosts, add your user to the docker group:
After updating group permissions, restart your shell or computer for changes to take effect.
sudo usermod -aG docker $USER
- Cause: Missed matching Clerk environment variables in the root
.envor Clerk settings. - Resolution: Verify that
NEXT_PUBLIC_CLERK_SIGN_IN_URLis set to/sign-inandNEXT_PUBLIC_CLERK_SIGN_UP_URLis set to/sign-up, and match these targets inside the Clerk dashboard settings.
- Cause: The Hono server cannot establish connection with PostgreSQL.
- Resolution: Ensure PostgreSQL is up (run
docker compose up db -d). The default connection uses host port5433. Double-check yourDATABASE_URLin the root.envfile.
Welcome to GSSOC '26! 🎉 We are excited to collaborate with you to build Glyph. To ensure a smooth experience, please follow these guidelines strictly:
- Never work on unassigned issues: Pull Requests referencing issues that are not formally assigned to you by a Project Admin/Mentor will not be accepted.
- Claiming an issue: Browse the Issues list, identify an open item, and comment on it stating why you would like to tackle it.
- Timeout rule: Assigned issues must have progress shown within 3 days. If there are no updates or code submissions, the issue will be unassigned and reassigned to other waiting contributors.
Create a dedicated branch from the latest upstream main for every issue. Name your branch using the format below:
feature/issue-[issue-number]-[brief-description]
fix/issue-[issue-number]-[brief-description]
docs/issue-[issue-number]-[brief-description]
Example: feature/issue-42-dark-mode-toggle
We use Conventional Commits standards. This helps keep our git log clean and readable:
feat: <description>: Introducing a new feature.fix: <description>: Fixing a bug.docs: <description>: Writing or updating documentation (e.g. README updates).refactor: <description>: Modifying code without adding features or fixing bugs.style: <description>: Formatting adjustments, whitespace cleanup, or missing semi-colons.chore: <description>: General maintenance tasks, package updates, or CLI scripts.
Example commit: git commit -m "feat: add real-time active users list component"
- Linting: Verify that all files adhere to lint configurations prior to opening a PR.
# Run in frontend folder npm run lint # Check types in server folder npm run type-check:server
- Clean PRs: Always create self-contained Pull Requests. One PR should solve exactly one issue. Do not bundle multiple unrelated features into a single PR.
| Profile | Role | Contact Channels |
|---|---|---|
| Anik | Project Admin & Creator |
Distributed under the Apache License 2.0. See the LICENSE file in the root directory for more details.