Web · Intermediate

Realtime Collaborative Whiteboard

Build a multiplayer canvas where many cursors draw and edit live with no merge conflicts, using CRDTs over WebSockets.

Intermediate15-25 hoursTypeScript

You will build a browser-based whiteboard where multiple users can draw shapes, add sticky notes, and move elements simultaneously without ever seeing conflicting states. The core challenge is wiring a CRDT library (Yjs) through a WebSocket server so every client converges to the same document, even after a network drop and reconnect. This project is worth building because CRDTs and operational synchronization are the foundation of every serious collaborative tool, from Figma to Notion, and hands-on experience with them is rare on a resume.

What you build

  • Shared infinite canvas with real-time cursor presence showing each user's name and pointer position
  • Drawing tools: freehand pen, rectangles, ellipses, and sticky notes backed by a Yjs shared document
  • Automatic conflict-free merging via CRDTs so concurrent edits never overwrite each other
  • Persistent rooms: the Yjs document state is stored server-side and replayed on reconnect
  • Undo/redo that works per-user without affecting collaborators' history
  • Live participant list showing who is currently in the room

What it teaches

  • How CRDTs (specifically Yjs Y.Map and Y.Array) achieve convergence without a central lock or operational transformation
  • WebSocket lifecycle management: connection, reconnection, and backpressure in a Node server
  • Yjs Awareness protocol for ephemeral shared state like cursors and selection that does not need CRDT guarantees
  • Canvas rendering strategies: when to use an abstraction layer like tldraw versus a raw HTML Canvas or SVG approach
  • Per-user undo stacks in a shared document using Yjs UndoManager scoped to local origin
  • Deploying stateful WebSocket servers alongside a Next.js app on platforms that separate serverless from long-lived connections

How it works

  1. 1

    User draws on canvas

    • tldraw dispatches a store mutation
    • Local Yjs doc updated immediately
  2. 2

    Yjs encodes the delta

    • Y.Doc computes a binary update
    • Update sent over WebSocket to y-websocket server
  3. 3

    Server broadcasts

    • y-websocket relays binary update to all room peers
    • Server persists doc state (LevelDB / Redis)
  4. 4

    Peers receive and merge

    • Each client's Y.Doc applies the update
    • CRDT guarantees convergence with no conflicts
  5. 5

    Canvas re-renders

    • tldraw reads updated Yjs store
    • All cursors and shapes reflect the merged state
fig. 01 — data flow from one user's draw action to all connected clients

Sign in to open the build guide

Free account. Get the step-by-step build and every resource link.

Sign in to continue

Take it further

  • Add a voice/video sidebar using the WebRTC DataChannel so collaborators can talk while drawing without leaving the app.
  • Implement version history by snapshotting the Yjs binary document state to a database on every significant edit and building a timeline slider that restores past snapshots.
  • Replace y-websocket with Liveblocks as the sync backend to explore a managed CRDT-as-a-service alternative and compare the tradeoffs in latency, pricing, and vendor lock-in.

More like this

All projects