State single source of truth
Generated 2026-10-05 from the code by scripts/state-ssot-doc.py (D-322d T-36, CHECKLIST 4.1). Rule: each piece of client state has one owner module, and components read and change it only through that owner.
Owners
| Concern | Owner module | Exports | localStorage keys | Importers |
|---|---|---|---|---|
| Screen-reader announcements | src/lib/core/state/a11yState.svelte.js | a11yState | none | 3 |
| Theme and app shell (sidebar, drawer) | src/lib/core/state/appState.svelte.js | AppState, appState | beetle-theme | 6 |
| Drag and drop | src/lib/core/state/dndState.svelte.js | dndState | none | 2 |
| Library filter panel | src/lib/core/state/filterPanelState.svelte.js | FilterPanelState, filterPanelState | none | 2 |
| Keyboard shortcuts | src/lib/core/state/shortcutState.svelte.js | shortcutState | beetle-settings, beetle-shortcuts | 2 |
| Toast notifications | src/lib/core/state/toastState.svelte.js | toastState | none | 13 |
| UI settings | src/lib/core/state/uiSettingsState.svelte.js | RATING_STYLES, HEART_COLORS, UiSettingsState, uiSettingsState | beetle-ui-settings | 2 |
| Library folders (sidebar) | src/lib/features/library/LibraryState.svelte.js | LibraryState | none | 1 |
| Playlists (sidebar and playlist pages, v2 API) | src/lib/features/playlists/PlaylistState.svelte.js | PlaylistState, setPlaylistState, getPlaylistState | none | 4 |
| Player queue and playback | src/lib/features/player/PlayerState.svelte.js | PlayerState, playerState | none | 3 |
Theme
appState.themeowns the theme.src/lib/features/settings/themeCatalog.jsvalidates it, and it persists underbeetle-theme, whichsrc/app.htmlreads before hydration to avoid a flash.- No second theme or UI-settings store is left: the legacy stores listed below are deleted.
- The per-theme text-contrast fixes in the generated block at the end of
src/lib/app.css(scripts/theme-contrast-audit.py) change colours only, not who owns the theme.
Direct localStorage access outside the owners
| File | Keys |
|---|---|
src/lib/features/player/EQControls.svelte | beetle-eq-settings |
src/lib/ui/feedback/ToastManager.svelte | beetle-settings |
src/lib/ui/layout/Sidebar.svelte | beetle-folder-sort |
src/routes/settings/+page.js | beetle-settings |
src/routes/settings/+page.svelte | beetle-settings |
Plan
- New client state goes into the owner of its concern, or into a new
*State.svelte.jsowner added to this table. Components do not calllocalStoragethemselves. - Each file in the direct-access table moves its keys into the owner of that concern the next time the file changes.
- Regenerate this page after state changes:
python3 scripts/state-ssot-doc.py.
Deleted legacy stores
src/lib/core/state/themeState.svelte.jssrc/lib/features/player/store.jssrc/lib/stores/playlistStore.jssrc/lib/stores/shortcutStore.jssrc/lib/stores/themeStore.js