---
name: Frontend slice (Svelte 5 + SvelteKit + Tauri webview)
type: architecture-map-slice-index
slice: 01-frontend
last_verified: 2026/05/09
---

# Frontend (Slice 01)

> **Where you are:** [Architecture map](../README.md) → Frontend

**Plain English summary.** This slice is everything the user sees. It is a Svelte 5 single page app, served by SvelteKit in SPA mode, hosted inside Tauri's webview. It owns four windows (main, tasks float, transcript viewer, transcription preview overlay), seven page modules switched by an in memory router store, around thirty reusable components, ten reactive stores, and the design system tokens. The frontend never touches the filesystem, audio, models or the LLM directly. Everything that crosses the WebView boundary goes through `invoke()` (calling Rust commands) or Tauri events. If you delete this slice, you delete the entire user surface but keep the engine.

## At a glance

- **Path:** `src/`
- **Total LOC counted:** about 17 200 (583 `app.css` + 2 740 routes + 6 230 pages + 3 174 components + 4 085 stores/utils/types + ~ 2 360 design system + 130 misc).
- **File counts:** 7 pages, 25 components, 10 stores, 1 action, 16 utils, 1 type module, 3 locales, 4 routes (root + float/viewer/preview), 20 design system preview HTMLs, 3 design system JSX kits.
- **Frameworks:** Svelte 5 (runes mode), SvelteKit 2.58, `@sveltejs/adapter-static` with `index.html` fallback (SPA), Vite 6, Tailwind v4 via `@tailwindcss/vite`, svelte-i18n 4, lucide-svelte for icons.
- **Tauri SDK touchpoints:** `@tauri-apps/api` (core invoke, event, window) plus `plugin-autostart`, `plugin-dialog`, `plugin-global-shortcut`, `plugin-notification`, `plugin-opener`. SSR is disabled (`src/routes/+layout.js`) so the whole tree is client side only.
- **Persistence used directly by frontend:** `localStorage` for `lumotia_settings`, `lumotia_profiles`, `lumotia_task_lists`, `lumotia_templates`, `lumotia_locale`, plus a small handoff key for the viewer window. Preferences additionally persist via Tauri (`save_preferences`).
- **Build commands:** `npm run dev` (`svelte-kit sync && vite dev`), `npm run build`, `npm run check` (svelte-check using `jsconfig.json`).

## Map of this slice

- [Windows and routes](windows-and-routes.md). The four Tauri windows, the SvelteKit routes that back them, the `+layout@.svelte` break, and how the shell decides between custom chrome and native decorations.
- [Pages overview](pages-overview.md). Index of the seven pages routed by `page.current`, and the `/float`, `/viewer`, `/preview` route pages.
- [Pages: dictation](pages/dictation.md). The hero recording surface.
- [Pages: settings](pages/settings.md). The 2 484 line settings panel.
- [Pages: history](pages/history.md). FTS5 backed transcript browser.
- [Pages: tasks](pages/tasks.md). Inbox, today, soon, later board.
- [Pages: files](pages/files.md). Drag and drop file transcription.
- [Pages: first run](pages/first-run.md). Hardware probe and model bootstrap.
- [Components](components.md). All 25 reusable components grouped by role.
- [Stores](stores.md). Ten Svelte 5 `$state` stores, plus what each owns and what events they react to.
- [Actions, utils, types](actions-utils-types.md). The single Svelte action, the 16 utility modules, and the `app.ts` type bible.
- [Internationalisation](i18n.md). svelte-i18n setup, locale persistence, current coverage.
- [Design system](design-system.md). Reference material under `src/design-system/` (preview HTML, JSX UI kits). Note: this is reference, not live code.
- [Frontend ↔ Tauri bridge](frontend-tauri-bridge.md). Every `invoke()` command name and every event listened for or emitted, with their callers.
- [App shell and styling](app-shell-and-styling.md). `app.css`, `app.html`, fonts, Tailwind v4 configuration, accessibility CSS variables.

## How this slice connects to others

**In (frontend depends on Tauri runtime, slice 02).**

- Sixty plus distinct `invoke()` commands. Full list with caller in [frontend-tauri-bridge.md](frontend-tauri-bridge.md).
- Tauri events listened to: `model-download-progress`, `parakeet-download-progress`, `lumotia:llm-download-progress`, `lumotia:hotkey-pressed`, `lumotia:open-wind-down`, `lumotia:preferences-changed`, `task-window-focus`, `preview-listening`, `preview-cleanup`, `preview-hide`, plus drag drop (`tauri://drag-drop`, `tauri://drag-enter`, `tauri://drag-leave`).
- Window APIs: `getCurrentWindow().minimize() / toggleMaximize() / setPosition() / label`.
- Plugin imports loaded lazily: `@tauri-apps/plugin-global-shortcut`, `@tauri-apps/plugin-dialog`.

