💡 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

Built With

Share this project:

Updates