Ten seconds is a long time on stage.
I perform live music alongside designing. A show is forty to fifty songs, and everything I needed to know about each one lived somewhere else. So I designed Playwell, and then built it, which is how I found out how much I had got wrong.
Playwell.
CONTEXT
Seven places to look, and the song has already started
A typical show runs forty to fifty songs, and knowing the song is only part of the job. I might need the lyrics, the key, the tempo, the set order, a transition into another song, or a note somebody changed during rehearsal.
The problem was never that this information didn't exist. It was that none of it lived together. My setlist was somewhere. Lyrics somewhere else. Someone sends a change through WhatsApp. Another song is saved in Notes. Spotify tells me what the track is, but not what our band is doing with it. The key is in my head, usually.
Seven places to look, for one song, somewhere between four and eight seconds each time. That sounds trivial written down. It is not trivial with a room watching and the previous song ending.
- ROLE
- Founder, product designer, researcher, builder
- SCOPE
- Strategy, research, UX/UI, prototyping, testing, development
- PLATFORM
- iPad-first PWA, responsive web
- STATUS
- Active development · native launch planned
The problem was never access to music. It was access to context.
There are already excellent tools for listening to music, reading lyrics, sharing files and taking notes. My job during a performance was never find this song. It was tell me what I need to know about this song, right now, without pulling me out of the performance.
That single reframe changed what I was designing. Not a better music app - a workspace with a very specific tolerance for latency.
Spotify, Has the track. Doesn't know what our band does with it.
THE CHALLENGE
Three questions I kept protecting
How might I make everything a musician needs during a show reachable in seconds?THE QUESTION UNDERNEATH ALL OF IT
That produced three more, and they stayed with me through every version, more useful than a feature list, because a list tells you what to build and these told me what to protect when something had to give.
- Find
- How quickly can I find the right song among thousands, when I only half-remember what I'm looking for?
- Perform
- How little interaction can the interface demand once I'm on stage and my hands are busy?
- Organize
- Can the product understand that songs belong to artists, events and mashups, and not just to a database?
RESEARCH
I was already the user, and here's what that is and isn't
I had one advantage most side projects don't: I could use the product in the exact place the problem happened. So instead of running a study, I documented friction where it occurred, across the four moments that make up a performing week - before a show, rehearsal, performance, after, and kept evaluating during real use rather than in a session.
The loop - perform, notice, change, use again - has run continuously through Playwell's development. Every version came out of one turn of it.
Four things I was wrong about in front of an audience
Speed matters more than discovery. Browsing casually, exploring is pleasant. During a performance it's a liability, the shortest path to a song had to win every time it competed with a more interesting one. So: persistent search, direct filtering, navigation kept deliberately shallow.
A song is more than a title. The useful object for a performer is song plus artist plus key plus tempo plus lyrics plus event plus notes plus relationships - which meant the data model was the design.
Setlists aren't static. Songs get moved, dropped, re-keyed. Two become a mashup ninety seconds before you play them.
Stage interaction is not desk interaction. Attention divided, lighting unreliable, device several feet away, hands occupied. The interface had to become less demanding exactly as the environment became more demanding, large targets, high-contrast dark surfaces, persistent context, fewer steps.
Perform, Find the next song, in seconds, with hands busy.
STRUCTURE
2,800 songs forced an information system, not a library
Scrolling is fine at fifty songs. At two thousand it's a failure state. So I introduced multiple paths into the same underlying library - search, all songs, artists, favorites, events, mashups, and the decision that keeps it coherent was to never duplicate information across them.
Favorites isn't a folder you copy into. Events don't own their songs. Artists aren't a second database. They're all views onto one music system. Change a song's key in any of them and it changes everywhere, because there is only ever one song.
Underneath it sit three moments rather than a set of screens: prepare, find, perform. Every feature since has had to justify itself against one of them.
Search, The primary, permanently available way in.
My first instinct was to put everything on screen
Early versions prioritised completeness, more controls, more metadata, more visible at once, because I could see the value of all of it. That works beautifully at a desk. It stopped being convincing the first time I had to use it quickly, in low light, with a song already playing.
So I separated information that exists from information that needs to be visible now. Search moved from a filter tucked into a toolbar to the primary, permanently available way in. Key, tempo and time signature had been visible at all times in V1; they matter maybe one time in ten, so they collapsed behind a More filters control with an active-count badge. Edit controls, which had sat beside performance controls, moved away entirely, on stage that's a hazard, not a convenience.
And one small fix I think about more than its size warrants: an 8px gap increase had pushed Sort and Clear onto a second row, costing about 44px of song list. Horizontal space is cheap on an iPad. Vertical isn't.
KEY DECISION
Designing lyrics for a musician, not a reader
A lyrics screen looks trivial until you consider where it's used. The iPad is several feet away. You glance at it. The song continues whether the interface is ready or not.
So the performance view does less, larger. Title and key scaled up about 1.6×, lyrics 1.2× again on top, a near-black reading surface, and auto-scroll on a fixed panel with a real slider rather than the fiddly rotating dial it replaced. Key, tempo and what's next stay visible without a tap.
The detail I'm most pleased with is in light mode: nothing in the app is pure white any more. The lyrics pane is the brightest surface in the product and the one read from on a dim stage. It was a flashlight in the eyes, and nobody asks you to fix that. You just notice it at the second gig.
KEY DECISION
A setlist shouldn't behave like a document
My original model was embarrassingly simple: an event is a list of songs. Real performances broke that inside one show.
Setlists change constantly, and a model where the list is a saved artifact makes every change friction - which means during a show you simply don't make it. If the cost of a change is higher than the cost of living with the error, people live with the error. So events became an operational layer: create, add, arrange, adjust, perform, reuse.
Then events grew a second view. The accordion is for performing; the run sheet is for organising. The two stay in agreement, reorder in one and the other follows, and a key typed into the sheet shows on that song's card for that event only, never touching the master database.
THE MODEL
When an edge case became the model
Mashups exposed the flaw in the simple song-library model, and then the data settled the argument. 53 of the 99 records in the bundled library are multi-section. More than half of what I perform isn't a song; it's a sequence.
Treating each part as independent meant the software described something we weren't doing: the setlist said three songs, the audience heard one. So a mashup became a relationship between songs rather than a new record type.
Then the next problem arrived. The same song appears inside several mashups and as a standalone - fix a typo in one place and the other four are still wrong. The fix came straight out of my day job: a section can be linked to a standalone song as its source, exactly like a Figma component and its instances. One source of truth, many placements. The alternative was five copies of the same lyric quietly drifting apart, which is precisely what had been happening.
There's a smaller decision inside it I'd defend too. Songs arrive titled Song A x Song B, and the app offers to auto-split them, but naive matching destroys real titles, so only a whitespace-bounded x, X or × counts. Experience, Taxi and Max are never touched.
This is one of my favourite parts of the product, because it didn't come from brainstorming features. It came from the product failing to describe reality correctly.
THE PATTERN
Six assumptions I'd encoded without noticing
Looking back through the changelogs, the same shape repeats. I build something that models the world as I assume it works. Reality declines to cooperate. The product changes, not cosmetically, but at the level of what it thinks a thing is.
The bug that was really a definition
Cross-device sync shipped and did nothing. Edit a song on the desktop, look at the iPad, nothing. No error, no failed request, no offline warning. The websocket was connected and healthy the entire time.
One line was throwing every message away. It was there to solve a real problem, when you write a change, the server echoes it back, and processing your own echo causes loops so the handler skipped any change whose author was the signed-in user.
// js/cloud/sync-service.js, the realtime handler
if (row.updated_by && row.updated_by === owner) return;
// meant: "ignore the echo of my own writes"
// actually: "ignore my other device, forever"Which is correct, right up until one person uses two devices. Then both devices are the same user, the condition is true for every message, and the receiving device discards everything the sender just said. The fix: echo detection by content rather than identity, the server owning its own timestamps, a 45-second backstop poll for when venue wifi blocks the socket, and sync diagnostics built into the product.
Why this is in a design case study at all. The failure wasn't technical, the code did exactly what it said. The bug was a definition: I had written user where I meant device, and every consequence followed correctly from that one wrong noun. Same failure as the mashups, same as the setlist-as-document. The product kept describing a world slightly to the left of the real one, and building it myself is what made that visible.
// js/cloud/sync-service.js, the realtime handler
if (row.updated_by && row.updated_by === owner) return;SYSTEM
Rules before more screens
As Playwell grew, repeating interface decisions by hand started producing inconsistencies I then had to spend time noticing. So it got reusable patterns, song rows, navigation, filter controls, badges, states, inputs, modals, event cards, responsive behaviour.
The system stays deliberately compact, and that's a decision rather than a limitation. This isn't an enterprise design system like the one I built for NXT; it doesn't need to survive two brands and eight modules. It's a product-level system tuned to one application's vocabulary.
The part I'd defend hardest is the colour logic, because one rule in it does real work. Blue-violet leads everything, every button, active filter, focus ring and key badge. Gold is reserved for exactly one thing: the mashup separator. Which means a separator that isn't gold is instantly visible as one the parser didn't recognise. The colour is a diagnostic.
Alongside it: section badges cycle five colours as an organisational aid, kept separate from tempo colours so the two are never read as the same signal; actions are semantic rather than positional, so Find Lyrics is always blue wherever it sits; cards show no tempo colour until you explicitly choose one, because absence of signal beats a default that's probably wrong; and nothing is pure white.
BUILDING IT
I wanted to know what happened after the prototype
Instead of stopping at Figma, I built Playwell into a working product, deliberately with no framework and no bundler, so there was nothing between an idea and it being installed on my iPad that evening. That collapsed the distance between a design decision and its consequences to about three days: design in the afternoon, rehearse with it that week, find out what was wrong on stage.
A service worker caches the app shell and every write lands in IndexedDB before it goes near the network, so airplane mode on stage changes nothing. Supabase handles auth, Postgres, realtime and storage, with row-level security on every table and migrations shipping alongside the app so schema and code can't drift apart. The deploy check fails the build if a PWA file or migration is missing, and fails it if song data ever gets embedded back into the HTML. The deploy script actively refuses to let me repeat a bug I already made once.
The library started around 1,100 songs and grew past 2,800, and that growth surfaced most of the six assumptions. Building it became another form of UX testing. A design that only works at demo scale isn't finished; it's untested.
ITERATION
Playwell wasn't redesigned once
It changed every time reality disagreed with me, and each stage answered exactly one question.
- V1, can I keep my songs in one place?
- Nothing forced it. I was tired of screenshots.
- V2, can I retrieve anything quickly?
- Forced by the library passing a few hundred songs and scrolling breaking.
- V2.2, can I actually use this on stage?
- Forced by taking it to a real show and finding I couldn't.
- V2.6, can the product represent how musicians work?
- Forced by playing three songs as one continuous mashup while the setlist insisted there were three.
- V3.0, can my library survive one device?
- Forced by everything living in one browser's storage.
- V3.1, now, can this stop being only my tool?
- Forced by a bandmate asking whether they could see the setlist, and there being no answer.
That last one changed the hardest product question from how do I manage my music to how could a band manage a performance together, and those need different foundations. Two decisions I'd defend: no invite codes (you add someone by email, and the moment they sign in with it the band and its shared events simply appear), and a bandmate sees the setlist rather than the library, an event's songs are snapshotted into their own table with their own security rules, so they get lyrics and keys for that setlist and none of the other 2,900. A schema decision doing work a permission dialog can't.
VALIDATION
The prototype doesn't get the final vote. The performance does.
I don't have a usability percentage for Playwell and I'm not going to invent one. What I have is a product tested in the least forgiving environment I know, in front of people, in real time, where a failure isn't a task-completion metric, it's a gap in a song.
Five signals carry it: real performance use, rehearsal use, large-library testing at around three thousand songs rather than the twenty a demo would use, an automated suite of 89 browser checks that must pass with zero uncaught errors, and feedback from other musicians. The suite can't tell me whether a screen works on stage. The stage can't tell me whether I broke row-level security. I need both.
OUTCOME
The honest version of what exists today
Playwell has no adoption metrics, retention curve or usability score, because it doesn't yet have users beyond me and the musicians I play with. Publishing invented numbers would be easy and worth nothing.
- 2,800+
- Songs managed in the working product
- 1,100 → 2,800+
- Library growth that stress-tested the architecture
- 89
- Automated browser checks, zero uncaught errors required to pass
- PWA + cloud
- Installed on iPad, syncing across devices, working offline
More importantly than any of those: Playwell moved from an idea I had during performances into a product I actually use in them. That's the honest outcome at this stage, and it's the one I'd defend in a room.
What's in front of it is mostly invisible in the interface and unavoidable in the architecture, shared-with-me events, per-song band libraries, sync diagnostics hardening, then offline resilience under load, analytics and onboarding for someone who isn't me, and eventually native iOS and Android. No store badges until there's something in a store.
One workspace. Same songs.
Knowing when to stop designing for yourself
Playwell started because I understood the problem intimately. That gave me speed. It also gave me bias, and the two are difficult to separate.
I could tolerate interactions because I already knew how they worked. I could understand labels because I wrote them. I could navigate structures because I designed them. Every one of those is a blind spot wearing the costume of good design.
The six assumptions are the evidence. Each survived because I could work around it without noticing, and each only surfaced when something outside my head disagreed: a real library size, a real stage, a real second device, a real bandmate. The next phase needs the opposite of what got it here, less intuition, more external validation.
The old question was “does Playwell work for me?” The one that decides it is “can another musician pick it up and perform without me explaining it?”WHAT TURNS A PERSONAL TOOL INTO A PRODUCT
Built because I needed it.
Still changing because I use it.
Playwell · 2026 · iPad-first PWA, active development. Song titles in screenshots are placeholders; the structure and the library sizes are real.