Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Real-Time Collaboration System

The real-time collaboration system allows multiple users to edit the same document simultaneously. Changes are instantly synchronized across all connected clients with Yjs handling the complexity of operational transformation and conflict resolution.

Core Technologies

  • Yjs - CRDT-based shared data structure for conflict-free collaboration
  • y-websocket - WebSocket provider for real-time synchronization
  • CodeMirror - Rich text editor with Yjs integration
  • Node.js WebSocket Server - Central hub for document synchronization

Architecture

System Components

┌─────────────────────────────────────────────────────────────┐
│                    Web Browsers (Clients)                   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────────────┐  ┌──────────────────┐  ┌───────────┐  │
│  │   User A         │  │   User B         │  │ User C    │  │
│  │  CodeMirror      │  │  CodeMirror      │  │ CodeMirror│  │
│  │  + Yjs Doc       │  │  + Yjs Doc       │  │ + Yjs Doc │  │
│  └────────┬─────────┘  └────────┬─────────┘  └─────┬─────┘  │
│           │                     │                  │        │
│           └─────────────────────┼──────────────────┘        │
│                                 │                           │
│                          WebSocket Updates                  │
│                           (JSON/Binary)                     │
└─────────────────────────────────┼───────────────────────────┘
                                  │
                    ┌─────────────▼──────────────┐
                    │   WebSocket Server         │
                    │   (Node.js + y-websocket)  │
                    │                            │
                    │  Document Rooms:           │
                    │  - Room 1 (Project A)      │
                    │  - Room 2 (Project B)      │
                    │  - Room N (Project N)      │
                    └────────────────────────────┘

Data Synchronization Flow

Single Edit Operation

User A types "function" in CodeMirror
         │
         ▼
Yjs detects text insertion at position 42
         │
         ▼
Creates update event with operation metadata
    {
      type: "insert",
      position: 42,
      content: "function",
      clientID: "user-a-xyz", 
      clock: 1234
    }
         │
         ▼
WebSocket sends update to server
         │
         ▼
Server broadcasts to all other clients (B, C, D, ...)
         │
         ▼
Each client receives update
         │
         ▼
Yjs applies update to local document state
         │
         ▼
CodeMirror re-renders with new text
         │
         ▼
✓ All clients see "function" at position 42

Concurrent Editing Example

Two Users Editing Simultaneously

Well, what happens when multiple user are on a single project, but different sections?
See below:

Initial State:

Document: "Hello"
Cursor positions: A at index 5, B at index 0

Operations:

User A (timestamp: T1)          User B (timestamp: T1)
Inserts "!" at end              Inserts ">> " at start
        │                               │
        └───────────┬───────────────────┘
                    │
            Local operation applied
            Local reorder: T1-A, T1-B
                    │
                    ▼
         User A sees: ">> Hello!"
         User B sees: ">> Hello!"

Without Conflict Resolution (Bad):

User A alone would see: "Hello!"
User B alone would see: ">> Hello"
Inconsistent state → ✗ BROKEN

With Yjs CRDT (Good):

Yjs uses client IDs and logical clocks
Deterministic ordering: (clock, clientID)
Both users converge to: ">> Hello!"
Consistent state → ✓ WORKS

Real-Time Update Propagation

Multi-Client Synchronization Timeline

How does multi-Client synchronization happens?

T0:00 - User A connects to project "thesis-2024"
        │
        ├─ Handshake: Hello, I'm user-a-xyz
        ├─ Server: Here's the current document state
        └─ CodeMirror renders initial content

T0:05 - User B connects to same project
        │
        ├─ Server sends full document state to B
        ├─ Server notifies A that B joined
        └─ Awareness layer shows "User B is editing..."

T0:10 - User A types "Introduction"
        │
        ├─ Yjs creates update: insert(0, "Introduction")
        ├─ WebSocket sends to server (~5-10ms latency)
        ├─ Server broadcasts to B
        ├─ B receives and applies update
        └─ B's CodeMirror updates live ✓

T0:15 - User B types "Section 1" (while A is still editing)
        │
        ├─ B's update goes to server
        ├─ A receives B's update
        ├─ Yjs merges both edits (no conflicts!)
        ├─ Both see same final text
        └─ Automatic sync ✓

T0:20 - User A disconnects
        │
        ├─ Server marks A as offline
        ├─ B can continue editing
        └─ When A reconnects, gets full sync

T0:25 - User C connects
        │
        ├─ Server sends full document state
        ├─ C gets all A and B's edits
        └─ C's document is immediately current ✓

Conflict Resolution

Automatic CRDT Merging

SCENARIO: Two users insert at same position simultaneously

Initial: "Hello world"

User A: Insert "beautiful " at position 6
        Result intention: "Hello beautiful world"

User B: Insert "amazing " at position 6
        Result intention: "Hello amazing world"

════════════════════════════════════════════════════════════

WITHOUT YEJS (Simple Last-Write-Wins):
├─ User A's update arrives first: "Hello beautiful world"
├─ User B's update arrives second: "Hello amazing world"
└─ Result: B's text overwrites A's → DATA LOSS ✗

════════════════════════════════════════════════════════════

WITH YEJS (CRDT - Conflict-Free Replicated Data Type):
├─ A's insert: (position: 6, clientID: A, clock: 1)
├─ B's insert: (position: 6, clientID: B, clock: 1)
├─ Deterministic ordering by (clock, clientID)
│  → clientID: A < B (alphabetically)
│  → A's insert happens first in canonical order
└─ Result: "Hello beautiful amazing world"
   Both A and B converge to SAME final state ✓
   NO DATA LOSS ✓

Awareness State

Seeing Who’s Online

┌─────────────────────────────────────────────────┐
│ Document: "thesis-2024/main.tex"                │
├─────────────────────────────────────────────────┤
│                                                 │
│ Online Users:                                   │
│ ┌──────────────────────────────────────────┐    │
│ │ 🔴 Alice (you)          Editing Line 42  │    │
│ │ 🟢 Bob                  Idle for 30s     │    │
│ │ 🟡 Carol                Editing Line 128 │    │
│ └──────────────────────────────────────────┘    │
│                                                 │
│ Cursor Positions:                               │
│ │                                               │
│ │  Alice's cursor 🔴                            │
│ │  Bob's cursor           🟢                    │
│ │  Carol's cursor                      🟡       │
│ │                                               │
│ └─ Each user sees others' cursors in real-time  │
│                                                 │
└─────────────────────────────────────────────────┘