Skip to content
Roomful is in public beta — install with the @beta tag. Share feedback →

Recipe: Multiplayer Canvas

Audience: users.

Goal: build a live canvas where strokes are broadcast instantly and persisted for late joiners.

  • events: immediate stroke broadcast for low-latency rendering
  • state: persistent stroke history
  • cursors: collaborator pointer visibility
const room = createRoom(`canvas-${canvasId}`, {
presence: { name: user.name, color: user.color },
});
await room.connect();
const events = room.useEvents();
const state = room.useState({
initialValue: { strokes: [] as Stroke[] },
strategy: 'crdt',
});
events.on<Stroke>('stroke', (stroke) => {
drawStroke(stroke);
});
canvas.addEventListener('mouseup', () => {
const stroke = captureStroke();
events.emit('stroke', stroke);
state.patch({ strokes: [...state.get().strokes, stroke] });
});
  • Keep stroke payload compact.
  • Consider chunking for very long paths.
  • Use relay mode for larger live sessions.