All recipes
StatesPaste into CLAUDE.md

Empty states that don't look broken

Agents design for full data. Your users open the app and see zero data. The empty state is the first screen every real user meets, and your agent has never met a real user.

Jaideep
Founder, Krit
01

Populated

Recurring revenue, the chart, the customer table. The state your agent was designing for the whole time.

02

What agents ship

A gray $0, axes with nothing on them, a table header with no rows. Every element is technically present, and the screen reads as broken.

03

Designed

No zero, no dead axes. The card title and date range stay, so the screen reads as finished. One crafted object, one sentence naming the condition that fills it, one action.

Add to CLAUDE.md

The standing rule. Paste it into CLAUDE.md, AGENTS.md, or .cursorrules.

## Empty states

Every screen that renders data ships with a designed empty state, built in the
same pass as the populated state. Never as a follow-up.

1. Never render a zero as the headline. "$0" above a flat chart reads as failure,
   not as a new account. In the empty state, the metric is replaced, not zeroed.

2. Delete dead scaffolding. Empty chart axes, table headers with no rows, and
   skeleton chrome read as broken UI. Remove them from the empty state entirely.

3. Keep the outer frame. The card title, the date range control, and the
   surrounding navigation stay, so the user still knows where they are and that
   the screen finished loading.

4. One sentence, written as a fact about the future. Say what will appear here
   and name the exact condition that fills it.
   Good: "Revenue will appear here once your first customer is charged."
   Bad: "No data yet." / "Nothing here!" / "Get started with revenue tracking."

5. Exactly one action, and it must be the action that fills this panel. Not
   "Learn more." Not a primary and a secondary button. One.

6. No emoji. No stock illustration. No dashed-border upload box. If the state
   needs an object, use one brand-owned render at low contrast, under a quarter
   of the panel height.

7. Same padding, type scale, and border radius as the populated state. An empty
   state is not a special layout.

8. Distinguish empty from filtered from failed. "No customers yet" (empty),
   "No customers match these filters" plus a clear-filters action (filtered),
   and "Couldn't load customers" plus retry (error) are three different screens.

9. When you touch any existing screen that renders data, check its empty state
   before you finish. If it renders a zero, dead axes, a header-only table, a
   bare "No data", or nothing at all, fix it in the same change. Do not leave a
   screen you edited in a state these rules would reject.

Before finishing any data screen, render it with an empty dataset. If it looks
broken, unfinished, or like an error, it is not done.
Download the raw .md

Run the audit

A one-off sweep of the app you already shipped. Paste this into your agent as a message, not into CLAUDE.md.

Audit every screen in this codebase for empty states.

1. Find every view that renders a collection, metric, chart, table, list, feed,
   search result, or detail panel populated from a data source.

2. For each one, work out what actually renders when that source returns
   nothing: an empty array, null, a zeroed metric, or no response at all. Read
   the component, do not guess from the file name.

3. Classify each screen:
   - designed: passes the empty-state rules
   - undesigned: renders a zero, dead axes, a header-only table, a bare
     "No data", or an unstyled string
   - missing: renders nothing, a blank region, or crashes

4. Check the filtered-empty path and the error path separately. A screen can
   have a designed empty state and still fall over when a filter matches
   nothing or the request fails.

5. Report one table, sorted with the most-visited screens first:
   file path | screen | what renders when empty | classification | the one
   sentence and one action you would use instead

Do not change any code in this pass. Report the table, then stop and wait.

Why this one rule changes the whole app

Every dashboard, table, list, inbox, and chart in your product has an empty state. An agent generates all of them from the same default, so one instruction propagates across every screen at once. It is the highest leverage line you can add to an agent instruction file.

When the table comes back from the audit, fix them highest-traffic first, one commit per screen, so each is reviewable on its own. Most teams find between eight and twenty screens in the undesigned or missing columns on the first run. That is not a failure of your agent. Nobody prompted for the zero-data case, so nobody got it.

Checklist

  • No zeroed metric standing in for the empty state
  • No empty axes, no header-only tables, no ghost rows
  • Card title and controls still present
  • One sentence naming the condition that fills the panel
  • Exactly one action, and it fills this panel
  • No emoji, no stock illustration
  • Padding and type scale match the populated state
  • Empty, filtered, and error states are distinct
  • Existing screens audited, not just the one you are building

When a rule isn't enough

The screens a rule can't fix, I redesign myself.

Two weeks, $3,000. Your real screens, redesigned on the Krit canvas and shipped as a pull request into your repo. You keep the tool.

Book a free product audit