Designing Empty and Zero-Data States for New Users

On a logistics platform we built last year, the first thing a new admin saw after signup was a dashboard with three empty charts and a table with a header row and nothing underneath. It looked broken, not empty. Support tickets from week one were almost entirely 'is this working?' rather than actual product questions.
We stopped treating empty states as a fallback and started designing them as their own screen. Instead of an empty table, we show a preview of what the table looks like once populated, greyed out, with a single clear call to action layered on top: 'Import your first shipment' or 'Connect your warehouse feed.' The ghost data does more to explain the product than any copy could.
The mistake we made first was writing empty-state copy that described the feature ('No shipments yet') instead of the next action ('Add your first shipment to start tracking'). Swapping description for instruction cut time-to-first-action by a noticeable margin in our post-launch analytics, because users stopped hunting for the button and started reading a sentence that told them where it was.
Zero-data states also need to differ from error states and loading states, which sounds obvious until you're staring at three visually identical grey boxes in a design file. We now use distinct illustration treatment for 'nothing here yet' versus 'something went wrong' versus 'still loading,' because users scan these screens in under a second and rely entirely on visual pattern, not text, to know which one they're looking at.
The other lesson: empty states are not one-size-fits-all across a product. A brand-new account's empty dashboard should sell the product. A returning user's empty search results should help them adjust their query. We used to reuse a single generic 'nothing here' component everywhere, and it undersold the product to new users while over-explaining to experienced ones.


