I built a card component I was genuinely proud of. Clean variants, sensible props, handled every case I could think of. Then someone on another team used it for something I hadn’t thought of, and it broke in a way that taught me more about component design than the six months I’d spent building it.
What ‘working’ actually meant
The component worked for every use case I had personally tested — which, it turned out, was a narrower set than I believed, because I’d unconsciously designed the test cases around how I already intended to use it. It’s hard to notice the gap between “handles every case I thought of” and “handles every case that will occur” until someone else supplies a case you didn’t think of, on a deadline, without asking you first.
The break itself was almost boring: someone nested the card inside another card, for a comparison view I hadn’t imagined, and every assumption about available width silently stopped being true. Nothing crashed. It just looked wrong, in a way that took two days to trace back to a component three layers removed from the actual bug report.
The real test isn’t your test suite
I’d written what I thought was reasonable coverage — different content lengths, empty states, a loading state, dark mode. What I hadn’t written, because I hadn’t imagined it, was any test for the component existing somewhere I hadn’t designed it to exist. That’s structurally impossible to test for in advance. You can’t enumerate the ways people you’ve never met will misuse something built for people you have met.
This is the actual argument for shipping components before they feel finished, which sounds backwards. A component nobody but its author has touched yet is unreusable by definition — not because it’s badly built, but because “reusable” is a claim about how it behaves under conditions its author didn’t anticipate, and there’s no way to generate those conditions alone.
What changed after that
I stopped treating a new component’s first release as the finished version and started treating it as the first draft of a test suite I couldn’t write myself. The real spec gets written by whoever uses it in a context I didn’t imagine, and the bug reports that follow aren’t failures of the original design — they’re the design process finally getting the input it needed.
Practically, this means I ship components looser and earlier than I used to, with more visible seams, and I pay closer attention to the first three teams who adopt something new than to my own review of it. Their misuse is more informative than my testing, every time, because it’s the only source of the cases I structurally couldn’t have thought of.
Rhys O’Sullivan is a product designer at Fieldstone, previously Loop. This is one in an occasional series of notes on research, systems, and the process of making things.
