Skip to content

Work / Charades / Wiki / Concepts

persisted-state

Conceptverified 2026-10-30

persisted-state

selectedPackIds is authoritative user state, not derived output. On rehydrate it is only pruned of packs that are no longer valid or owned. It must never be recomputed from the packs the user happens to own, which is what used to discard their per-pack choices on every launch.

A fresh install selects only family-starter (DEFAULT_SELECTED_PACK_IDS in src/lib/pack-selection.ts), which is also the fallback when pruning leaves nothing. Every later launch restores the saved selection through the store's merge, minus any pack no longer owned.

Store version is 5 (v4 → v5 in lib/store-migrations.ts: one feedback flag, the two offers).

The price cache, charades.prices.v1, is display only. It is written directly to MMKV, outside Zustand persist, so a cold start paints prices on the first frame instead of waiting on the network. RevenueCat persists CustomerInfo but not resolved store products, and on Android the first getOfferings() also waits for a Play Billing connection. 30-day TTL, replaced by every successful fetch, and never consulted by a purchase, which always uses the live offering.

completedGames: see round-end-prompts.