State Model
Philosophy and anti-patterns: [core-architecture-thinking.md](./core-architecture-thinking.md). This file lists **concrete stores, keys, and files**.
Philosophy and anti-patterns: core-architecture-thinking.md. This file lists concrete stores, keys, and files.
Rule Of Thumb
- Zustand: browser OS local state.
- TanStack Query: server state and cache. Planned / not implemented yet in shell runtime.
- localStorage: persisted user preferences and local-only layout hints.
- React local state: temporary UI state for panels, dialogs, menus, animations, and previews.
- Browser
localStorage: Shell React surfaces should useuseLocalStoragefromusehooks-ts. Zustand and other non-React writers usebrowser-local/browserLocalStore.ts. All Próx-managed keys are listed inbrowser-local/proxOsLocalStorageKeys.ts(also used by Developer Tool “clear managed storage”).
Zustand
Store: apps/os-shell/src/window-manager/store.ts
Main fields:
| Field | Meaning | Primary readers/writers |
|---|---|---|
windows | Active WindowInstance[]. | useDesktopShellController, WindowLayer, Active Apps panel. |
spaces | Ordered desktop and fullscreen Spaces. | useDesktopShellController, WindowLayer, Mission Control. |
activeSpaceId | Current virtual desktop or fullscreen Space. | WindowLayer, keyboard shortcuts, route sync. |
previousSpaceId | Previous Space used for transition context. | Window manager actions. |
missionControlMode | none, spaces, or windows. | Global shortcuts, Mission Control overlay, App Expose transforms. |
spaceTransitionDirection | Horizontal Space-switch animation hint. | WindowLayer. |
activeWindowId | Current focused window id. | TopBar, WindowLayer, AppSwitcherOverlay, Active Apps panel. |
commandOpen | Command surface visibility. | DesktopScene, GlobalShortcuts, Shellbar command button. |
commandQuery | Command search text. | CommandSurface, useCommandModel. |
utilityTrayOpen | Developer tool drawer visibility. | Dock, GlobalShortcuts. |
activeAppsOpen | Active Apps drawer visibility. | Dock, Shellbar active apps button. |
The store owns durable local OS mechanics: open, close, focus, minimize, desktop zoom, fullscreen Space entry/exit, Space switching, layout hydration, and command/drawer visibility.
localStorage
Settings hook: apps/os-shell/src/shell/settings/useShellSettingsState.ts
Current keys:
prox-os.os.densityprox-os.os.themeprox-os.os.shellbar-placementprox-os.os.cursorprox-os.os.shellbar-layoutprox-os.os.overlay-placement-modeprox-os.os.panel-sideprox-os.os.toast-cornerprox-os.os.screensaverprox-os.os.screensaver-timeprox-os.os.desktop-backgroundprox-os.os.view-modeprox-os.os.language-preferenceprox-os.os.recent-appsprox-os.os.window-sizes
These preferences are local-first and can later be backed by profile sync without changing presentation components.
React Local State
Controller: apps/os-shell/src/shell/useDesktopShellController.ts
Examples:
notificationssystemToastaiAssistantOpenaboutOsOpenexitOsOpensnapPreviewspaceDropPreviewanimatedWindowIdminimizeAnimationactiveAppsPulse
These are view-session states. They should not be stored in Zustand unless other independent subsystems need to observe them. Mission Control is the exception: it lives in Zustand because keyboard handling, Space routing, window transforms, and the overlay all need one shared source of truth.
Small visual affordances inside Mission Control, such as the hover preview for the pinned + control, stay CSS-only inside MissionControlOverlay.tsx. Drag/drop placement feedback uses spaceDropPreview in the shell controller because it depends on the active drag pointer and must be cleared atomically when a window is moved into an existing or newly inserted desktop Space.
TanStack Query
apps/os-shell now mounts QueryClientProvider through apps/os-shell/src/providers.
Current files:
apps/os-shell/src/providers/queryClient.tsapps/os-shell/src/providers/QueryProvider.tsxapps/os-shell/src/providers/AppProviders.tsx
React Query Devtools are mounted only in development with initialIsOpen={false}.
No useQuery server data cache is currently used by shell apps yet.
Planned use:
- app registry fetched from
/api/apps - synced settings from
/api/settings - session from
/api/user/session - server-backed notification, visitor, asset, and project read models
Remote server data should go through TanStack Query, not Zustand.
API / Mock State
Current app data is mostly static local mock data:
packages/os-apps/src/shared/mock-data.ts- per-app local arrays inside app components
No formal API client is currently used in apps/os-shell.