Skip to content
ExamsLibraryFor agentsConnect your agent

Every list has four states

beginner·7 min·Markdown for agents

What this lesson teaches

Design the loading, empty, error and full branches of any list or page, and get an agent to build all four.

  1. 1Four branches, every time
  2. 2Loading: delay, then a skeleton
  3. 3Empty: three jobs
  4. 4Error: what happened, and a way out
  5. 5One more state: the first paint
  6. 6Getting an agent to do it

Watch a list arrive. First its outline, then a problem, then a retry, then the rows.

app.northwind.co/projects
Projects
MAtlas rebrandMaya ChenActive
JQ3 reportJon ParkDraft
ACheckout redesignAna RuizActive
LOnboarding emailsLeo SatoReview
Couldn't load projectsThe server didn't answer. Nothing was changed.Try again
A skeleton in the rows' own shape, an error that offers a way out, then the content.

That took about five seconds and showed you three different screens. Most generated UI only ever designs the last one, because the test account always has data. The states are the work. Components are where people touch your product, and their states are where most interfaces get lazy.

Four branches, every time

Every list, table, feed and dashboard has four states:

StateWhen you see itIts job
LoadingThe data is on its wayHold the shape so nothing jumps
EmptyThere is no data yetExplain what belongs here and how to add it
ErrorThe data could not be fetchedSay what happened and offer a real fix
FullThe data is hereThe screen you actually designed

Flip through them below, then switch to Agent default to see what you get when nobody asks.

Projects–
No projects yetA project keeps one client's files, notes and invoices together.

Says what belongs here, why it matters, and the one action that fills it. Same height as the full list.

Same list, same box. The designed version keeps its height in every state.
A missing branch in the code is a finding, even if the screen looks done.

Loading: delay, then a skeleton

Speed is a feeling, so the indicator depends on how long the wait will be.

Expected waitShow
Under about 150msNothing. Delay every indicator ~150ms so fast answers never flash one
By 400msA for a content area; a spinner only inside the button that started the work
3 to 15 secondsA progress bar with a percentage
Over 15 secondsProgress, time left, and a cancel button

A skeleton is a gray placeholder in the exact shape of the content: circles where avatars go, bars as wide as the words. Size each row from the real row (48px because the loaded row is 48px, not a guess). When the content arrives, nothing moves.

A centred spinner as the loading state of a whole list is a defect: the page collapses to a dot, then everything jumps when the data lands. That jump is called , and it is the first thing that makes a screen feel cheap.

Empty: three jobs

An is often the very first thing a new user sees. "No data" wastes it. A good one does three things:

  1. Says what belongs here. "No projects yet."
  2. Points to the next action. A real button: "Create project".
  3. Optionally, adds context. One line on why it matters, or an example.

Size it like the full state, so the first item does not shove the layout. An empty search result says what was searched and offers to clear it. And never auto-redirect from an empty state ("nothing here, taking you home..."): it feels like the app broke.

✕ Default

No data

✓ Designed

No projects yet
A project keeps one client's files, notes and invoices together.
Create project

Error: what happened, and a way out

An error state answers two questions: what went wrong, and what can I do now. "Something went wrong." answers neither. "Couldn't load projects. The server didn't answer. Your projects are safe." plus a Try again button that really refetches answers both. The framework's built-in error page and 404 count as missing states, too.

One more state: the first paint

A theme that flashes light before going dark, a sidebar that renders open then snaps shut: both happen because a saved value was read after the page painted. The fix is to decide before the first paint. A tiny script in the page head sets the theme class; layout choices like a collapsed sidebar come from a cookie the server reads; anything else waits to render until its value is known.

Getting an agent to do it

Agents build the full state because that is what their test data shows. Ask for the other three by name, with the numbers.

All four states· for your agent
For every list, table and feed in this screen, build all four states: loading, empty, error and full.
- Loading: delay any indicator 150ms; then a skeleton with the loaded rows' exact height, widths and gaps. No centred spinner.
- Empty: a title saying what belongs here, one line of why, and the primary action button. Same height as the full list.
- Error: what happened in plain words, that nothing was lost (if true), and a Try again that refetches.
- Persisted UI state (theme, sidebar) is set before first paint, not in an effect.
List any view where a branch was missing before you started.

Quick check

A list takes about 2 seconds to load. Which loading state fits?

What this lesson builds on and leads to, across every course.

  • Cards, icons, avatars and APIs
  • Words in the interface
  • Words matter
  • States are the work
  • A button has eight states
  • Instant actions, undo and toasts