Workspace & Persistence
Relevant source files
The following files were used as context for generating this wiki page:
Workspace & Persistence manages the state and storage of user-defined scanner configurations within the Nexus Scanner application. It ensures that filter criteria, universe selections, and interface preferences remain consistent across browser sessions by utilizing local storage. This system allows equity researchers to retain momentum, trend, and liquidity screens without requiring a backend database for user accounts.
Sources: frontend/README.md:9, frontend/README.md:124-126
Persistence Architecture
The application implements persistence through the useLocalStorageState hook, which synchronizes React state with the browser's localStorage API. This mechanism is origin-specific and does not perform external synchronization or cloud uploads.
Data Flow for State Persistence
The following diagram illustrates how user interactions trigger state updates that are then serialized to local storage.
The diagram shows the bidirectional relationship between React components and browser storage via the custom hook.
Sources: frontend/src/hooks/useLocalStorageState.ts:1-26, frontend/src/components/ExploreTab.tsx:43-56
Local Storage Keys and Schema
The application uses specific keys versioned with a .v1 suffix to prevent collisions and manage schema migrations.
| Feature | Local Storage Key | Data Type | Default Value |
|---|---|---|---|
| Active Tab | nexus-scanner.active-tab.v1 | string | "explore" |
| Screener Universe | nexus-scanner.screener.universe.v1 | UniverseType | "mainboard" |
| Match Mode | nexus-scanner.screener.match-mode.v1 | MatchMode | "all" |
| Active Conditions | nexus-scanner.screener.conditions.v1 | Record<string, ActiveCondition> | RVOL & SMA 50 |
| Text Query | nexus-scanner.screener.query.v1 | string | "" |
| Table Sorting | nexus-scanner.screener.sort.v1 | SortConfig | { field: 'rvol', direction: 'desc' } |
Sources: frontend/src/App.tsx:28, frontend/src/components/ExploreTab.tsx:43-56, frontend/README.md:434-436
Active Conditions Data Structure
The nexus-scanner.screener.conditions.v1 key stores an object mapping condition IDs to their specific parameter values.
// Example of a persisted condition state
{
"mom_rvol": {
"instanceId": "default_rvol",
"conditionId": "mom_rvol",
"parameters": { "minRvol": 1.5, "maxRvol": 20.0 }
},
"trend_price_vs_ma": {
"instanceId": "default_sma50",
"conditionId": "trend_price_vs_ma",
"parameters": { "maType": "SMA", "maPeriod": 50, "operator": "above", "thresholdPct": 0 }
}
}
Sources: frontend/src/components/ExploreTab.tsx:32-41, frontend/src/types/screener.ts
Implementation of useLocalStorageState
The useLocalStorageState hook provides a standardized way to manage persisted values. It handles JSON serialization and deserialization while providing a fallback to default values if the storage is empty or corrupted.
export function useLocalStorageState<T>(key: string, defaultValue: T): [T, (value: T | ((prev: T) => T)) => void] {
const [state, setState] = useState<T>(() => {
const saved = localStorage.getItem(key);
if (saved !== null) {
try { return JSON.parse(saved); } catch { /* ignore */ }
}
return defaultValue;
});
const setValue = useCallback((value: T | ((prev: T) => T)) => {
setState((prev) => {
const next = typeof value === 'function' ? (value as any)(prev) : value;
localStorage.setItem(key, JSON.stringify(next));
return next;
});
}, [key]);
return [state, setValue];
}
Sources: frontend/src/hooks/useLocalStorageState.ts:4-26
Runtime Cache Management
Beyond persistent local storage, the application maintains several runtime caches to optimize performance during a single session.
Cache Categories
- TanStack Query Cache: Manages request/result caching for API calls with a default stale time of five minutes.
- Worker Snapshots: The
snapshotEngineretains up to two loaded revisions in memory to facilitate fast switching between sessions. - IPO Snapshots: The
realAdaptermaintains a cache of up to three revision loads for the IPO catalogue. - Object Cache: Content-addressed data objects (such as charts or announcement summaries) are cached in a map limited to 32 entries.
The sequence diagram demonstrates the separation between persistence (LocalStorage) and session performance (Runtime Cache).
Sources: frontend/README.md:424-432, frontend/src/api/realAdapter.ts:56-70
Limitations
- No Named Screens: A named-screen library is not currently implemented; only the active workspace persists.
- Storage Clearing: All preferences are lost if browser site storage is cleared or if accessed from a different domain/port.
- No Cloud Sync: There is no account synchronization or IndexedDB implementation for larger datasets.
- Snapshot Validity: Persisted conditions may become invalid if the underlying scanner revision changes and the schema is no longer compatible.
Sources: frontend/README.md:126, frontend/README.md:438-440, frontend/README.md:444-446