Side project · Product design + build

Roomy

A realtime whiteboard that sorts itself.

Tidy turns a wall of sticky notes into labelled themes in one click, and you preview the result before anything changes for your team.

A six-day experiment: how far can one designer take an idea in a week, with Claude writing the code? I designed it from a brief, without research sessions with facilitators, and the case study says so where that matters.

Role
Product designer: framing, design system, every screen and state, motion, accessibility. Built alongside an AI engineer (Claude).
Timeline
Six days · 31 Oct – 5 Nov 2026
Tools
Figma (variables, components, prototypes), Dev Mode, Claude
Live
roomy-six.vercel.app

Try Roomy ↗

Accepted: labelled themes, with shapes left where they were

Part 1 · Design

Designing a board that sorts itself

I designed Roomy end to end in Figma, from the design system to every screen and state, and it shipped as a working product on 5 Nov 2026.

01 · The problem

Whiteboards are great until the meeting ends

Filling a wall with ideas is easy; the useful part, finding the themes and writing down what was decided, still happens by hand, usually by one person after everyone has left.

I framed the product around four moments where existing boards let people down. They became the landing page's “Sound familiar?” section.

MomentWhat goes wrongRoomy's answer
After the workshopOne person stays behind for an hour dragging notes into groupsTidy groups and labels the wall in one click
When the team joinsCursors stutter, notes jump back, “just refresh”Smooth live cursors, follow mode, a fast canvas
When the wifi dropsEdits are lost on a train or at a client siteKeeps working offline and merges on reconnect
When someone presses ⌘ZA teammate's work vanishes, and trust goes with itUndo only ever takes back your own changes
A Roomy board covered in unsorted sticky notes
The wall nobody wants to sort.

The brief kept scope tight: one AI feature done well, two roles (owner and editor), and no video, templates marketplace or extra permission levels.

02 · Design principles

The rules I gave myself.

  • Nothing changes without consent. AI previews, never acts. Tidy, transcript import and photo to board show their result first, and one undo reverses any of them.
  • AI is always recognisable. One colour (orchid) and one mark (a four-pointed sparkle) belong to AI and nothing else.
  • The room comes first. Presence, the shared timer and “bring everyone to me” are designed for the facilitator and the whole room.
  • Every state is a screen. Loading, empty, offline, reconnecting, error and no-access are designed as carefully as the happy path, in light and dark.

03 · Designing Tidy

Designing Tidy so it asks first

Nobody wants to come back to a board that rearranged itself while they were away. So every decision about Tidy protects the person's sense of control.

Preview before change

Pressing Tidy shows a proposal first. Notes move into dashed frames with suggested labels, and a bar says “Preview only — nothing is saved until you accept”, with Revert and Accept. Focus lands on Accept, so keyboard users can decide straight away. After accepting, the bar offers Undo, and one undo reverses the whole thing.

Tidy running: notes flying towards their themes
Notes on their way to a theme
Tidy's preview: dashed theme frames and a bar with Revert and Accept
The preview: nothing saved until you accept
  • The preview is private. Only the person who ran Tidy sees it, so collaborators never watch a half-decided layout jump around.
  • Edits during the preview. If someone changes the board mid-preview, the bar asks “Re-run Tidy?” instead of silently applying a stale plan.
  • Clear scope. Tidy works on the selection, or on every sticky note when nothing is selected. Shapes and drawings never move.
  • Honest limits. It needs at least 6 notes. Below that the button is disabled, and its tooltip says why and how far you are: “Add at least 6 sticky notes (3 so far)”.

A motion storyboard

The motion explains what happened, so it was storyboarded in Figma before any code.

TimeWhat happens
0–120 msNotes lift to 104%, so you see they're about to move.
120–700 msNotes fly to their theme on a spring (stiffness 260, damping 26), staggered 20 ms by distance from the centre.
700–900 msNotes settle; labels slide up 4px and fade in.
On acceptDashed borders turn solid in 150 ms.
Reduced motionThe whole sequence becomes a 200 ms crossfade.

Trust

AI work is marked consistently. Orchid and the sparkle appear on Tidy, Listen, summaries and photo to board, and nowhere else. Labels are editable like any other text, because the AI's naming is only a starting point.

Accepted: labelled themes, with shapes left where they were
Accepted: labelled themes. Shapes stay where they were.

04 · Designing for many people

Knowing who is doing what, and never losing someone's work

A shared board fails socially before it fails technically, so the multiplayer design is about knowing who is doing what, and never losing someone's work.

