Building an MTG Collection App, Part 3: The Redesign
By the end of part 2, my Magic collection app could import cards, build decks, analyze decks, value sealed product, track a wish list, and argue with me about Oko. It also looked like it had been built one weekend at a time, because it had.
No single screen was bad. The problem was that every screen had been designed alone, at a different hour of the night, by someone (me) who mostly wanted the feature working before bed.
The audit
When I finally looked at the whole app at once, I found:
- Hard-coded colors everywhere. Red, amber, green, sky, and violet utility classes scattered across dozens of files, plus black text on accent colors that only worked because the whole app was dark. Adding a light theme would have meant searching through every file by hand.
- Six native
confirm()dialogs. Six times the app asked “Are you sure?” in a gray browser popup that looks like a 2003 phishing attempt. - Buttons that were similar but not quite the same. At least four styles of “primary button,” all close enough to look intentional and different enough to bother me.
- Tap targets built for a mouse. I use this app on my phone at the game store. Tiny row actions plus big thumbs equals deleting the wrong deck.
Infrastructure people call this config drift. Designers call it a lack of a design system. Either way, the fix is the same: stop making one-off decisions and set the decisions in one place.
Foundations first
The redesign started with the boring part on purpose:
- Semantic color tokens. “Danger” and “surface” instead of “red-500” and “zinc-900.” Adding a light theme was then mostly a matter of defining the tokens a second time. The theme choice lives in a cookie, so the server renders the right theme on the first paint. No flash of the wrong theme, no flashbang at 11pm.
- Shared components. Button, Chip, PageHeader, a segmented control, bottom sheets for mobile, menus, and a toast system. They get built once and used everywhere, so the next feature looks like it belongs to the same app.
- Undo instead of “are you sure?” Deleting a deck, a wish-list card, or a sealed product now hides the row right away and offers Undo before the delete request is even sent. This is a better pattern than a confirmation popup, because nobody reads confirmation popups. I’ve been clicking OK on them since dial-up.
- Accessibility basics. Visible focus rings, proper pressed states on the color toggles, and bigger tap targets on row actions.
And, in a moment of real catharsis, I removed an error message that still mentioned Supabase. A database I’d migrated off on day one, back in part 1, had been haunting the UI ever since.
What I’d tell myself in August
- Design tokens on day one. It costs five minutes up front and saves a weekend of find-and-replace later. Same deal as the database migration.
- Validate the AI, don’t prompt-engineer your way to trust. The deck builder works because code checks every card, not because I found the perfect prompt.
- Hobby projects are the best lab. Every lesson in this series (OAuth scopes, race conditions, token budgets, config drift) is one I deal with at work. It’s just a lot more fun when the stakes are a Commander deck.
The redesign isn’t finished. The foundations are in, and the screens are moving over to them one at a time. Some things never change. I’ll get to the rest one weekend at a time.
Meanwhile, I still don’t know where that second copy of the card is. But the app can tell me it’s worth about forty cents, so I’ve stopped looking.