How I Built LetX: Real-Time Collaborative LaTeX
I built LetX, a real-time collaborative LaTeX editor, using CRDTs for conflict-free editing and sandboxed Docker compile. Here's the full architecture.
I built LetX because every time I co-authored a paper, Overleaf dropped our edits, timed out on compile, or merged in the wrong version. The core problem: real-time document collaboration under LaTeX's strict, stateful compilation model.
The CRDT decision
The first design question was how to merge concurrent edits without conflicts. Operational Transformation (OT) requires a central server to linearize all operations. CRDTs don't — each client converges independently.
I chose a sequence CRDT (specifically a variant of RGA — Replicated Growable Array) for the text buffer. Every character insertion is globally unique via a vector clock + site ID pair. No server arbitration needed for the document state.
type Op struct {
ID VClock
SiteID string
Pos CRDTPos // (leftOrigin, rightOrigin)
Char rune
Deleted bool
}
Conflicts resolve deterministically by comparing site IDs when two insertions target the same position. The CRDT layer runs in Go on the server and TypeScript on the client — same algorithm, both sides.
Sandboxed compile
LaTeX compilation is dangerous: \write18 lets you execute arbitrary shell commands. Every compile job runs in a Docker container with:
- Filesystem isolated via
--read-only+ tmpfs for/tmp - Network disabled (
--network none) - Memory cap: 512 MB, 30s CPU timeout
- PID limit: 64
docker run --rm \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--network none \
--memory 512m \
--pids-limit 64 \
letx-latex-runner \
pdflatex -interaction=nonstopmode main.tex
Output PDF streams back via a signed S3 URL with a 5-minute TTL.
What I'd change
The CRDT serialization is verbose — each operation carries its full vector clock. For documents over ~50k characters, the in-memory op log becomes the bottleneck. Next version will compact via periodic snapshots with a tombstone-pruned state vector.
Try it at letx.app. Built by Shihab Shahriar Antor — Shahriar Labs.