Skip to content
Flows
Debugging Beginner · 45-75 minutes

Add Database Persistence

Your app forgets everything on refresh: move state into a real database with working CRUD.

Start Route · 5 steps

The route

5 steps to Done

  1. 01

    Inventory unpersisted state

    Find everything the app forgets - the full list, not samples.

    Preview prompt + verify gate ▾

    Audit the app and produce a table of every piece of state that should persist but currently does not: the data (e.g. tasks, profile edits, settings), where it lives now (useState/localStorage/nowhere), what user action creates or changes it, and whether refresh loses it. Test by performing each action then refreshing. Mark each row KEEP-LOCAL (genuinely UI-only) or PERSIST.

    • Each row was refresh-tested
    • Every user-created data type appears
    • PERSIST rows cover all important data
  2. 02

    Design models and endpoints

    Give each PERSIST item a schema and API before wiring.

    Preview prompt + verify gate ▾

    For every PERSIST row, define: the database model (fields, types, owner id where user-scoped, timestamps) and the endpoints needed (list, create, update, delete as applicable) with request/response shapes. Note which lists need pagination and which data is user-scoped versus global. Then create the models and endpoint skeletons in the codebase.

    • Every PERSIST item has a model
    • User-scoped data includes an owner field
    • Endpoints cover each needed operation
  3. 03

    Wire writes to the backend

    Every create/edit/delete must hit the database, not just state.

    Preview prompt + verify gate ▾

    Wire all mutating actions to the backend. Requirements: create/edit/delete handlers call their endpoints and await success before confirming in the UI; failures show visible errors and do not fake success; optimistic updates (if used) roll back on failure; after each mutation the data refetches or reconciles. Prove each with a mutation followed by a hard refresh.

    • Each create survives refresh
    • Each edit survives refresh
    • Each delete stays deleted
    • Failures show errors without fake success
  4. 04

    Wire reads with proper states

    The UI must load truth from the backend with honest states.

    Preview prompt + verify gate ▾

    Wire all reads. Requirements: every list/detail view fetches from the backend on mount; loading skeletons while fetching; empty states with helpful copy when there is no data; error states with retry on fetch failure; remove all hardcoded/demo arrays. User-scoped views must filter by the authenticated user.

    • Hardcoded arrays are gone
    • Loading and empty states render
    • Fetch failure shows retry
  5. 05

    Persistence QA pass

    Prove the app remembers everything, everywhere.

    Preview prompt + verify gate ▾

    Run persistence QA and report PASS/FAIL with evidence: for each PERSIST item - create, refresh, edit, refresh, delete, refresh; open a second browser/incognito session and verify consistency; kill the network and verify reads/writes show error states instead of silent loss; check user-scoping with two accounts if applicable. Fix all failures and re-run.

    • Full CRUD-with-refresh cycle per entity
    • Second-session consistency verified
    • Offline behavior shows errors, not silent loss
    • All failures fixed