Real-time multiplayer collaborative whiteboard with infinite canvas, presence, chat, reactions, and a laser pointer.
https://collabspace-mauve.vercel.app
Status: The production deploy currently shows a clean “Supabase not configured” shell. Full multiplayer collaboration requires a Supabase project; the free tier is limited to 2 active projects and those slots are already used by other portfolio apps.
Locally the project runs fully: Docker + local Supabase (npx supabase start) +npm run dev. Schema is idempotent — pastesupabase/migrations/0001_init.sqlinto any free Supabase project (or use the local stack) for a working realtime demo.
- Infinite canvas — pan (Shift-drag / middle-click), zoom (scroll), minimap
- Drawing tools — Pencil, Line, Rectangle, Circle, Text, Sticky note, Eraser, Select, Laser pointer
- Real-time multiplayer — live cursors with name labels via Supabase Presence
- Persistent elements & chat — Postgres Changes fan-out (no custom Socket server)
- Ephemeral signals — floating emoji reactions + laser pointer via Realtime Broadcast
- Undo / Redo with full history stack (
⌘Z/⌘⇧Z) - Dark / light theme with system preference + anti-flash
- Responsive — 5 breakpoints, mobile bottom-drawer sidebar, 44 px touch targets
- Accessible — focus-visible rings, ARIA tablist, prefers-reduced-motion, prefers-contrast
- Anonymous identity — random user stored in
localStorage(auth-ready later)
| Layer | Tech |
|---|---|
| Frontend | React 18 · Vite 5 · TypeScript · Framer Motion |
| Backend | Supabase (Postgres + Realtime Presence / Broadcast / Postgres Changes) |
| Deploy | Vercel (SPA rewrite via vercel.json) |
| Identity | Client-side random (localStorage) |
# 1. Install
npm install
# 2. Env
cp client/.env.example client/.env
# Add VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY
# 3. Schema (paste supabase/migrations/0001_init.sql into Supabase SQL Editor)
# Idempotent — safe to re-run
# 4. Dev server
npm run dev
# → http://localhost:5173Original v1 used Express + Socket.io + Prisma + SQLite.
v2 is fully client-side against Supabase — no custom backend process.
| Concern | v2 implementation |
|---|---|
| Boards / elements | boardSync.ts / canvasSync.ts → Supabase REST + Postgres Changes |
| Chat | chatSync.ts → Supabase insert + Postgres Changes |
| Cursors / presence | Supabase Realtime Presence |
| Reactions / laser | Realtime Broadcast (ephemeral) |
| Identity | identity.ts → localStorage |
See client/src/lib/realtime.ts for the single joinBoard() session that wires all four channels.
MIT License. See LICENSE for details.