Sam's cursor and selection on Ada's screen, on a board built from a meeting transcript
Live together: Sam's cursor and selection on Ada's screen, on a board built from a meeting transcript.
  • Presence. Each person gets one of 8 presence colours for their cursor, name tag, selection outline and avatar. The colours are the same in light and dark, so a person keeps their colour when you switch themes.
  • Follow. Every avatar is a button: choose it to follow that person's view. A banner says “Following Sam · Esc to stop”, and any pan or zoom of your own ends it.
  • Bring everyone to me. Facilitators pull the whole room to their view in one click, instead of saying “scroll left, no, further”.
  • Undo that respects teammates. ⌘Z only takes back your own changes. One person's undo can never erase another person's note.
  • Offline and reconnecting. The status always says what's true: “Reconnecting…” while it retries, and “Offline · edits saved on this device” when it can't. You keep working, and edits merge when you're back.
  • Listening is visible. When someone uses Listen, everyone sees “Ada is listening — talking points will appear as notes”. Nobody is recorded without knowing.

05 · Meetings to board, and the facilitation kit

Getting ideas in, running the session, getting decisions out

Most sticky notes start as talk, so the second half of the product covers the meeting itself: getting ideas onto the board, running the session, and getting decisions out.

Getting ideas in

  • Listen turns talking points into sticky notes as people speak. Before it starts, a sheet explains that it uses the microphone and that everyone on the board will see you're listening.
  • Import a transcript by pasting text or uploading a .vtt, .srt or .txt file. The dialog names the tools it works with (Zoom, Google Meet, Teams, Otter or plain text), so nobody has to guess.
  • Photo to board reads a photo of a real sticky-note wall. You review every note before it's added: hard-to-read notes are outlined, and you choose whether to keep the photo's colours.

Running the session

The facilitation panel holds four tools, each one row with a short promise.

ToolPromise on the row
Timer“everyone sees it”
Dot voting“3 votes each”
Hide notes“Until you reveal”
Bring everyone to me“Moves all views to yours”

During voting, a banner counts down your votes and teaches the interaction in one line: “click a note to vote, again to take it back”. When voting ends, it reports the total and offers Sort by votes.

Getting decisions out

The summary panel splits into a summary, decisions and action items, all editable before you copy. Copy for Slack and Copy for Notion format the text for where it's going next.

Voting ended: a banner reports the votes and offers Sort by votes
Voting ended, with Sort by votes
The summary panel with a summary, decisions and action items, and Copy for Slack or Notion
The summary, ready for Slack or Notion

06 · Visual system

The interface is quiet so the board can be loud

Sticky notes carry the colour, and the interface around them stays neutral.

Tokens first

The system lives in Figma variables, with CSS code syntax so names match the code exactly.

  • Three collections: Primitives, Color (Light and Dark modes) and Space.
  • 15 text styles and 3 elevation shadows.
  • Semantic names everywhere. Components use bg-surface-raised or text-secondary, never a raw colour. The code has the same rule: no hex values and no one-off Tailwind values in the interface.

A rebrand that took minutes

The first direction used warm sand neutrals, a clay brand colour and violet for AI. Partway through, I picked a new brand colour: indigo #2930FF (indigo/500), with indigo/400 #4F55FF in dark mode. Neutrals moved to cool slate and the AI colour to orchid.

Because components only referenced semantic tokens, every screen updated at once, in Figma and in code. That was the strongest argument for tokens on this project.

The same accepted board in dark mode
The same accepted board in dark mode: same tokens, other mode.

Colour roles

  • Brand indigo: primary actions and your own selection. White text on it passes WCAG AA in both themes.
  • Orchid: AI only. If something is orchid, the machine did it.
  • Presence 1–8: people, identical in light and dark.
  • Ink focus ring. A brand-coloured ring disappeared on filled indigo buttons, so the focus ring uses ink instead.

Type

  • Geist for the interface.
  • Bricolage Grotesque for display moments: page titles, Tidy's theme labels and the wordmark.
  • Geist Mono for keyboard shortcuts.

Icons and illustration

Compact UI (banners, toasts, the Tidy bar) uses Lucide icons at 20px. Full-screen states (empty, error, no access, welcome, 404) use spot illustrations instead. They're drawn only with tokens, so they switch with light and dark, and screen readers skip them.

07 · Every state designed

Every state has its own screen

Most of the Screens page in the Figma file is states rather than features: offline, reconnecting, empty, error, no access.

AreaStates designed
BoardLive, dark, following someone, offline, reconnecting, empty, loading, error
TidyWorking, preview, error (for example out of credit), needs more notes
HomeBoards grid, empty, loading, error
AccessSign in, check email, join via link, link no longer works, no access
ConfirmationsRename, delete board, remove person, per-user undo toast
OnboardingThree tips, each placed next to what it's about

