Drawgether

Case Study

Realtime · Canvas · Social

Drawgether

A social media platform built around collaborative drawing. Users join rooms, receive an AI-generated topic, draw together on a shared canvas in real time, and publish their finished piece to a community feed.

RoleSolo Developer
StackNext.js · Supabase · OpenAI
AuthCustom-built + TOTP
DeployVercel
Problem

Drawing is more fun
together

Solo drawing tools are everywhere. But collaborative drawing, with real people, on a shared canvas, with a creative constraint, is a fundamentally different experience that very few platforms get right.

Most multiplayer canvas tools are either too complex (Figma-style whiteboards) or too shallow (one-off doodle apps with no social layer). There's a gap between the two.

Drawgether fills that gap: a game-like drawing session that ends with a real artifact, published to a profile and a community feed. Part drawing game, part social network.

Collaborative drawing requires low-latency sync without complex infrastructure overhead

Shared canvas state needs to stay consistent across reconnects and undo actions

A social layer requires proper auth, profiles, and a scalable feed architecture

AI topic generation needs to feel integrated, not bolted on

Goals

Built to be production-grade

01

Ship a full multiplayer canvas with real-time sync and collaborative undo

02

Build a complete custom auth system without relying on third-party providers

03

Integrate AI topic generation as a first-class part of the game loop

04

Implement a social layer: profiles, a community feed, and auto-published drawings

Tech Decisions

Every choice deliberate

Supabase Realtime's broadcasting model is a natural fit for drawing rooms, each room becomes a channel, and stroke events are broadcast to all participants. Connection management, reconnection, and channel cleanup are handled by the library.

Rolling raw WebSockets would have required a separate backend process for connection state. Supabase Realtime kept the stack Next.js-only while still delivering sub-100ms broadcast latency.

The channel model mapped cleanly onto rooms without managing WebSocket infrastructure.

Challenges

Problems worth solving

Undo in a solo drawing app is trivial, maintain a local history stack and pop it. In a multiplayer canvas, undo is a shared operation: when one user undoes a stroke, all clients need to reflect the same state.

The fix was broadcasting a start_drawing event the moment a user begins a stroke, which triggers all connected clients to simultaneously push a history snapshot. This keeps the history stacks in sync across clients, so undo operations are deterministic regardless of who triggers them.

canvas-sync.ts
01
02// sender
03pushHistory();
04channelRef.current?.send({ type: 'broadcast', event: 'start_drawing' })
05
06// receiver
07.on('broadcast', { event: 'start_drawing' }, () => {
08 pushHistory();
09})

Undo needed to be deterministic for all participants, not just the user who triggered it.

Retrospective

What I'd do differently

01 / Architecture

Design the state machine first

The room state machine (WAITING → STARTING → ACTIVE → FINISHED) evolved organically, which caused rework. Defining all states, transitions, and edge cases upfront would have avoided several bugs during the timer and undo sync work.

02 / Auth

Start with custom auth

I spent time evaluating NextAuth before deciding to build from scratch. For a project with custom session requirements, the decision to go custom was always correct. I just reached it later than I should have.

03 / Testing

Test realtime flows with multiple clients early

Several bugs, including the undo desync and the timer offset, only appeared when two real clients were connected simultaneously. A simple two-client test harness from the start would have caught these earlier.

Results

Shipped

Multiplayer canvas with real-time stroke sync and collaborative undo via Supabase Realtime

Room state machine with server-authoritative timer and AI-generated topic reveal

Complete custom auth: registration, email verification, TOTP, forgot password, role-based permissions

Social layer: profile pages, community feed with cursor-based infinite scroll, auto-published drawings