Make a State Checklist
For each component, ask what states it can be in before you start writing.
Before starting, list the states each element can appear in, as a table. This table is both the spec and the acceptance checklist.
What you'll run into:
- It passes when you click through it yourself, then hits a state you never built the moment someone else uses it
- You don't know what to test, so you click around by feel
- You ask the AI to fill in states and it adds two, while three others go unmentioned and unbuilt
Missing states happen because they never appear in the requirement description. You say "build a reconciliation page," and the picture in your head is the screen with data, all normal. The checklist's job is to force you to think through all those other screens. It isn't a document for someone else — it's a tool for you: it turns "I remember there are states" into "these states are all written down." The first relies on memory; the second relies on paper.
How to make it
Four columns is enough: element, state, trigger, what's shown. Add a checkmark column at the end to use as an acceptance sheet when you're done. Keep the column names consistent with the words used in implementation and testing, so nothing drifts apart.
- List by element, not by page. A page has lists, buttons, inputs — each with its own states. Mix them together and you'll miss some.
- Write trigger conditions concretely. "When an error occurs" isn't enough; "API returns 500 or times out" tells you how to test it.
- What to display should be directly actionable. "Show an error hint" isn't enough; "show the reason plus a retry button" is.
- Scan the list yourself before building. Adding a state now is one line in a table; adding it after it's built is a code change.
As an example, take the comment list. Element: comment list. State: empty. Trigger: the list API returns 200 with an empty data array. What's shown: a placeholder illustration and a line saying "No comments yet — post the first one." With this row written, the implementer doesn't guess and the reviewer has something to check against.
Six questions for each element
Six questions map to six states; ask them for every element, and each one you skip is a screen design you lose:
| Question | State it covers |
|---|---|
| What if there's no data? | Empty state. Distinguish "never had data" from "filtered everything out" |
| What if data hasn't returned? | Loading state. Only needs to show past one second |
| What if it failed? | Error state. Needs a reason and a retry |
| What if it can't be clicked? | Disabled state. Also say why it's disabled |
| What if it's processing? | In-progress state. Lock the button to prevent double submit |
| What if the data is huge or extra long? | Truncate, fold, paginate. The layout must survive extremes |
| What if validation fails? (inputs) | Validation state. Point it out in place and state the rule |
| What if it's read-only? (inputs) | Read-only state. Content viewable but not editable, visually distinct |
The sixth question is the easiest to skip. It isn't a state, it's an edge case — but the symptom looks the same: a forty-character name can break an entire row's layout. The last two rows are input-only; lists and buttons don't need them, but form pages can't do without them.
The first four questions are the core; they map to All Four States, which covers what each state should answer. The checklist's job is to turn those concepts into rows you can tick off in your own requirement.
A note for the AI
Have the AI produce the checklist first, you tweak a few lines, then let it implement against it. Much steadier than asking for code directly — you're editing a table, not code, and the earlier you catch a mistake, the cheaper it is to fix.
PROMPT · state checklist
Page: [page name and purpose]
Main elements: [list / form / button / filters ...]
Do not write code yet. Output a state checklist as a table
with four columns:
element | state | trigger | what's shown
Requirements:
1. Walk every element through these six questions: no data,
loading, failed, disabled, processing, extreme (extra-long
content / too many rows).
2. For input elements, additionally list: validation failed,
read-only.
3. Write triggers concretely, e.g. "API returns 500 or times
out after 10s", not "when an error occurs".
4. What's shown must be directly implementable, including the
key copy points.
5. Finally list the states you're unsure about separately and
ask whether I want them.
Write code only after I confirm the checklist. When done, go
through the checklist item by item and report which ones pass
and which deviate.
Once the table is complete, it doubles as the acceptance checklist: have the AI self-check against it, tick every row yourself, then ship. That costs an order of magnitude less than letting users hit the missing states after launch. The more concrete the checklist, the more deviations the AI can catch on its own — and the less rework you do.
