Skip to content

Latest commit

 

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Collaborative Whiteboard

A real-time collaborative whiteboard built with Next.js, Excalidraw, and Y.js. Local-first with offline support, using CRDTs for conflict resolution and eventual consistency. No central authority.

Overview

This project is a collaborative whiteboard that allows users to:

  • Draw freehand sketches
  • Add Shapes (rectangles, ellipses, arrows, etc.)
  • Eraser
  • Collaborate Real-time: See other users' changes instantly
  • Share-Via-URL: No login required. Just share the URL
  • Offline Support: Continue working offline, changes sync when reconnected

Tech Stack

  • Frontend: Next.js (App Router), React, Tailwind CSS
  • Whiteboard Engine: Excalidraw
  • Real-time Sync: Y.js - CRDT (Conflict-free Replicated Data Type) library
  • WebSocket Server: Y.js WebSocket server
  • Offline Persistence: y-indexeddb

Architecture

(Made on this project's site itself!) Architecture

How Y.js Works (The Magic)

Shared Data Structure (Y.Map)

Excalidraw elements are stored in a shared Y.Map:

  • Key: Element ID (e.g., arrow_1702...)
  • Value: Excalidraw element object

Conflict Resolution (CRDTs)

When two users edit simultaneously, Y.js ensures eventual consistency:

Scenario Resolution
User A and B move same shape "Last Write Wins" - latest timestamp wins
User A goes offline, adds shapes Shapes merge when reconnected
User A deletes, User B modifies Deletion typically wins

Why Backend Doesn't Care About Excalidraw

The backend is data-agnostic. It only relays Y.js binary updates:

Client A → Yjs Update (binary) → Server → broadcast → Client B

It doesn't parse or validate the data - works with any Y.js content.

Installation

Prerequisites

  • Node.js (v18+)
  • npm

Setup

  1. Install Dependencies

    npm install
  2. Run Backend (Terminal 1)

    cd apps/backend
    npm run dev

    (Runs on ws://localhost:1234)

  3. Run Frontend (Terminal 2)

    cd apps/frontend
    npm run dev

    (Runs on http://localhost:3000)

Project Structure

.
├── apps
│   ├── backend          # Raw Y.js WebSocket Server
│   │   └── raw-server.ts
│   └── frontend         # Next.js App
│       └── components
│           └── ExcalidrawCanvas.tsx
├── package.json         # Monorepo configuration

Deployment

Backend → Railway

cd apps/backend
railway init
railway up

Frontend → Vercel

  1. Push to GitHub
  2. Import project at vercel.com
  3. Set root directory: apps/frontend
  4. Add environment variable:
    NEXT_PUBLIC_WS_URL=wss://your-backend.railway.app
    

Environment Variables

Variable Location Description
PORT Backend Railway injects automatically
NEXT_PUBLIC_WS_URL Frontend WebSocket URL (wss:// for production)

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages