State Management
The website keeps its shared state in one Zustand store, web/lib/store.ts. Zustand does the job NgRx does in Angular, with much less code: state plus the functions that change it.
What lives where
| State | Where | Why |
|---|---|---|
| Sign-in, open page, drawer, last failed save | The store | Several parts of the site use them |
| Data from the database | Each page loads its own | Supabase is the master copy |
| One component's own state | React useState | Nothing else needs it |
| Small preferences (panel widths) | localStorage | They belong to this browser |
The store
| Field | Meaning |
|---|---|
auth | {session} when signed in, {message} when not, null while checking |
section | "sources" or "math" |
menuOpen | Whether the ☰ drawer is open |
saveError | The last save to the account that failed |
| Action | When |
|---|---|
setAuth | Sign-in is checked, the token refreshes, or you sign out |
setSection | You move between Sources and Maths |
toggleMenu | You press ☰ |
closeMenu | The drawer closes (Escape, or a link on a phone) |
setSaveError | A save fails, or a page clears the last error |
Sessions
Supabase keeps the sign-in session in the browser and refreshes its token (persistSession: true in web/lib/auth.js). There is no server, so no cookies or middleware. watchSession() keeps the store's auth current: signing out in one tab signs out the others.
Seeing the store
On dev and locally only, never on the live site:
- Install the Redux DevTools browser extension.
- Open abhyas.dev.nishko.co, open developer tools, go to the Redux tab.
- Pick abhyas. Each action appears by name as it happens.
Or type abhyas.getState() in the Console.
Using it in code
// React: the component redraws only when the picked value changes
const menuOpen = useSite((s) => s.menuOpen);
// Plain JavaScript (lib/sources.js, lib/math/app.js)
site.getState().setSaveError("");
const stop = site.subscribe((s, before) => { /* ... */ }); // call stop() when the page closes
Add state to the store only when more than one part of the site needs it. Give it a default, a comment and a setter in web/lib/store.ts. Keep database data out of it.