Clean Shopper — a process case study
Clean Shopper is a research assistant for ingredient‑aware shoppers. It's also the vehicle I used to learn how to design and build well alongside an AI collaborator — across five phases, from a written workflow through a shipped feature.
Phase one
I didn't set out to build a shopping app. I set out to learn how to design and build well with an AI collaborator — and I wanted a real product behind that exercise, not a toy example.
Clean Shopper became the vehicle: a single-user research tool for people who read ingredient labels before they buy. Search a home or personal-care product, get a plain-language clean/not-clean read grounded in ingredient safety data, save what passes to a personal library, and build a shopping list from it.
The constraint mattered as much as the feature list. No accounts, no multi-user complexity — small enough scope that the actual subject of the exercise stayed visible: how do you structure a working relationship with Claude Code so the output holds up, phase over phase, instead of drifting?
Phase two
Before writing a single component, I wrote down how I wanted to work. CLAUDE.md became the standing contract: tech stack, file-naming conventions, state rules, and a short list of things not to touch without asking.
The instructions that mattered most weren't about code style — they were about sequencing. Check the component spec before building anything new. Ask before creating a new file. Treat the build plan as a queue, not a suggestion.
Claude Skills turned recurring judgment calls into repeatable procedure — one that checks any component change against the design system before it's committed, another that writes and runs the browser tests for a feature's main flow and edge cases against a fixed checklist. The skills didn't replace judgment; they made sure the same judgment got applied every time, not just when I remembered to ask for it.
Phase three
Design decisions came before feature decisions. A design-system spec fixed the palette, type scale, spacing, radius and shadow values as the single source of truth — sage green for "clean," a warm terracotta reserved as a decorative accent only, never a text color, Poppins across a six-step type scale.
Those values then had to exist somewhere Claude Code could actually reach for at build time — declared as Tailwind theme tokens, so a component could use bg-primary and text-h3 instead of a hex value or an arbitrary pixel size. A hardcoded color became something an audit could catch and name, not an intuition to argue about.
A component specification followed the same logic: before building any UI element, check whether an existing component already covers the use case.
Phase four
Every feature got scoped before it got built. The product-comparison feature has a written spec that splits it in two: a read-only, side-by-side facts view that's buildable now, and a preference-weighted recommendation layer that stays blocked until the assessment engine and saved preferences exist. Writing that boundary down kept "compare products" from quietly turning into "recommend products" halfway through a session.
Supabase went in underneath as the persistence layer for saved products, categories, and the eventual preference data the second half of the comparison feature will need.
The AI chat feature got the same scoping discipline. It answers one question well — "is this safe?" — instead of becoming an open-ended assistant, and it's pinned to a smaller, faster model than the one used for product analysis, chosen deliberately for the lower cost and latency a short Q&A reply needs.
The product grid itself was designed for where the app actually gets used: standing in an aisle, not at a desk.
Phase five
Before anything reached main, it had to survive its own checklist. Four baseline rules apply to every feature regardless of what it does: name and score visible, saves persist on reload, every list has a real empty state, all styling resolves to design tokens. A separate testing pass writes and runs the actual browser tests for a feature's main flow and its edge cases against that same baseline.
A design audit runs on anything touching a component or the app shell before it's committed — checking hardcoded colors, off-scale type, and drift from the rules about how the app talks about certainty and risk. It caught small things: a badge and score sitting a few pixels off the title's baseline on the product detail view, invisible until you looked for it, then obvious.
Catching it there — before deploy, against a written standard — made it a design step, not a bug report.
Storybook deploys automatically on every push to main, so the component library stays a live reference instead of a set of screenshots that go stale the week after they're taken. The app itself follows the same path: build, audit, test, ship.
Working this way for five phases changed what I think Claude Code is for. Used as a tool, it's a very fast typist — you still hold every decision.
Used as a collaborator, it holds the standards you wrote down and applies them even when you're tired or moving fast — not doing the thinking for you, but making sure your own decisions actually stick.