AppCrumble mascotAppCrumble
DesignEmptyStateOnboardingUI

Your Empty State Is Doing More Work Than You Think

It's the screen a new user stares at the longest, and the one most teams design last. Three rules for making it earn that attention.

August 17, 20265 min read

The empty state is usually the last screen a team designs, and the first screen a new user actually spends time on. Before there's any data, any history, any reason to trust the product yet, there is just this one screen making the first impression. It's worth treating like one.

Three ingredients, not ten

AppCrumble's EmptyState component keeps to three things, on purpose:

  • A plain-language explanation of why the screen is empty - not a generic "no data found", but the actual reason ("you haven't created a project yet").
  • One clear action, styled as the obvious next step rather than buried among three equally-weighted buttons.
  • No copy that implies the user did something wrong. An empty project list isn't a mistake to apologize for.

Not every empty state is the same empty state

The mistake most teams make isn't writing bad copy - it's using the same copy for three situations that aren't actually the same:

  • First-time empty. Nothing has ever been created here. The action is creation, and the tone can be genuinely welcoming - "Create your first project to get started."
  • Filtered empty. Data exists, but the current search or filter combination doesn't match anything. The action here is almost never "create new" - it's "clear filters" or "try a different search." Offering to create a duplicate of something that probably already exists, just outside the current filter, is how you end up with three near-identical records in a database.
  • Cleared empty. The user deleted everything on purpose - an inbox at zero, a completed task list. This one doesn't need a call to action at all, and definitely doesn't need to be treated as a problem. A quiet "All caught up" does more good than a bold button trying to talk them into creating more work.

Using the first-time copy for a filtered-empty screen is the single most common empty-state bug: a search for a typo'd name returns "You have no projects yet - create one?", and a fair number of users will click it before realizing their project already exists.

Say what happened, not what's missing

"No results" describes the system's internal state. "Nothing here yet - create your first project to get started" describes the user's situation, and tells them what to do about it. The difference is one sentence, and it's the entire job of the screen.

Don't forget it has to be heard, not just seen

If a list quietly goes from "loading" to "empty" to "populated" with no visual reload, a sighted user notices the change; a screen reader user gets nothing unless that region is marked aria-live="polite". Wrap the container that swaps between skeleton, empty, and populated states in one, and make sure the empty state's action is a real, labeled button or link - not a bare icon with no accessible name - so it actually reaches someone navigating by keyboard or screen reader, not just someone scanning the layout.

Note
If an empty state needs an illustration to feel finished, that's usually a sign the copy isn't doing enough work yet. Fix the sentence before reaching for the artwork.

It's a small component - a heading, a line of body text, a button - but it's one of the eight shared pieces we treated as non-negotiable for v1, alongside things like SkeletonLoader and ErrorState. The dashboard a user sees on day one is mostly empty states wearing different labels, so it's worth getting the pattern right once.