A few decisions carried most of the weight:

  • Say what's true, then what to do. Error copy names the cause and a next step: “Export didn't work. Try again, or export a smaller selection.”
  • Removing someone is explained before it happens. The confirmation says they lose access right away, are disconnected if they're on the board now, and that their notes stay.
  • Offline keeps working. You keep editing. Only Tidy pauses, because its AI call runs on the server.
  • Calm loading. Skeletons pulse softly, and not at all with reduced motion.
  • Spec notes for behaviour. Yellow “Spec” notes beside the frames describe what a still frame can't show: timings, focus order, what collaborators see.

08 · Accessibility and keyboard

Every canvas interaction has a keyboard path

A canvas is invisible to screen readers and keyboards by default, so every canvas interaction was designed with a keyboard path from the start, not retrofitted.

  • Objects are reachable. Arrow keys move between and nudge objects, and key hints appear above the toolbar while you do it.
  • Everything has a key. Alt+arrows resize by 8, Alt+[ and Alt+] rotate by 15°, Shift+F10 opens the object menu, and Enter on a toolbar tool places an object in the middle of the view.
  • Screen readers hear changes. What's selected, a new size or angle, and the sync status are announced.
  • Real text fields. Typing in a note uses a real text field laid exactly over the canvas, so spellcheck, IME input and screen readers work as they do anywhere.
  • The toolbar is one tab stop (roving tabindex), and menus return focus when they close. The shortcuts list (press ?) shows only shortcuts that really work.
  • Hidden notes stay hidden. During “hide until reveal”, screen readers don't hear other people's notes either.

An automated check (axe) passes on the board, Share and shortcuts, in light and dark. It caught two real issues: missing landmarks, and the faint grey “Skip tips” text (3.8:1), which now uses the tip's full text colour.

09 · Phone

The board stays as big as possible

On a phone, everything else moves out of the way. The design assumes viewing, panning, sticky notes, pen and undo on phones, with the other tools desktop-first.

  • A compact top bar under 640px keeps back, title, people and the menu. Tidy, Share, Listen and Facilitate move into the menu.
  • Pinch replaces the zoom control, and the toolbar scrolls sideways, keeping every tool rather than hiding some behind “more”.
  • Dialogs become bottom sheets, and side panels go full width.
  • Banners sit under the top bar, and menus skip items you can't see, so the keyboard never lands on a phone-only item on a desktop.

The Figma phone screens cover sign in, boards, the empty board, the board itself, Tidy preview as a bottom sheet, the share sheet, the landing page and 404.

The same board on a phone
The same board on a phone.
Share as a bottom sheet on a phone
Share as a bottom sheet.

10 · From Figma to shipped

Where the build changed the design, it was written down

The build followed the Figma file closely, and where it didn't, the change was written down as an assumption in the code and in the decision log.

In FigmaIn the buildWhy
Free and Pro plans, Pro badges, upgrade dialogEverything free, no badgesProduct decision: free for now
Transcript import previews, then you acceptNotes are added, with UndoSame result with fewer steps
Microphone picker in ListenBrowser's default microphoneBrowser speech recognition can't choose a microphone
Version history rowsTime and object count, not who editedAssumption, still to confirm
Theme framesAt least as wide as their labelFix made during the build
No close button on the Tidy error barDismiss button addedOtherwise the bar can't be cleared
Grey “Skip tips” textFull tip text colourGrey measured 3.8:1, under the contrast target
Listen in every browserFirefox users are pointed to transcript importFirefox can't do speech-to-text

The Tidy bar also changed shape slightly: its preview offers Revert and Accept, and Re-run appears only when someone edits during the preview.

11 · Reflection and what's next

Designing the system before the screens paid for itself

Semantic tokens made a full rebrand a same-day change, and designing states as screens meant the build had answers ready instead of guesses.

What worked

  • Preview before change gave AI features a single, repeatable pattern: Tidy, transcripts, summaries and photo to board all let you check before anything is kept.
  • Spec notes carried behaviour, timing and focus order that frames alone can't show, which kept the build close to the design.
  • One colour for AI made machine-made changes recognisable everywhere without extra labels.

What I'd do differently

  • Check presence colours for contrast with initials on top before locking the palette; it's the one open accessibility issue.
  • Test with real facilitators earlier. Every flow here came from the brief. I haven't run a research session yet.

What's next

  • Re-take the screenshots with the AI key on, so they show Claude's own theme labels.
  • Resolve the presence-colour contrast.
  • Usability sessions with facilitators running a real workshop.
  • A meeting bot that joins calls, planned for after v1.
Home: your boards
Share and export
Facilitate: timer running
Facilitate: notes hidden until reveal
Listen: turning it on
Photo to board: review before adding
Settings
Onboarding, tip 1 of 3
Welcome: set your name and cursor
Join a board from a link
Account menu
Home, empty
Delete board: confirm
Board couldn't open

