NotesBuilding with AI4 min read
Loading, Empty and Error States Are Part of the Feature
Your application needs to make sense when the data is late, missing or unavailable.
Piotr Mrozowski — Founder, Mrozowski International
As per your prompt - AI builds a dashboard. It has charts, recent activity, a few summary cards and a rather impressive list of sample customers (which will likely sit in a JSON forever without getting cleaned up - but that’s a different topic).
Everything looks good.
Then you create a real account. There are no customers yet. Half the dashboard disappears, one card says “NaN” and a blank table takes up most of the page.
Apparently, the design depended on already having a successful business.
This is easy to overlook when building with AI. You review the version where everything has loaded, the data exists and nothing has failed (we usually refer to this as the “happy flow”). But your users will encounter other versions too.
While the data is loading
When someone opens a page, the data may not arrive immediately (and no - you don’t need to know the difference between CSR, SSR, SSG and ISR).
If the screen stays blank, they cannot tell whether the application is loading, broken or waiting for them to do something. Clicking around impatiently is a fairly predictable next step.
Give them an indication of what is happening.
Depending on the situation, that could be a loading message, a spinner or a skeleton: placeholder shapes that roughly match the content about to appear.
The same applies to actions. If someone submits a form, the button should acknowledge it. “Sending…” is more useful than leaving “Send” unchanged while a request runs in the background.
Prevent repeated submissions while the first is processing, too. Five clicks should not create five orders (in engineering terms - you want this to be idempotent).
And if the request fails or times out, the interface needs to move on from loading. A spinner that spins forever is technically animated, but otherwise not particularly helpful.
When there is nothing to show
An empty screen is not necessarily an error.
A new account has no activity. A project has no files. A search finds no matching results.
These situations need different explanations.
For a new account:
You haven’t added any customers yet. Add your first customer to get started.
For a filtered customer list:
No customers match these filters. Try changing or clearing them.
The first helps someone begin. The second helps them find something that may already exist.
Simply displaying “No data” in both places leaves the user to work out what happened.
Also check the less obvious parts of an empty page. Summary cards, charts and calculations need to handle having no records. An average based on zero entries should not become “NaN,” and a failed request should not quietly appear as zero revenue.
Those mean very different things.
When something fails
Requests fail. Connections drop. External services have bad days.
Your application should explain what happened in language the user can understand and offer a sensible next step.
We couldn’t load your invoices. Please try again.
That is more useful than a blank section or an unexplained “Error 500.”
Where retrying is appropriate, provide a retry button. If part of the page still works, keep it available instead of replacing the entire screen with an error.
And please preserve what the user entered.
If someone spends ten minutes completing a form and submission fails, clearing every field is a remarkably effective way to make sure they never try again.
There is another distinction worth checking: a success message should appear only after the application has confirmed the relevant action succeeded. Clicking “Save” is not, by itself, evidence that anything was saved.
Ask AI to show you these versions
Do not only ask whether loading and error handling were added. Ask to see what happens.
Have the AI demonstrate the page with a slow response, no records, no search results and a failed request, where its tools allow it.
This is also where you may discover that the error message is technically present but appears below the bottom of the screen. Or that the loading indicator makes the whole layout jump.
The code can contain all the right pieces while the experience still needs work.
A prompt you can reuse
Review the screens and user actions affected by this task. Handle the relevant loading, empty, success and error states as part of the implementation. Follow the project's existing UI patterns and components. While requests are processing, show appropriate feedback and prevent accidental duplicate submissions. Ensure failed or timed-out requests do not leave the interface stuck in a loading state. Distinguish between a new account with no records, a search with no results and a failure to load data. Provide a useful explanation and next action for each relevant case. Preserve user input when submission fails. Show success only after the relevant operation is confirmed. Provide retry controls where retrying is appropriate. Make sure charts, summary cards and calculations handle empty data correctly. Do not present failed requests as empty results or zero values. Verify these states using controlled test data or simulated responses where possible. Do not disrupt live services to create failures. Run the relevant checks and report which states you actually verified, along with anything you could not test.You do not need an elaborate illustration for every empty table or a skeleton for every button. Often, a short message and a clear next action are enough.
But these situations belong in the feature from the beginning. Your first user should not need to populate the application before it becomes usable.