Field Notes
State Management
Three-Tier State Management: URL, Zustand, and TanStack Query
Rillex Casino uses three state layers: the URL for shareable UI state, Zustand for client-only state, and TanStack Query for server data. This gives its 22 feature modules clear boundaries instead of one overloaded store.
- Topic
- State Management
- Year
- Read
- 7 min
- Connected
- Rillex Casino
The problem
system cutThe solution
I split the state into three tiers. Each tier has a clear job.
Tier 1: URL state
- Active tabs, filters, sort order, and pagination cursors
- Modal triggers such as
?modal=loginand?modal=deposit - Game category and provider filters
useQueryParam(key, defaultValue)usesreplaceStateanduseSyncExternalStoreso updates stay synchronous without routing through Next.js
Tier 2: Zustand
- Seven isolated stores:
authStore,walletStore,uiStore,platformStore,chatStore,notificationStore, andliveBetsStore - Each feature owns its slice. For example,
chatStoredoes not needwalletStore. - Sensitive persisted data, including auth tokens and the user object, is stored in
localStoragewith AES-GCM encryption - The
rillex-authBroadcastChannel keeps login, logout, and token refresh in sync across tabs
Tier 3: TanStack Query
- Typed key factories per feature, including
gamesKeys.list(filters),walletKeys.balance(), andbonusKeys.active() - All 33 WebSocket event types map to query keys.
deposit_confirmedinvalidateswalletKeys.all;bonus_wagering_updateinvalidatesbonusKeys.all. - Server components prefetch with a
QueryClientsingleton andReact.cache, then dehydrate throughHydrationBoundary. Games, banners, and SEO data are therefore available without a second client request.
Why this works
The tiers do not duplicate state. The URL holds shareable UI state, Zustand handles client-only details like toasts, sidebar state, and chat drafts, and TanStack Query owns API data. When a feature is added, there is a sensible place for it to live.