💡 Inspiration
In today's remote-first world, real-time collaboration is no longer a luxury — it's a necessity. Tools like Google Docs have set the bar, but building one from scratch is a deeply technical challenge. I wanted to understand how conflict-free collaborative editing actually works under the hood and build a production-ready version using modern open-source technologies.
🛠️ How I Built It
The core challenge in any collaborative editor is conflict resolution — what happens when two users type at the same position simultaneously?
I solved this using Yjs, a CRDT (Conflict-free Replicated Data Type) library. The math behind CRDTs guarantees that for any two states \( S_1 \) and \( S_2 \):
$$merge(S_1, S_2) = merge(S_2, S_1)$$
This means order of operations never matters — conflicts are mathematically impossible.
Tech Stack
- Frontend: React + Vite + TipTap + Tailwind CSS
- Backend: Node.js + Express + Socket.IO
- Collaboration Engine: Yjs CRDT
- Database: MongoDB Atlas
- Deployment: Vercel + Render
Key Implementation
Yjs encodes document updates as compact binary patches sent over Socket.IO:
// Encode local Yjs update and broadcast to peers
ydoc.on('update', (update) => {
const encoded = Buffer.from(update).toString('base64');
socket.emit('yjs-update', { docId, update: encoded });
});
🚧 Challenges I Faced
1. CORS in production — The trickiest bug was a trailing slash in the CLIENT_URL environment variable on Render. The allowed origin was https://collabedit-nine.vercel.app/ but browsers send it without the slash — one character caused hours of debugging.
2. Yjs state hydration — Loading persisted Yjs binary state from MongoDB and applying it to a fresh Y.Doc on room creation required careful sequencing to avoid state corruption.
3. Custom Socket.IO bridge — Instead of using the standard y-websocket provider, I built a custom Socket.IO bridge encoding Yjs updates as base64 — giving full control over rooms, presence, and events.
📚 What I Learned
- Deep understanding of CRDT theory and why it outperforms OT (Operational Transformation) for collaborative editing
- How to architect real-time WebSocket rooms with proper lifecycle management
- Production deployment challenges across Vercel + Render + MongoDB Atlas
- Debugging environment-specific issues like CORS, dynamic IPs, and binary state serialization
✨ Features
- Real-time CRDT sync — zero conflicts, instant updates
- Live cursors — see every user's cursor with their name and color
- User presence — avatar stack showing who's online
- Rich text formatting — Bold, Italic, Underline, Headings, Lists, Code
- Auto-save — persists to MongoDB every 3 seconds
- Revision history — browse and preview past versions
- Dark mode — persisted across sessions
- Shareable links — one click to copy and share
🔗 Try It Out
- 🌐 Live Demo: collabedit-nine.vercel.app
- 💻 GitHub: HariOm-Coder-Ambadnya/collabedit
Built With
- atlas
- express.js
- github
- javascript
- mongodb
- node.js
- react
- render
- socket.io
- tailwindcss
- tiptap
- vercel
- vite
- yjs
Log in or sign up for Devpost to join the conversation.