2026-04-19-offline-first-writes

Sun Apr 19 2026 07:00:00 GMT+0700 (Western Indonesia Time)type/changelog

2026-04-19 — Offline-first writes + entity outbox

Commits b92f1ef, adcddd7.

What

  • Implemented offline-first writes for transactions backed by an IndexedDB outbox (src/lib/offline/outbox.ts, sync.ts).
  • Extended outbox coverage to banks, categories, and wishlist via per-entity merge logic (mergeBanksOutbox.ts, mergeCategoriesOutbox.ts, mergeWishlistOutbox.ts).
  • Added OutboxSyncContext, useOutboxSync, usePendingEntities, usePendingTransactions hooks for UI awareness of pending state.
  • PWA service-worker tuning for performance.

Why

Adding a transaction on mobile while offline (commute, no signal) was the dominant unmet use case. Without an outbox, the form just failed silently. The outbox makes the PWA actually useful as a "capture now, sync later" tool. Extending to all mutable entities meant onboarding (creating a first bank/category) also works offline.

Touches

  • src/lib/offline/ (new module)
  • src/app/(main)/* — UI for pending indicators
  • next.config.* — PWA tuning
  • tests/e2e/offline-*.spec.ts — E2E coverage

Gotchas

  • Server-side merge must be idempotent; outbox can replay the same write. See [[Projects/personal-finance-notion/runbooks/runbook-pwa-outbox-stuck|runbook-pwa-outbox-stuck]].
  • New entity types must register dispatchers in entity-dispatch.ts and merge logic — easy to miss when adding a model.