Step 1 of 5
Inventory async surfaces
List every place the app waits or can fail.
Scan the app and produce a table of every async surface: data fetches (per view), mutations (per button/form), and lists that can be empty. For each record: current loading treatment (none/spinner/skeleton), current error treatment (none/console/UI), and empty-state presence. Test each by throttling the network and forcing a failure in devtools.
Expected after this step
A gap table of all async surfaces and their current states.
Should not happen
- ✕White/blank flash before data appears
- ✕Errors caught and swallowed with empty catch blocks
- ✕Lists that render nothing when empty
- ✕Buttons that stay enabled and double-fire during requests
Verify before continuing
Do not move on until every check is true. The complete button stays locked until then.
Do not continue if…
- !White/blank flash before data appears
- !Errors caught and swallowed with empty catch blocks
- !Lists that render nothing when empty
- !Buttons that stay enabled and double-fire during requests
If the AI messes this up
Use this when the AI fakes progress or breaks the feature. It forces a real fix.
The table missed surfaces. Grep for every fetch/axios/mutation call and every list render, and re-verify each with throttled network.