KubeStellar Console uses a layered storage strategy to balance performance, durability, and developer ergonomics. The layers — from fastest to most durable — are sessionStorage, localStorage, IndexedDB, and SQLite WASM via OPFS.
| Layer | Scope | Survives Reload? | Survives Tab Close? | Purpose |
|---|---|---|---|---|
| sessionStorage | Single tab | Yes | No | Fast hydration snapshots for cache data |
| localStorage | Origin-wide | Yes | Yes | Settings, auth tokens, UI preferences, dashboard config |
| IndexedDB | Origin-wide | Yes | Yes | Fallback durable cache when SQLite WASM is unavailable |
| SQLite WASM (OPFS) | Origin-wide | Yes | Yes | Primary cache database — all I/O runs off-thread in a Web Worker |
localStorage is the primary store for user settings, authentication state,
and UI preferences. All keys are defined in a single constants file
(web/src/lib/constants/storage.ts)
so they can be audited and renamed from place.
Authentication
| Key | Description |
|---|---|
token | Session JWT returned by the backend after GitHub OAuth |
auth_token | Token used by the notification API |
Demo &
| Key | Description |
|---|---|
kc-demo-mode | Whether the console is in demo mode |
demo-user-onboarded | Whether the user completed |
demo-onboarding-responses | Saved survey answers |
Settings (synced to backend)
Settings stored in localStorage are synced to the kc-agent backend so
they survive cache clears. If localStorage is empty on load, the console
restores settings from the backend. See
usePersistedSettings.
| Key | Description |
|---|---|
kubestellar-theme-id | Active theme identifier |
kc-custom-themes | User-installed custom themes from the marketplace |
kubestellar-ai-mode | AI feature mode (off, assist, auto) |
kubestellar-prediction-settings | AI prediction configuration |
accessibility-settings | Accessibility preferences |
kc_notification_config | Notification settings |
kc-analytics-opt-out | Analytics opt-out flag |
Dashboard Persistence
| Key | Description |
|---|---|
kubestellar-main-dashboard-cards | Card layout and ordering for the main dashboard |
UI State
| Key | Description |
|---|---|
sidebar-left-pinned | Whether the sidebar is pinned open |
kubestellar-cluster-layout-mode | Cluster view layout (grid, list, etc.) |
kubestellar-nav-history | Navigation history for sidebar customization |
kubestellar-cluster-order | User-defined cluster sort order |
kubestellar-missions-active | Active AI Missions |
kubestellar-missions-history | AI Mission history |
Orbit Maintenance
| Key | Description |
|---|---|
kc-orbit-missions | Orbit mission configurations (type, cadence, auto-run, target clusters) |
kc-ground-control-dashboards | Mapping of Ground Control dashboards to orbit missions |
On the backend, orbit missions are also persisted to orbit_missions.json in the data directory, with a background scheduler that checks for auto-run missions every 60 seconds.
Engagement & Nudges
Keys such as kc-nudge-dismissed, kc-session-count, kc-visit-count,
and kc-nps-state track user engagement milestones (e.g., whether the
getting-started banner has been dismissed or when the NPS survey last appeared).
Component-specific Caches
Several hooks cache API responses in localStorage with a timestamp to
avoid redundant network requests. These follow the pattern of storing data
under a cache key (e.g., opa-statuses-cache) alongside a timestamp key
(e.g., opa-statuses-cache-time).
| Key Prefix | Data Cached |
|---|---|
opa-statuses-cache | OPA Gatekeeper policy status |
kc-kyverno-cache | Kyverno policy status |
kc-kubescape-cache | Kubescape scan results |
kc-trivy-cache | Trivy vulnerability scan results |
kc-rbac-cache | RBAC analysis results |
The main caching layer uses SQLite compiled to WebAssembly, running in
a dedicated Web Worker so all I/O stays off the main thread. This
architecture is documented in
web/src/lib/cache/index.ts
and
web/src/lib/cache/worker.ts.
main.tsx calls initCacheWorker() which spawns a Web Worker
that loads @sqlite.org/sqlite-wasm./kc-cache.sqlite3. OPFS provides true file-system
persistence inside the browser.CacheWorkerRpc)
that posts structured messages to the worker and awaits responses.Map so useCache() calls can check freshness with a
zero-cost Map.get() instead of an async round-trip.REFRESH_RATES in web/src/lib/cache/index.ts.const { data, isLoading, isRefreshing, refetch } = useCache({
key: 'pods',
fetcher: () => api.getPods(),
category: 'pods',
})
If OPFS is unavailable (e.g., non-secure context, unsupported browser),
the cache layer falls back to IndexedDB using a database named
kc_cache with a single object store named cache. The API surface is
identical — the fallback is transparent to consuming code.
To eliminate the skeleton-screen flash on page reload, the cache layer
writes a snapshot of each entry to sessionStorage under the prefix
kcc:. On the next page load (same tab), the snapshot is read
synchronously in the CacheStore constructor so components render
with data immediately — before the async SQLite worker finishes
initializing.
Snapshots include a version number so they are automatically discarded after deploys that change the cache schema.
sessionStorage is also used for chunk-load error recovery: if a code-split chunk fails to load, the console records a reload timestamp in sessionStorage to prevent infinite reload loops.
On first load, main.tsx runs a-time migration:
migrateFromLocalStorage): reads any
cache entries stored under the legacy kc_meta: prefix in localStorage
and moves them to IndexedDB.migrateIDBToSQLite): reads all entries from
the IndexedDB kc_cache store and inserts them into the SQLite database.A flag (kc-sqlite-migrated) is set in localStorage after migration
completes so it runs.
The console provides a “Clear Cache” action (available in Settings) that:
kcc: sessionStorage snapshots.| File | Purpose |
|---|---|
web/src/lib/constants/storage.ts | All localStorage key constants |
web/src/lib/cache/index.ts | Cache layer entry point, useCache hook, refresh rates |
web/src/lib/cache/worker.ts | SQLite WASM Web Worker |
web/src/lib/cache/workerRpc.ts | RPC layer between main thread and worker |
web/src/lib/cache/workerMessages.ts | TypeScript message types for worker communication |
web/src/hooks/usePersistedSettings.ts | Settings sync between localStorage and backend |
web/src/main.tsx | Cache worker init and migration orchestration |