Session Storage Contract Change — What You Need to Know
Session Storage Contract Change — What You Need to Know
Affects: Capacitor mobile app integrations Severity: Potentially breaking (Capacitor only) Version introduced: 0.1.90
Background
When the myProp platform was originally built, user account data was persisted to the browser's sessionStorage under the key user_accounts after login. On page refresh, an INIT_STORE action rehydrated that data into the application state, avoiding a network round-trip and making the app feel fast even on slow connections.
The rebuilt platform takes a different approach. It uses tRPC with React Query for all data fetching. Rather than reading stale account data from sessionStorage, the app fetches fresh account data from the server. This is the correct pattern for a Next.js application and results in more accurate, up-to-date data being shown to users.
What No Longer Happens
- User accounts are not written to
sessionStorageunderuser_accounts. - There is no
INIT_STORErehydration step on page load. - Session state is managed entirely by React Query's cache and the server.
Impact by Platform
| Platform | Impact |
|---|---|
| Web (Next.js) | ✅ No impact. Server rendering and React Query handle data freshness. |
| Capacitor mobile app | ⚠️ Potentially breaking if the app reads sessionStorage.user_accounts directly. |
How to Verify
- Check whether the Capacitor mobile app is still in active production.
- Search the Capacitor app codebase for any reads of
sessionStorage.getItem('user_accounts')orsessionStorage.user_accounts. - If no such reads exist, no further action is needed.
- If reads are found, proceed with the compatibility shim below.
Compatibility Shim (if required)
If the Capacitor app depends on the user_accounts sessionStorage key, add a shim on the web side that writes account data to sessionStorage after each successful tRPC account discovery fetch:
import { useEffect } from 'react';
import { trpc } from '@/lib/trpc';
export function useAccountSessionShim() {
const { data: accounts } = trpc.accounts.discover.useQuery();
useEffect(() => {
if (typeof window === 'undefined' || !accounts) return;
sessionStorage.setItem('user_accounts', JSON.stringify(accounts));
}, [accounts]);
}
Call this hook at the top level of the authenticated app layout so it runs consistently after every account fetch.
Note: This shim is a backwards-compatibility measure only. It should be removed once the Capacitor app is updated to fetch account data via the tRPC API directly, or once the Capacitor app is retired.
Why This Architecture Is Correct
The sessionStorage rehydration pattern was a pragmatic solution in the original app but carries a number of downsides:
- Stale data risk:
sessionStorageis never automatically invalidated. A user whose account permissions changed mid-session could see outdated data. - SSR incompatibility:
sessionStorageis not available on the server, requiring defensivetypeof windowchecks throughout the codebase. - React Query handles this better: React Query's cache provides fast, optimistic data on re-render while automatically revalidating in the background — giving the same performance benefit without the staleness risk.
The rebuilt app's approach is both safer and more maintainable for the long term.