Design the empty, loading and error states for a screen
FreeDesign every empty, loading, and error state for a UI screen with a developer-ready spec covering layout, microcopy, behavior, and accessibility, so no edge case ships as a blank white page or a dead-end error.
Turns a single screen into a complete state map — first-use empty, no-results, initial and incremental loading, offline, server error, expired session — each fully specified with copy, visuals, behavior, and a11y so engineers build them without guessing.
Your details
saved for every promptThis prompt
You are a senior product designer who specializes in interaction design and UX microcopy. You are known for designing the full state matrix of a screen — not just the happy path — so that empty, loading, and error moments feel as considered as the populated view.
Design the empty, loading, and error states for {{screen_name}} in {{product}}. Success = a developer or design-system engineer can build every state from your spec without guessing, and no realistic condition (first use, no network, slow API, server failure, expired session) is left as a blank screen or a dead-end error.
Context — the screen and its constraints:
- Screen: {{screen_name}}
- What it shows when full (the populated / happy state):
"""
{{populated_content}}
"""
- Platform: {{platform}}
- How its data loads: {{data_source}}
- Primary action a user takes on this screen: {{primary_action}}
- Design system / components to reuse (or "none"):
"""
{{design_system_notes}}
"""
- Voice for all user-facing copy: {{brand_voice}}
Work through these steps:
1. Map the state matrix. List every state this screen can enter — the empty variants (first-use, empty-after-clearing, and no-results if the screen has search or filters), the loading variants (initial load, refreshing, loading more), and the failure variants that {{data_source}} makes possible (offline with and without cache, server error, not-found, permission or expired session, timeout). Mark which ones actually apply here, and where two conditions overlap, state which one wins.
2. Design each empty variant. Distinguish them clearly — a brand-new user needs orientation and encouragement, someone who cleared their list needs reassurance, and a no-results view needs a way to broaden or reset. For each, specify a headline, a supporting line, illustration or icon guidance, a primary CTA tied to {{primary_action}}, and any secondary action.
3. Design the loading states. Choose a skeleton, spinner, or progress indicator per context and justify it — prefer a skeleton shaped like the real {{populated_content}} for initial content loads. Define timing: delay showing a loader for very short waits so it doesn't flash, hold it a minimum once shown so it doesn't flicker, and describe optimistic or stale-while-revalidate behavior and the "load more" pattern.
4. Design the error states. For each realistic failure, write a plain-language message (what happened and what to do next), give a clear recovery action, preserve any input or scroll position the user had, and choose the surface — inline, full-screen, or toast — by how much of the screen the failure affects. Include an offline or cached fallback wherever {{data_source}} allows it.
5. Specify accessibility and motion for every state. Announce loading with a polite live region and errors assertively, expose busy state, manage focus on each state change, provide screen-reader text for anything purely visual, avoid relying on color alone, and honor reduced-motion.
6. Define transitions and voice. Describe how the screen moves between states and the timing of those moves, and keep all microcopy consistent with {{brand_voice}}.
Output in this structure:
- State inventory: a table with columns State | Trigger / condition | Applies here | Priority when overlapping.
- Per-state spec: one block per applicable state with Layout, Visual, Headline, Body copy, Primary action, Secondary action, Behavior & timing, and Accessibility.
- Transitions: a short summary of how the states flow into each other.
- Copy sheet: every user-facing string collected as key = "value" pairs, ready for handoff and localization.
- Assumptions & open questions: anything you had to assume, or would confirm before build.
Constraints:
- Write every user-facing string in {{brand_voice}}; keep error text free of status codes and technical jargon, and never phrase it to blame the user.
- Give every state a way forward — an action, an auto-recovery, or a fallback. No dead ends.
- Reuse the components and tokens named in {{design_system_notes}} wherever they fit; introduce a new pattern only when none exists, and flag it when you do.
- Describe layout and behavior in tool-agnostic terms (structure, spacing intent, timing) rather than framework-specific code.
- If the screen's data or actions are unclear, list them under Assumptions & open questions instead of inventing product details.16 fields still empty — the {{like_this}} slots fill in as you type.
See it in action
What this prompt produces with example details filled in:
State inventory — Saved Articles (iOS) | State | Trigger / condition | Applies | Priority when overlapping | |---|---|---|---| | First-use empty | Signed in, zero articles ever saved | Yes | — | | Cleared empty | Had saves, user removed them all | Yes | — | | No-results empty | (no in-list search or filter) | No | — | | Loading (initial) | Screen opens, no cached list | Yes | Suppressed if response < 300 ms | | Refreshing | Pull-to-refresh over an existing list | Yes | Non-blocking | | Loading more | Infinite scroll, next page exists | Yes | Footer only | | Offline — cached | No network, cached list present | Yes | Beats server error; show stale + banner | | Offline — no cache | No network, nothing cached | Yes | Beats generic error | | Server error (initial) | API 5xx on first load | Yes | Only when no cache exists | | Load-more error | API 5xx while paginating | Yes | Footer only, list stays | | Session expired | API 401 | Yes | Routes to global sign-in | Precedence: cached content always beats a blank state; Offline beats Server error; a full-screen error appears only when there is nothing else to show. ── Loading (initial) ── Layout: 6 DS Skeleton cards stacked at 8pt gaps, each mirroring the real Card — 64×64 thumb block, two text lines at 60% and 40% width, a small pill for read-time. Visual: shimmer from the Skeleton component. Headline / body: none — the skeletons carry the meaning. Behavior & timing: render on open; if the fetch resolves under 300 ms, skip the skeleton and show cards directly; once shown, hold it ≥ 500 ms to avoid flicker; cross-fade to real cards on success (reduced-motion → instant swap). Accessibility: list container role="status", aria-busy="true"; SR text "Loading your saved articles." ── First-use empty ── Layout: centered stack in the upper third, 24pt padding. Visual: DS EmptyState illustration "bookmark-open", 120pt. Headline: "Nothing saved yet" Body: "Tap the bookmark on any article to keep it here — ready to read, even offline." Primary action: Button (primary) "Find something to read" → Home feed. (The bookmark itself lives in the reader, so we send people to where saving starts.) Secondary action: none. Behavior & timing: static. Accessibility: illustration aria-hidden; the headline is the screen's first heading and takes focus; SR announces "No saved articles. Find something to read to get started." ── Server error (initial) ── Layout: centered stack, same rhythm as the empty states. Visual: icon "cloud-slash" 64pt in a muted tone — not an alarming red. Headline: "We couldn't load your saved articles" Body: "Something slipped on our end. Give it another try." Primary action: Button (primary) "Try again" → refetch. Secondary action: Button (ghost) "Back". Behavior & timing: appears only when no cached list exists; "Try again" shows the initial skeleton again. Accessibility: container role="alert"; focus moves to the headline; "Try again" is the first focusable control. Transitions: open → Loading → (Populated | First-use empty | Offline-cached | Server error). Populated → pull-to-refresh → Refreshing → Populated (or a Toast on failure, list preserved). Populated → scroll end → Loading more → appended (or a Load-more footer with "Retry"). Any state → connectivity lost → Offline banner; regained → auto-refetch. Copy sheet: - loading.sr = "Loading your saved articles" - empty.first.title = "Nothing saved yet" - empty.first.body = "Tap the bookmark on any article to keep it here — ready to read, even offline." - empty.first.cta = "Find something to read" - empty.cleared.title = "Your list is clear" - offline.cached.banner = "You're offline — showing your last saved list." - error.server.title = "We couldn't load your saved articles" - error.server.body = "Something slipped on our end. Give it another try." - error.server.cta = "Try again" - error.loadmore.footer = "Couldn't load more. Retry" Assumptions & open questions: - No in-list search or filter, so no no-results state is specified — confirm. - Session expiry (401) hands off to the app's global sign-in flow rather than rendering inside this screen. - Load-more failures retry on tap, not automatically — confirm that's the desired behavior.
Tips
- Paste your real populated layout into {{populated_content}} — the skeleton shape and the empty-state value prop are only as good as your description of the full state.
- Fill {{data_source}} honestly (auth? offline-capable? real-time?) — it decides which error states are even possible and which fallbacks make sense.
- If the screen has search or filters, say so in {{populated_content}} so the no-results empty state gets designed too, not just first-use.
- Run the same prompt across every screen and reuse the copy-sheet keys as a shared checklist so states stay consistent product-wide.
Built by Web Innoventix
Want the work done, not just prompted? We design, build and rank websites that get found on Google and cited by AI.
Get a free quoteMore prompts
Browse all →Turn a rough UI idea into a build-ready design prompt
Turn a vague UI idea into a precise, generation-ready design prompt — a one-line vibe, a named-colour design system, and a numbered page structure — that v0, Stitch, Lovable, or Claude can render into a polished first screen on the first try.
Design critique that returns prioritised fixes
Get a senior product-design critique of any screen — specific, located, severity-ranked usability fixes tied to real heuristics, not vague praise.
Design a first-run onboarding flow to your product's aha moment
A ready-to-paste ChatGPT prompt that interviews you about your product, then designs a first-run app onboarding flow that walks new users to their aha moment — delivered as a build-ready spec.
Plan your product's information architecture and sitemap
A paste-and-go ChatGPT prompt that interviews you about your product and users, then delivers a full information architecture and sitemap — navigation model, page hierarchy, URL scheme, and key user flows.
Interview a user and turn it into a UX research brief
A paste-and-go ChatGPT prompt that runs a professional UX discovery interview one question at a time, then synthesizes your answers into a structured, shareable UX research brief.
Generate a design token system with light and dark palettes
A paste-and-go ChatGPT prompt that briefly interviews you, then generates a complete light and dark design token system — primitives, semantic tokens, and WCAG-checked contrast — ready to export as CSS variables, DTCG JSON, or a Tailwind config.

