Designing in States
Designing in code brings bugs you can't draw your way out of — states you never knew a screen could be in, worst on checkout and payments. A state machine maps them all, including the ones you'd miss.
The bugs that bite aren’t visual — they’re a user landing in a state I never planned: a payment stuck retrying, a button still spinning after the response came back. So model the screen as a state machine. It’s always in exactly one named state, and only the paths you drew can happen — anything you didn’t, can’t.
Here’s a checkout drawn that way: the happy path as a spine, every edge and failure state hanging off it.
And each state is a screen. Switch between the base flow, the coupon feature added later, and the states easiest to miss — then drive each one; only the transitions the machine allows light up.
The point isn’t to enforce it — it’s that the diagram and the screens are one thing, and it surfaces the states you’d never have drawn: the failures, timeouts, and half-finished flows where a user gets lost. I wouldn’t reach for this on a settings page; on checkout or payments, where a missed state quietly costs money or trust, it’s worth keeping a living map beside the code.
Sources
- David Harel — Statecharts: A Visual Formalism for Complex Systems (1987)
- Ian Horrocks — Constructing the User Interface with Statecharts (1999)
- Erik Mogensen — statecharts.dev
- David Khourshid — XState / Stately Studio
- Khourshid — Model-Based Testing in React with State Machines (CSS-Tricks)
- @xstate/test docs
- Hillel Wayne — Formally Specifying UIs (Edmodo Snapshot, Alloy)
- Ryan Lucas — sketch.systems
- Stately Studio — Figma embed
- Alloy