**Out (frontend triggers behaviour back into the runtime).**

- DOM `CustomEvent` bus on `window` carries internal traffic (`lumotia:start-timer`, `lumotia:toggle-recording`, `lumotia:task-completed`, etc). The Rust side does not listen to these; they are intra frontend.
- Tauri `emit()` is used for `lumotia:preferences-changed` only, to fan preference updates across windows.
- Multi window orchestration: pages call `open_task_window`, `open_viewer_window`, `open_preview_window` to ask Rust to spawn secondary webviews.

**Other slices that read frontend conventions.**

- Slice 02 (Tauri runtime) emits the events listed above and registers commands the frontend invokes.
- Slice 03 (audio + transcription) ships partial results via a `Channel` (Tauri 2 typed channel) opened in `DictationPage`.
- Slice 04 (LLM, formatting, MCP) emits `lumotia:llm-download-progress` and `cleanup_transcript_text_cmd` results consumed by Dictation.
- Slice 05 (storage, hotkey, build) supplies `add_transcript`, `delete_transcript`, profiles, tasks and the evdev hotkey backend.

## Existing in repo docs (do not duplicate)

- `docs/brief/` and `docs/whisper-ecosystem/brief.md`. Product brief and feature set.
- `docs/icon-mapping.md`. Lucide icon migration audit.
- `docs/code-review-2026-04-22.md`. Last code review snapshot.
- `docs/handovers/`. Ship logs (e.g. Phase 9c is the most recent settings related one).
- `docs/audit/`. UX and accessibility audits.
- `docs/superpowers/`. Process artefacts.
- `src/design-system/README.md`, `src/design-system/SKILL.md`. Brand and design ground truth.

This slice index is the navigation hub. The map files referenced above carry the detail.

## Open questions, debt, drift, dead code

1. **`src/lib/Sidebar.svelte` lives outside `components/`.** Every other reusable Svelte module is under `src/lib/components/`. The sidebar is the only sibling of those folders. Cosmetic but it surprises contributors.
2. **Two parallel theme systems.** `settings.theme` (string `"Light"`/`"Dark"`/`"System"`) coexists with `preferences.theme` (`"light"`/`"dark"`/`"system"`). `+layout.svelte:61-68` and `float/+layout@.svelte` both run a "legacy → new" migration `$effect` every time. The legacy pathway should be retired.
3. **`@ts-nocheck` is widespread.** `+layout.svelte`, `DictationPage.svelte`, `FilesPage.svelte`, `FirstRunPage.svelte` and the float/viewer/preview layouts all opt out of TypeScript. Type safety stops at the page boundary.
4. **`SettingsPage.svelte` is 2 484 lines.** Phase 9c handover already flagged this. `SettingsGroup.svelte` exists but the deeper restructure into seven progressive disclosure groups plus search has been deferred.
5. **`profiles` redirect is a dead route.** `+page.svelte:13` still rewrites `page.current === "profiles"` to `"settings"`, suggesting the old profiles page was removed but call sites may persist. Worth grepping and deleting the redirect after a release.
6. **Cross window settings sync uses `localStorage` `storage` events.** `float/+layout@.svelte` listens for `storage` to apply settings, while preferences use the dedicated `lumotia:preferences-changed` Tauri event. Inconsistent. Settings sync via `storage` is fragile because it only fires on cross document writes.
7. **`shims.d.ts` next to the lib root.** Single shim file at `src/lib/shims.d.ts`. Worth verifying it is still needed (Svelte 5 + SvelteKit ship most ambient types now).
8. **`design-system/ui_kits/`** contains JSX components and an HTML index. They are reference, not live, and should not import from the runtime tree. Confirm the build excludes them.
9. **`speaker.svelte.ts` is ten lines.** A near empty store. Used by `SpeakerButton.svelte`. Consider folding into a util if it never grows.
10. **CSS variable `--font-size-transcript` is set on `body` from `+layout.svelte` but `preferences` already sets `--font-size-body` and `--transcript-font-size`.** Three knobs for transcript text size in different stores. Drift between `settings.fontSize` and `preferences.accessibility.transcriptSize` is likely.
11. **i18n coverage is thin.** Each locale has 19 lines. svelte-i18n is wired but most strings remain hardcoded. Treat as a stub.
12. **Tailwind v4 has no standalone config file.** All theming lives in `app.css` `@theme`. There is no `tailwind.config.{js,ts}`. Mention this so contributors do not waste time looking.
13. **`docs/architecture-map/01-frontend/` was empty before this pass.** Reciprocal slice indexes (02 to 05) need updating to point here.
