Why Violet shows you nothing instead of something
Violet renders an honest nothing instead of a fabricated something. This post walks through three real empty states in the codebase, from the trust panel to the managed inference endpoint, explains why placeholder data erodes trust in AI products, and shows how real-or-nothing rails are enforced in review and tests.
What an honest empty state is
An honest empty state is what an interface shows when there is genuinely nothing to show. It says so in plain words. It does not fill the space with sample data, invented activity, or a skeleton that resolves into filler. In Violet the rule is structural: every surface renders real data or an explicit nothing. There is no third option.
This post is the working reference for that rule. It quotes three empty states from the actual Violet codebase, explains why the alternative erodes trust, and documents how the rule is enforced so it survives contact with deadlines.
Three real empty states in Violet's code
These are not mockups. Each example quotes the exact copy in the source files, together with the condition that triggers it.
First, the trust panel. The trust panel is the privacy promise made visible: when it opens, it lists every local storage key the companion app has actually written, by its real name, with a plain description and the real count. When no keys exist, it does not render an illustrative list. It renders this:
Nothing stored on this device yet.
Your conversation is not stored by this app. The thread lives only in this open page.
The clear-data control tells the same truth. When nothing is stored, it says there is nothing to clear, instead of pretending to clean something up.
Second, the morning arrival line. The companion greets the day with one sentence built from the real payload only: calendar events, tasks due, the current temperature. Each part appears only if the data behind it exists. One event today produces a line like 'One thing on today, at 9:00.' No events, no tasks, and no weather produce this:
Nothing scheduled. The day is open.
The tempting alternative is a placeholder agenda: a few generic rows so the screen never looks bare. Violet's rule forbids it. A schedule you did not create must never appear on your screen, even as decoration.
Third, the managed inference endpoint. Violet's cloud forwards chat requests to a real model provider and streams the reply token by token. If the provider is not configured, the endpoint does not degrade into a canned response. It returns an honest error:
HTTP 503
{ "error": "inference unavailable", "reason": "provider_not_configured" }
The neighboring failure paths hold the same line. An unreachable provider returns 502 with reason provider_unreachable. An exhausted free daily budget returns 429 with the reset time. A missing entitlement returns 402. Every failure has a status code and a reason. None of them has a fabricated answer.
Why fabricated placeholders erode trust
Placeholder data creates a second channel of information inside your product: the real one and the decorative one. The user cannot tell them apart, because they are rendered identically. From that moment, every value on screen carries an implicit question: is this mine, or is this filler?
In an AI product the stakes are higher, because the product's whole job is to assert things: what is on your calendar, what it remembers about you, what it did on your behalf. The first time a user catches one fabricated assertion, the damage is not local. It poisons every future assertion, including the true ones. Trust does not degrade gracefully.
There is also an asymmetry of cost. An honest nothing costs a little now: the screen looks quieter, and a new user sees less apparent activity. A fake something costs later, at the worst moment, when the user is depending on the product to be right. Violet takes the small cost every time.
Empty states are also the first thing a new user sees. A product that opens by telling the truth about having nothing sets the terms for everything after it. A product that opens with invented content has already taught the user how it behaves under pressure.
The real-or-nothing data rail
The general form of this rule is what we call a real-or-nothing data rail, one of the four rails of honest AI design. A surface may render a value only if it can trace that value to a real source: real state, real user data, or a real service response. When the source is absent, the surface renders its honest-empty state. The rail is a structural constraint on render paths, not a tone-of-voice guideline, and that is exactly what makes it checkable.
- No seeded demo data on production surfaces.
- No example rows that persist past a tutorial.
- No invented metrics or activity feeds.
- No canned AI replies when the model is unavailable.
- No skeleton loaders that resolve into filler instead of an empty state.
The rail does not forbid teaching material. It forbids teaching material that passes as the user's own data. A labeled tutorial, a sandbox that says it is a sandbox, or a styled illustration with a visible caption are all fine, because nothing about them pretends to be real.
How the rail is enforced in code review and tests
A rule that lives only in a style guide dies at the first deadline. In the Violet repo the rail is enforced by three mechanisms that a reviewer can actually run.
- A review question per render path: for every value on screen, name its source. If the source can be absent, show the empty branch. A pull request that adds a surface without its empty branch is incomplete by definition.
- Tests that assert honest failure: the API test suite asserts that speech-to-text returns HTTP 503 when its provider key is unset, and that the approve-to-send email seam refuses with 503 when no transport is configured. A change that fakes success on those paths fails the build.
- Exact, greppable copy: the honest empty strings are stable literals, so a reviewer can search for 'Nothing stored on this device yet.' and confirm the branch exists, and search for filler vocabulary to confirm it does not.
The source files also carry the rule at the top. The trust panel's header comment states its honesty rails in plain words: no aspirational claims, no invented values, no fake states, and nothing listed that is not there. The comment gives every future reviewer an anchor to hold the file against.
How to apply this in your own product
- Inventory every surface that renders data, including error toasts and loading states.
- For each value, name the source it must trace to. If you cannot name one, the value goes.
- Write the empty branch first, before the populated one, so it cannot be forgotten.
- Give every failure a status code and a machine-readable reason instead of a soft fallback.
- Test the nothing paths explicitly, the same way you test the happy paths.
- Make empty copy specific. 'Nothing stored on this device yet.' answers a question. 'No data' does not.
None of this requires new technology. It requires deciding, once, that the interface never asserts what it cannot ground, and then wiring that decision into review so it holds when nobody is looking.
Questions
Is an honest empty state the same as a blank screen?
No. A blank screen is ambiguous: the user cannot tell nothing from broken. An honest empty state is a plain, specific statement that there is nothing, such as 'Nothing scheduled. The day is open.' It answers the question the user arrived with.
Why not show sample data to help new users learn the interface?
Teaching content is fine when it is labeled as teaching content and cannot be mistaken for the user's own data. The problem is filler that passes as real. If a surface needs a tutorial, ship a tutorial, not fake records.
What should an AI product do when its model is unavailable?
Say so, with a status code and a reason. Violet's managed inference endpoint returns HTTP 503 with the reason provider_not_configured instead of a canned reply. A fabricated answer during an outage is worse than no answer, because the user has no way to know it is fabricated.
How do you keep empty states honest as a product grows?
Make them checkable. Keep the copy exact so reviewers can search for it, write tests that assert the failure paths return honest errors, and require one review question for every value on screen: where does this come from, and what renders when the source is absent?