Skip to content

Working with IndexedDB

Namesake uses IndexedDB to store form data locally in the user’s browser. No form data is ever sent to a server. The idb library provides a Promise-based wrapper around the native IndexedDB API.

All database code lives in web/src/db/.

The database is named "namesake" and contains two object stores:

Store Key Purpose
formData field Stores each form field’s saved value
formProgress formSlug Stores each form’s current XState machine state
  1. Open your browser’s developer tools with Cmd + Option + I on Mac or F12 / Ctrl + Shift + I on Windows.

  2. Navigate to IndexedDB.

    Browser Dev Tools
    Chrome ApplicationStorageIndexedDBnamesake
    Firefox StorageIndexed DBnamesake
    Safari StorageIndexed Databasesnamesake
  3. If the namesake database exists, you will see the database version, the number of object stores, and entries within each object store.

Every schema change is a numbered migration file in web/src/db/migrations/. Each file exports a single migration function that receives the database and the current upgrade transaction.

When the app opens the database, getDB() in init.ts compares the stored version against DB_VERSION. If they differ, it runs every migration between the old version and the new one in order.

Each migration handles a single step — adding a store, renaming one, etc. Migrations must be idempotent.

Run the generator to scaffold all the boilerplate at once:

Terminal window
pnpm idb:add-migration <kebab-case-name>

For example, pnpm idb:add-migration add-documents-store will:

  1. Create migrations/NNN-add-documents-store.ts with a stub migration function
  2. Create migrations/__tests__/NNN-add-documents-store.test.ts with test stubs
  3. Register the migration in migrations/index.ts
  4. Bump DB_VERSION in init.ts

After running the script:

  1. Implement the migration in the generated .ts file
  2. Update NamesakeDBSchema in types.ts if you added or removed a store
  3. Fill in the test stubs in the generated .test.ts file

Migration tests use fake-indexeddb to simulate IndexedDB in Node.

Terminal window
pnpm test src/db

migrations/__tests__/index.test.ts contains two kinds of tests:

  • CI invariant — fails if DB_VERSION and the migrations array length fall out of sync, catching the most common mistake when adding a migration.
  • Upgrade path tests — run through getDB() to verify the full pipeline end-to-end (correct ordering, real starting states, known regressions).

Per-migration test files (001-*.test.ts, 002-*.test.ts, …) test each migration function in isolation using runMockMigration from test-utils.ts.