Part 2 · Engineering

Built with Claude

I directed the build with Claude as the engineer: I set the brief, scope and rules, reviewed every change, and Claude wrote the code. These are the engineering decisions worth telling.

E1 · What I built

A collaborative canvas that sorts itself

  • A collaborative canvas: sticky notes, shapes, text, pen and eraser, connectors, grouping, alignment, layers, rotation and resizing.
  • Live collaboration: several people on one board, live cursors and selections, follow mode, and offline editing that merges when you reconnect.
  • Per-user undo, which only takes back your own changes, never a teammate's.
  • Tidy: themes found by AI (or by a built-in method with no AI key), animated into labelled frames, and nothing saved until you accept.
  • Share and export (PNG, SVG), keyboard access throughout, light and dark themes, and reduced-motion support.

Stack: Next.js and React with TypeScript, Tailwind with design tokens, Yjs for sync, Cloudflare Durable Objects and D1, and Claude (claude-haiku-5-5) for Tidy.

Two browsers, one board: Ada and Bo add notes, Bo moves one, Ada runs Tidy, and Bo sees the themes arrive when she accepts.

E2 · Engineering decisions worth telling

Six decisions that shaped the build

  1. 01

    Our own canvas renderer, outside React

    The board is drawn on an HTML canvas by a plain TypeScript engine. React only renders the UI around it. Panning and dragging fire dozens of events a second, so the engine redraws at most once per frame, and only when something changed.

    Result: with 500 objects, drawing takes about 0.5 ms of a 16.7 ms frame at the median (1.0 ms at p95), with no dropped frames. 2,000 objects still take about 2 ms.

  2. 02

    One way to change the board

    Every tool describes its edit as a list of changes and hands it to one function. That made the later steps cheap:

    • Sync needed one place to write to the shared document.
    • Undo records exactly those transactions.
    • Board rules (no connector to a deleted note, no group of one) are checked after every change, from anyone.
  3. 03

    A CRDT for sync, with presence kept apart

    The board lives in a Yjs document, a CRDT: a data structure that merges edits made at the same time, or offline, without a central referee. Each board has its own Cloudflare Durable Object that relays and saves it, and every browser keeps a copy in IndexedDB so it opens instantly, even offline.

    Cursors, selections and follow travel on a separate live channel, so they're never saved and never clutter the history.

  4. 04

    Undo that respects teammates

    A shared undo stack would let one person's ⌘Z wipe out someone else's work, so undo only tracks edits made in this browser.

    One bug was worth fixing properly: a fast “move, then Delete” merged into one undo step. Now every pointer press, key press and typing session starts its own step.

  5. 05

    Tidy: AI that previews before it acts

    • Server only. The API key never reaches the browser.
    • Structured output. The model answers in a fixed JSON shape, and we still check it: unknown IDs are dropped, missed notes go into “Other”.
    • A fallback that costs nothing. With no AI key, a built-in method groups notes by shared words.
    • Preview is local, and Accept is one transaction, so one undo takes it all back.
    • Limits: request caps, daily limits, a spend limit, and a clear message for every failure. The board is never left half-changed.
  6. 06

    Accessibility as a feature

    • Every canvas object can be reached and moved with the keyboard.
    • Screen readers hear what's selected.
    • Dialogs trap focus and return it.
    • The shortcuts list only shows shortcuts that really work.
    • axe passes on the board and dialogs in both themes, with one known gap: presence-colour contrast.

E3 · Performance, before and after

Render time looked fine. The board didn't.

Moment500 objects, render median / p95Dropped frames
Step 1 baseline0.4 / 0.7 ms0 / 300
Pen strokes, first try (one big outline path)0.6 / 1.4 ms24 / 300
Pen strokes, outlines drawn one by one0.7 / 2.6 ms4 / 300
After sync, undo, Tidy and polish0.5 / 1.0 ms0 / 300

The lesson from the pen work: our code got faster while the board got jankier, because the browser was slow to paint one huge path. Render time alone would have hidden it, so we track dropped frames too.

Measured in headless Chromium in a cloud container, not on a mid-range laptop.

E4 · Where it stands

Everything in the v1 brief is built

Canvas, live sync, offline, per-user undo, Tidy, accounts and sharing, Listen and transcript import, summaries, the facilitation kit, photo to board, version history, the landing page and phone layouts. Roomy is free for now, so billing waits.

Still to switch on: the AI key (Tidy, transcripts and summaries use built-in methods until then; photo to board needs it), plus Google and email sign-in. Planned after v1: a meeting bot that joins calls.

Next case studySnuget · one honest naira picture

Working on something people find hard to use?

Let's talkjonmidas27@gmail.com

Replies within a day.