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>
9.6 KiB
name, type, slice, last_verified
| name | type | slice | last_verified |
|---|---|---|---|
| Windows and SvelteKit routes | architecture-map-page | 01-frontend | 2026/05/09 |
Windows and routes
Where you are: Architecture map → Frontend → Windows and routes
Plain English summary. Magnotia is a single SvelteKit build that runs as multiple desktop windows. The Rust side opens four webviews (main, tasks float, transcript viewer, transcription preview) and points each one at a different SvelteKit route. The frontend uses SvelteKit's +layout@.svelte "break" trick so secondary windows skip the main shell (sidebar, titlebar, toast viewport) and render a focused, single purpose UI.
At a glance
- Path:
src/routes/ - LOC: 2 740 across the route tree.
- Key files:
src/routes/+layout.js:5. Disables SSR. Adapter isadapter-staticwithindex.htmlfallback (svelte.config.js:6). The whole tree is SPA only.src/routes/+layout.svelte. The shell. Sidebar, custom titlebar (non Linux only), toast viewport, focus timer overlay, morning triage modal, resize handles, global hotkey wiring, OS detection, profile load, first run gate, error capture.src/routes/+page.svelte. The main window's page switch (page.current→ 7 page modules).src/routes/float/+layout@.svelte. "Break" layout for the tasks float window.src/routes/float/+page.svelte. Tasks float window UI.src/routes/viewer/+layout@.svelte. Break layout for the transcript editor window.src/routes/viewer/+page.svelte. Transcript editor with audio playback.src/routes/preview/+layout@.svelte. Break layout for the live transcription preview overlay.src/routes/preview/+page.svelte. Preview state machine: listening → live → cleanup → final.
- Imports:
- Internal: every store, plus shell components (
Sidebar,TaskSidebar,Titlebar,ToastViewport,ResizeHandles,FocusTimer,MorningTriageModal). - External:
@tauri-apps/api/core(invoke, Channel, convertFileSrc),@tauri-apps/api/event(listen, emit),@tauri-apps/api/window(getCurrentWindow),@tauri-apps/plugin-global-shortcut,@tauri-apps/plugin-dialog,lucide-svelte.
- Internal: every store, plus shell components (
- Used by: Tauri (slice 02). Window labels are
main,tasks-float,transcript-viewer,transcription-preview. Each is created with the matching route URL.
What's in here
src/routes/+layout.js (5 LOC)
Single line: export const ssr = false;. Tauri has no Node server, so SvelteKit must run as a SPA.
src/routes/+layout.svelte (493 LOC)
The shell. Mounts on every window (the secondary windows then render only {@render children()} and suppress the chrome).
Responsibilities:
- Initialise svelte-i18n (
initI18n()is idempotent across windows,+layout.svelte:38). - Detect Tauri runtime (
hasTauriRuntime) and OS (loadOsInfo). Linux uses native KWin/Mutter decorations; macOS and Windows render the customTitlebarplus invisibleResizeHandles. DefaultuseCustomChrome = falseto avoid a flash on Linux (+layout.svelte:49). - Hotkey backend selection. On Wayland, attempt the evdev backend (
check_hotkey_access). Otherwise fall back totauri-plugin-global-shortcut. Falls back to "unavailable" if neither path works (+layout.svelte:76-102). - Hotkey registration. Only the
mainwindow owns the global shortcut. The function debounces evdev autorepeat at 120 ms (Handy issue #1143 referenced in comments,+layout.svelte:171-186). - Cross window listeners:
magnotia:hotkey-pressed(evdev path),magnotia:open-wind-down(tray menu),magnotia:preferences-changed(sync prefs across windows). Apply external preferences if the source label differs from our own. - Theme migration
$effect. Readssettings.theme(legacy "Light" / "Dark" / "System") and writespreferences.theme("light" / "dark" / "system"). See README debt note 2. - Font size CSS variable
--font-size-transcriptset on<body>fromsettings.fontSize. - Global error capture.
window.onerrorandunhandledrejectionforward tolog_frontend_errorRust command. Best effort, swallow throws. - First run check on mount. If
list_modelsandlist_parakeet_modelsboth return empty arrays, switchpage.currentto"first-run". - Background update check via
check_for_update. Toast on result. - Pre warm default model on mount if
settings.prewarmModelOnStartup(callsprewarm_default_model_cmd). - Meeting auto capture poller (
$effect). Whensettings.meetingAutoCaptureis true, pollsdetect_meeting_processesevery 15 s with the configured patterns (default["zoom", "teams"]). Edge triggered (toast only on first match per session). Tear down on effect re run. - Sidebar collapse heuristic.
[toggles, narrow viewport collapses automatically. - Render branches:
isSecondaryWindow(URL starts with/floator/viewer) renders only children. Otherwise: optional Titlebar, sidebar (hidden on first run), main slot, optional task sidebar (whenpage.taskSidebarOpen). - Always rendered alongside:
<ToastViewport />,<FocusTimer />,<MorningTriageModal />,<ResizeHandles />(custom chrome only).
src/routes/+page.svelte (33 LOC)
Pure dispatcher. Switches the seven page modules from page.current:
first-run→FirstRunPagedictation→DictationPagefiles→FilesPagetasks→TasksPagehistory→HistoryPagesettings→SettingsPageshutdown→ShutdownRitualPage
Also redirects the legacy page.current === "profiles" to "settings" via $effect (debt note 5).
src/routes/float/+layout@.svelte (99 LOC)
The @.svelte suffix tells SvelteKit to skip parent layouts. Reimports app.css, mounts Titlebar (non Linux) and FocusTimer, applies the same theme migration $effect, listens on the browser storage event (not Tauri events) to sync settings from main window writes, and handles the task-window-focus Tauri event to glow and auto focus the quick add input.
src/routes/float/+page.svelte (481 LOC)
Tasks float window. Self contained quick add, list filter, sort menu, completed toggle, list management (rename, delete, reorder, move to profile), drag and drop reordering. Reads tasks straight from the page.svelte.ts store helpers. No invoke() calls of its own; mutations go via addTask, completeTask, etc, which then call Rust.
src/routes/viewer/+layout@.svelte (77 LOC)
Same break layout pattern. Mounts Titlebar, ToastViewport, applies preferences sync via magnotia:preferences-changed, applies theme.
src/routes/viewer/+page.svelte (606 LOC)
Transcript editor. Hydrates from a transcript ID handed off via localStorage (magnotia:viewer-handoff style key, see file). Fetches the full row from SQLite via get_transcript. Renders an <audio> element using convertFileSrc() to map the saved audio path to a webview URL. Provides per segment editing, debounced autosave through saveTranscriptMeta, virtual scrolling via VirtualSegmentList, playback speed control (PLAYBACK_SPEEDS), starring and tagging.
src/routes/preview/+layout@.svelte (68 LOC)
Mounts only what the overlay needs: theme, preferences sync. No sidebar, no titlebar, no toast viewport.
src/routes/preview/+page.svelte (274 LOC)
Live transcription overlay. Listens for preview-listening, preview-cleanup, preview-hide (and reads partial text via the same Channel pattern as Dictation, in some flows). State machine: listening → live → cleanup → final → auto hide. Provides a copy button (uses navigator.clipboard.writeText first, falls back to copy_to_clipboard invoke) and a revert to raw button. Auto hide timer constants live at the top of the file.
Data flow
- Window creation: Rust opens four webviews and routes them to
/,/float,/viewer,/preview. The same JS bundle loads in each. - Cross window state:
localStoragecarriesmagnotia_settingsand the viewer handoff payload. Float window listens on the browserstorageevent to mirror settings.- Tauri events carry preferences (
magnotia:preferences-changed), tray driven navigation (magnotia:open-wind-down), and float window focus (task-window-focus).
- Hotkey: only the main window registers, but every window's layout includes the migration
$effect. The label guard at+layout.svelte:115-121prevents secondary windows from re registering. - First run gating: only the main window evaluates and sets
page.current = "first-run". The float/viewer/preview windows skip the shell altogether.
Watch outs
- The
useCustomChromeflash is mitigated by defaulting tofalseon Linux. If you ever flip the default, expect a one frame flash of custom chrome beforeloadOsInfo()resolves. - The break layouts duplicate the theme migration
$effect. Touch one, touch all. Same forapplyExternalPreferenceslisteners. transcription-previewis a borderless overlay withWindowTypeHint = Utility. Layout assumptions about chrome height do not apply.+layout.sveltecallsapplyExternalPreferencesonly after a payloadsourcecheck. If you ever add a fifth window, its label must be propagated correctly or the window will echo its own preference writes.- Drag drop on
FilesPage.sveltelistens ontauri://drag-dropevents, which require the window to declare drag drop intauri.conf.json. Slice 02 owns that surface.
See also
- Pages overview. What
page.currentends up rendering. - Frontend ↔ Tauri bridge. Every command and event referenced above.
- App shell and styling. The CSS plumbing that the shell relies on.
- ../02-tauri-runtime/README.md. Window creation, tray, and the matching event surface.