Zovia Snapshot

The checklist

What a real app actually needs.

Months of building shipped apps taught us what real means: the concerns every app has to handle before it is good enough to charge for. Here is the whole checklist, nothing held back. The stack in Zovia Snapshot ships each of these already solved.

27 checks across 7 groups

Foundation

The parts that are painful to change once people depend on them.

Server-authoritative data

If the app can send its own user id, anyone can act as anyone. Trust is decided on the server or it is not decided at all.

HowRead the caller's identity from the session on the server. Send data from the app, never identity.

Validate the backend before every deploy

A backend that returns an array where the app expects a string crashes every screen that reads it.

HowKeep a schema you validate against, and run that check before any deploy that touches the shape of a response.

Real accounts from the first launch

A guest state you bolt real accounts onto later becomes a migration you regret. Every user should be a real account from minute one.

HowSign people in on first open, email and password with verification or a one-tap path, with no dead-end guest mode.

Every screen

What each screen owes the person looking at it.

One owned app shell

Rebuilding the header, nav, and chrome per screen guarantees they drift apart.

HowPut the shared chrome in one scaffold every screen uses. Screens own their body, not the frame.

A skeleton on every load

A blank screen or a bare spinner reads as broken. People decide an app is slow in the first second.

HowShow a placeholder shaped like the real content while it loads. Every data-loaded component ships one.

Navigation that goes somewhere

Broken links fail silently. A tap that lands nowhere looks identical to a tap that registered.

HowConfirm every route you send someone to actually exists, and smoke-test the link in the running app.

Every interaction

Ten interaction principles we hold every screen to. Each is a pass or fail check, not a vibe.

Doherty threshold

Past about 400ms with no response, people feel the app stall and lose the thread.

HowAnswer every action inside roughly 400ms with a skeleton, an optimistic update, or motion.

Fitts's law

Small targets in the corners are missed taps and quiet frustration.

HowPrimary targets at least 44pt, in the natural thumb zone, never tucked under the chrome.

Forgiveness

One wrong tap should never be permanent.

HowGive every destructive action an undo, or a clear confirm before it happens.

Recognition over recall

A blank field asks the user to remember. A good field reminds them.

HowSurface recent and likely choices before asking anyone to type.

Progressive disclosure

Showing everything at once buries the small part that matters right now.

HowOpen on the common case. Put the rest behind More, a chevron, or a second screen.

Hick's law

Too many choices at once stalls the decision.

HowKeep a primary surface to about seven options. Beyond that, group, filter, or search.

Peak-End rule

People remember the peak and the ending, not the average.

HowGive each flow an intentional opening and a satisfying close, never a silent drop back to a list.

Zeigarnik effect

Unfinished work nags, but only if the user can see it.

HowShow incomplete progress when they return: 3 of 5 done, draft saved a moment ago.

Goal-gradient effect

Effort rises near a visible finish. Hide the finish and it does not.

HowShow progress, and let it visibly accelerate as completion nears.

Calm technology

An app that interrupts for everything gets muted for everything.

HowDefault to ambient signals. Reserve notifications and modals for time-sensitive, high-stakes moments.

Every write

What has to happen when a person changes their data.

An undo path on every write

People tap the wrong thing. A write with no undo turns a half-second mistake into lost data.

HowEnd every user write with an undoable confirmation whose undo actually reverses the write.

Refresh the surface you are on

An action that does not visibly change the screen reads as it did not work, so people re-tap.

HowUpdate the current view the moment the action fires, with no reload and no reopen.

Cache-first and optimistic

A returning user staring at a spinner is a user deciding the app is slow.

HowShow cached content instantly, refresh in the background, apply writes optimistically and revert on failure.

Consistency

The difference between one coherent app and ten screens that drifted apart.

Design tokens, no hardcoded values

Ten one-off colors and paddings across the app fragment the whole thing.

HowUse tokens for type, color, spacing, motion, and opacity. If a value is not a token, the token set is what is wrong.

One component layer

Raw framework widgets drift from your type ramp and theme the moment you use them.

HowBuild from your own set for buttons, links, sheets, and toasts, not the framework's defaults.

Readable on any color

White text on a bright accent is invisible, and it is always a real user who finds out.

HowCompute the foreground color from the background's luminance. Never assume white or black.

Correctness that bites later

The bugs that ship quietly and surface once real people are using it.

Calendar days, not elapsed hours

Something done at 11pm yesterday reads as today if you count 24-hour blocks.

HowFor today, yesterday, and X days ago, compare local calendar days, not elapsed time.

Test the payload shape

The day the backend starts sending the full object, a field typed wrong crashes every screen that reads it.

HowKeep a parse test that covers the full payload, a sparse one, and unknown fields, and run it on every shape change.

Modals that do not stack

Two auto-firing prompts on the same frame land on top of each other, and on top of whatever the user was doing.

HowRoute auto-firing prompts through one coordinator that shows them one at a time.

Building with an AI in the loop

The habits that keep an AI-built app honest.

Scope the task, match the model

A heavy model on a typo wastes tokens. A light model on an architecture change wastes a day.

HowName each task's size before you start, and match the model and effort to it.

Verify before you call it done

It probably works is how broken things ship. Checking always costs less than a user finding out.

HowRun the thing and read the output before claiming a fix works. Evidence before the claim.

Every item on this list, already solved.

This is the bar Zovia Snapshot is built to clear. You do not reassemble it from a checklist, you start from the stack that already holds it, as source you own, with the same list shipped inside as a reference you build against.