🔗 Live Demo: https://syncdraft.vercel.app/
👉 Open the same document in two tabs to see real-time collaboration.
We welcome contributors of all levels! If you'd like to help, please read CONTRIBUTING.md for how to get started, our workflow, and a list of issues suitable for beginners. Look for issues labeled good first issue or help wanted.
Tip
Use this navigation map to jump to the section you need.
| 🧭 Overview | What is SyncDraft? · Features · Architecture Overview · Tech Stack |
| 🚀 Getting Started | Live Demo · Quick Start (Local Development) · Environment Configuration · Running Locally |
| 📈 Operations | Metrics · UI Preview · Troubleshooting · Security Notes |
| 🗂 Project | Contributing · Roadmap · License |
SyncDraft is an open-source, CRDT-powered collaborative editor inspired by tools like Google Docs — built to be offline-first, conflict-free, and horizontally scalable.
SyncDraft uses Yjs as the CRDT engine to guarantee:
- No overwriting of edits
- Automatic document convergence
- Seamless collaboration even on unstable networks
This project is intended as a production-minded reference implementation for real-time collaborative systems.
- Real-time collaborative editing using Yjs
- Conflict-free merging (CRDTs — no locks, no last-write-wins)
- Offline-first editing with automatic resynchronization (via Yjs)
- Multi-user presence & cursor awareness
- (Planned) Version snapshots & document history using Yjs snapshot APIs
- Authentication integration with Supabase
- Horizontally scalable WebSocket backend (Hocuspocus + Redis)
- Prometheus-compatible metrics endpoint
Note: Some higher-level features (persistent, long-term document history / snapshots and fine-grained permissions) are mentioned as planned — see Roadmap for details.
Frontend (React + TipTap) ↓ Yjs CRDT Document State ↓ Hocuspocus WebSocket Server ↓ Redis (Awareness + Horizontal Scaling / Upstash) ↓ Supabase (Auth & Metadata — optional persistence)
- Yjs — Shared document state and conflict resolution
- TipTap — Editor layer (ProseMirror-based)
- Hocuspocus — Collaborative WebSocket sessions (backend)
- Redis / Upstash — Awareness + horizontal scaling support
- Supabase — Authentication & optional metadata persistence
- prom-client — Metrics for Prometheus
- React (Create React App)
- TipTap
- Yjs
- Supabase JS client
- Node.js (ESM)
- @hocuspocus/server (Hocuspocus)
- @hocuspocus/extension-redis
- ioredis / Upstash compatible settings
- prom-client (Prometheus metrics)
- Supabase (Auth & Database)
- Vercel (Frontend hosting)
- Render (Backend hosting) — optional example
👉 https://syncdraft.vercel.app/
Try this:
- Create a document (via demo UI)
- Open the same document in two tabs or browsers
- Watch edits sync in real time — conflict-free
(If the demo is down, feel free to run locally — instructions below.)
- Node.js 18+ (recommended)
- npm 9+
- Redis instance (Upstash or other Redis with TLS)
- Supabase project (optional for auth functionality)
Project structure of interest:
- server/ — Hocuspocus backend
- syncraft/ — React frontend
git clone https://github.com/Sachin1395/Distributed-Collaborative-Editor.git
cd Distributed-Collaborative-EditorOpen two terminals or use a multiplexer:
Terminal A — backend:
cd server
npm installTerminal B — frontend:
cd syncraft
npm installThis repository uses per-package .env.example files. Copy and edit each .env.example into a .env file in the same directory.
- server/.env.example — backend settings
- syncraft/.env.example — frontend settings
Important: do not commit .env files or secrets.
Example (server/.env.example):
# server/.env.example
PORT=1234
REDIS_URL=rediss://<token_or_credentials>@<host>:<port> # Upstash or Redis Cloud (use TLS)
SUPABASE_URL=https://<project>.supabase.co
SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key> # keep this secret and never expose to the browser
ALLOWED_ORIGINS=http://localhost:3000
METRICS_PORT=4000
METRICS_TOKEN=<optional-metrics-token>Example (syncraft/.env.example — frontend uses Create React App ENV prefix):
# syncraft/.env.example
REACT_APP_SUPABASE_URL=https://<project>.supabase.co
REACT_APP_SUPABASE_ANON_KEY=<public-anon-key>
REACT_APP_WS_URL=ws://localhost:1234Notes:
- The frontend uses
REACT_APP_*env variables because it is a Create React App project. Do NOT useNEXT_PUBLIC_*unless you migrate the frontend to Next.js. - For Upstash, prefer
rediss://(TLS). The backend code configures ioredis with TLS andenableReadyCheck: falsefor Upstash compatibility.
- Start the backend (Hocuspocus server)
cd server
npm startBy default the server listens on port 1234 (WS and HTTP). If you set PORT in server/.env it will be used.
Accessible at:
- WebSocket: ws://localhost:1234
- HTTP: http://localhost:1234 (Hocuspocus itself is a WS server — see metrics below)
- Start the frontend
cd syncraft
npm startBy default the React app runs at:
Make sure REACT_APP_WS_URL in syncraft/.env points to your backend WS URL (e.g. ws://localhost:1234).
The backend exposes a Prometheus-compatible metrics endpoint. Configure the following server env vars:
- METRICS_PORT (default in code: 4000)
- METRICS_TOKEN (optional) — if set, requests to /metrics must include
Authorization: Bearer <METRICS_TOKEN>
Metrics endpoint example:
http://localhost:4000/metrics
The backend includes a gauge for active WebSocket connections (ws_active_connections) and also registers default process metrics.
-
WebSocket not connecting
- Ensure backend is running and
REACT_APP_WS_URLpoints to the correct host and port (default ws://localhost:1234). - Check browser console for CORS/Origin errors; ensure
ALLOWED_ORIGINSin server/.env contains your frontend origin (e.g. http://localhost:3000).
- Ensure backend is running and
-
Redis Errors
- Upstash requires TLS — use a
rediss://URL and the backend creates the Redis client with TLS enabled. - Ensure REDIS_URL is set in server/.env. The server will throw an error and exit if REDIS_URL is not provided.
- Upstash requires TLS — use a
-
CORS / Origin blocked
- The Hocuspocus server checks the
Originheader and will reject connections not in ALLOWED_ORIGINS when that list is non-empty.
- The Hocuspocus server checks the
-
Metrics unauthorized
- If METRICS_TOKEN is set, requests to /metrics must include the header
Authorization: Bearer <METRICS_TOKEN>.
- If METRICS_TOKEN is set, requests to /metrics must include the header
- Never expose the Supabase Service Role Key or any privileged keys to the browser or commit them to source control. SUPABASE_SERVICE_ROLE_KEY belongs in server/.env only.
- Keep
.envfiles out of your repository (they are not included in this repo). - Upstash / Redis credentials are sensitive — use access controls and rotation as needed.
- The project uses Hocuspocus + Redis for session state, awareness and horizontal scaling. Long-term document persistence (durable snapshots / database-stored history) is not yet fully implemented in this repository.
- Yjs supports snapshots and you can persist them to storage (S3, Postgres, etc.). If you need durable history, add a persistence extension to Hocuspocus or export Yjs snapshots to your DB in the backend.
Contributions are welcome! Please see CONTRIBUTING.md for how to get started and the Code of Conduct.
Planned / desirable improvements:
- Granular document permissions & ACLs
- Comments & suggestions mode (comment threads)
- Export to Word Document / PDF (frontend export presets)
- Improved offline persistence / background sync
- End-to-end encryption (E2EE) for document content
- Persistent snapshot storage & version history
This project is licensed under the MIT License.
See the LICENSE file for details.

