I Built a Real-Time Collaborative Whiteboard in One Day — Here's How
Source: Dev.to
It started at midnight
I had 24 hours, a free Replit subscription, and an idea: what if I could build something like Miro—but actually understand every line of code in it?
The core problem I had to solve first
Multiplayer sync sounds simple until you actually build it. The hard part isn’t sending a canvas update—it’s figuring out what to send.
// client side
canvas.on('object:modified', (e) => {
socket.emit('canvas:update', {
roomId,
delta: e.target.toObject(['id', 'left', 'top', 'scaleX', 'scaleY'])
});
});
On the server, the room state is held in memory and rebroadcast to all other clients in the room. New joiners receive a canvas:init event with the full current state so they’re immediately in sync.
What CollabCanvas actually does
- Live multiplayer canvas with real‑time drawing sync.
- Color‑coded cursor presence for every connected user.
The technical stack
- Frontend: React + Vite
- Backend: Simple Node.js server (no database).
- Canvas state lives in server memory per room and is cleared after an hour of inactivity. This kept the scope tight for a one‑day build while still being fully functional.
What surprised me
Cursor sync was the feature I almost skipped—and it ended up being the most impressive thing in the demo. Seeing three colored cursors moving independently on the same canvas makes the multiplayer feel real in a way that just synced drawing doesn’t.
// client side cursor handling
canvas.on('mouse:move', ({ e }) => {
const { x, y } = canvas.getPointer(e);
socket.emit('cursor:move', { roomId, userId, x, y });
});
Lesson: polish the presence features. They’re what make multiplayer feel alive.
Try it
The live demo is deployed on Replit. Open it in two tabs, click the link in the first tab, then use the “Share” button to share the room ID with the second tab and start drawing—you’ll see exactly what I mean.
https://collab-canvas—dhruvaugust1.replit.app
Built in 24 hours for the Replit Buildathon. Feedback welcome.