Five-slice navigable map of the entire codebase under
docs/architecture-map/. Each slice is a self-contained
breadcrumbed sub-tree:
01-frontend (16) Svelte/SvelteKit UI
02-tauri-runtime (26) src-tauri commands + lifecycle
03-audio-transcription (16) audio + transcription crates
04-llm-formatting-mcp (19) llm, ai-formatting, mcp, cloud
05-core-storage-hotkey-build core, storage, hotkey, workspace,
(26) CI, dev glue
Plus master README.md and data-flow-end-to-end.md tracing
audio bytes from microphone to FTS5 search to MCP read.
Generated by 5 parallel subagents on 2026/05/09 against
HEAD 3c47000. Each page has YAML frontmatter, file:line code
refs, sibling cross-links, plain-English summaries.
Aggregated debt surfaced (full lists in master README):
RB-08 macOS power assertion, schema head drift v14 vs v15,
VAD blocked on ort version conflict, streaming primitives
not wired into live.rs, no prompt versioning, MCP has no
auth, cloud-providers in-memory keystore, SettingsPage
2 484 LOC, commands/live.rs 1 737 LOC, dual theme system,
brand rename to Lumenote pending across the codebase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.3 KiB
name, type, slice, last_verified
| name | type | slice | last_verified |
|---|---|---|---|
| Stores | architecture-map-page | 01-frontend | 2026/05/09 |
Stores
Where you are: Architecture map → Frontend → Stores
Plain English summary. Reactive state. Magnotia uses Svelte 5 runes ($state, $derived, $effect) instead of legacy stores. Each file under src/lib/stores/ exports one (or more) $state objects plus the helper functions that read or mutate them. Components import the state directly and Svelte tracks reactivity automatically. Two persistence channels: localStorage for settings, profiles, task lists, templates; Tauri (save_preferences) for accessibility preferences.
At a glance
- Path:
src/lib/stores/ - Files: 10 (4 085 LOC across stores + utils + types).
- Cross window sync:
localStoragestorageevent in the float window for settings.- Tauri
emit("magnotia:preferences-changed")for preferences (handled by every layout).
- Persistence keys:
magnotia_settings,magnotia_profiles,magnotia_task_lists,magnotia_templates,magnotia_locale, plus a viewer handoff key.
The stores
page.svelte.ts (697 LOC). The big one.
Owns:
page(PageState):current,status,statusColor,activeProfile,recording,timerText,handedness,taskSidebarOpen. Initial:current = "dictation".settings(SettingsState). Persisted tolocalStorage["magnotia_settings"]viautils/settingsMigrations.ts. Defaults at line 60 onward. Includes engine choice, model size, language, device, format mode, fillers, anti hallucination, British English, auto copy/paste, transcription preview, meeting auto capture (+ apps list), sound cues + volume, timestamps, theme, font size, AI tier, LLM model id and prompt preset, GPU concurrency, prewarm flag, save audio, output folder, global hotkey, sidebar collapsed, microphone device, energy state, match my energy, TTS voice + rate, rituals (morning/evening + time), launch at login, ritualsPromptSeen, nudges (enabled/muted/speakAloud), showMomentumSparkline.profiles,templates,taskListsarrays.tasksandhistoryarrays.
Helpers (selected, with line refs):
addToHistory→add_transcript(page.svelte.ts:234).mapTranscriptRow,saveTranscriptMeta→update_transcript(page.svelte.ts:272).deleteFromHistoryById→delete_transcript(page.svelte.ts:320).addTask,completeTask,uncompleteTask,deleteTask,setTaskEnergy,updateTask→ matching*_task_cmdRust commands.completeTaskand friends emitmagnotia:task-completed | -uncompleted | -deletedwindow events (line 470 onward).- Task lists:
addTaskList,renameTaskList,deleteTaskList,moveTaskList,sortTaskLists,moveTaskToList,moveTaskListToProfile. - Profile mutators:
addProfileTaskList,removeProfileTaskList. saveSettings,saveProfiles,saveTemplateswrite tolocalStorage.
preferences.svelte.ts (172 LOC).
Owns the Preferences shape: theme ("light" | "dark" | "system"), zone ("default" | ...), accessibility (fontFamily, fontSize, letterSpacing, lineHeight, transcriptSize, bionicReading, reduceMotion).
- DOM is the source of truth at runtime:
readFromDOM()reads<html>data attributes and CSS variables;applyToDOM(prefs)writes them. - Persists via
invoke("save_preferences", { preferences: JSON.stringify(prefs) })with a debounce. Failure shows a single toast per process (preferences.svelte.ts:101-120). - Cross window:
broadcastPreferencescallsemit("magnotia:preferences-changed", { source, prefs }). Receivers in+layout.svelteand the secondary+layout@.sveltefiles apply external prefs after a label check. - Exposes
getPreferences,updatePreferences,updateAccessibility,applyExternalPreferences,PREFERENCES_CHANGED_EVENTconstant. - Font families resolved from a constant map (Lexend, Atkinson, OpenDyslexic).
profiles.svelte.ts (123 LOC).
The vocabulary profile store (separate from the profiles array on page.svelte.ts). Holds:
activeProfileId, list of profiles, vocabulary terms.
Tauri commands: load_profiles_cmd (implicit on load), update_profile_cmd, delete_profile_cmd, delete_profile_term_cmd, plus add term commands.
Exposes DEFAULT_PROFILE_ID.
toasts.svelte.ts (99 LOC).
Toast notifications. State is an array of {id, severity, title, body, duration}.
Helpers: toasts.info(title, body?), .warn, .error, .success, plus dismiss(id). Auto dismiss via setTimeout. Read by ToastViewport.svelte.
llmStatus.svelte.ts (64 LOC).
Tracks the LLM lifecycle pill. State is one of idle | loading | generating | downloading | unavailable.
refreshLlmStatus(aiTier)callsget_llm_statusand updates the chip.markGenerating(),markGenerationDone()are called aroundcleanup_transcript_text_cmdinDictationPage.svelte.
completionStats.svelte.ts (59 LOC).
Phase 8 gamification. Owns recentCompletions (DailyCompletionCount[]) and a todayCount derivation.
Refresh triggers (no polling): module load, magnotia:task-completed, magnotia:step-completed, magnotia:task-uncompleted, magnotia:task-deleted, window focus (for midnight rollover).
focusTimer.svelte.ts (238 LOC).
Owns the floating focus timer. State: target ms, started at, label, taskId, paused.
setIntervalat 250 ms (TICK_INTERVAL_MS).- Triggered by
magnotia:start-timerwindow events. Emitsmagnotia:focus-timer-cancelledandmagnotia:focus-timer-completeon transitions.
implementationIntentions.svelte.ts (260 LOC).
"When X happens, do Y" rules engine. Owns the rules array.
- 30 second
setInterval(TIME_RULE_POLL_MS) checks time based rules. - On match, can route
page.current = "tasks"(lines 125, 136, 142) and calltts_speakif speak aloud is enabled (line 170). - Uses
delete_implementation_ruleto remove a rule (line 82). - Emits
magnotia:implementation-rules-changedafter writes. - Lifecycle:
startImplementationIntentions,stopImplementationIntentionsfrom+layout.svelte.
nudgeBus.svelte.ts (292 LOC).
Owns the nudge engine. Two setInterval handles:
blurCheckHandlefor window blur detection.triagePollHandleat 5 minute cadence checking morning triage triggers.- Plus a
microStepTimersMap for per task delayed notifications.
Key commands: deliver_nudge (line 112), tts_speak (line 119).
Emits magnotia:morning-triage-finished after the modal closes.
Lifecycle: startNudgeBus, stopNudgeBus from +layout.svelte.
speaker.svelte.ts (10 LOC).
Tiny. Holds speakingId so SpeakerButton instances can debounce / cancel each other. Candidate for collapsing into a util (README debt note 9).
Cross store traffic
DictationPage.completeRecording()→addToHistory(page) →add_transcriptRust → push to history.MicroSteps"start timer" button →magnotia:start-timer→focusTimerstore transitions →FocusTimercomponent renders ring.TasksPage.addTask→tasksstore → emitsmagnotia:task-completed/...→completionStatsrefreshes →CompletionSparklinere renders.SettingsPageaccessibility toggle →updatePreferences→ DOM write +save_preferencesinvoke +magnotia:preferences-changedemit → secondary windows mirror.- Float window settings sync uses
localStoragestorageevent, not the Tauri preference event. Drift candidate.
Watch outs
page.svelte.tsis doing a lot. Splitting transcripts, tasks, task lists, settings, profiles into separate stores would help but is outside this map's job.settingsandpreferencesoverlap (theme, font size,transcriptSize). Settings are localStorage only; preferences are Tauri persisted. Race possible during the migration$effect.nudgeBusandimplementationIntentionsboth run timers. They are torn down in+layout.svelteonDestroy. Only the main window starts them.completionStatslistens on the DOMwindowfor events; it does not subscribe totasksdirectly. Adding a new task mutation that does not emit one of themagnotia:task-*events will silently break the sparkline.
See also
- Components. Consumers.
- Frontend ↔ Tauri bridge. The
invokeandemitcalls per store. - Actions, utils, types.
settingsMigrations,errors,storage,time,osInfo,runtimehelpers used by stores.