SvelteKit frontend
The frontend lives in tauri/src/. It’s purely a view onto the backend state —
every file IO, subprocess call, and HTTP request lives in Rust, reached through
a single typed IPC wrapper.
Routes
Section titled “Routes”Under tauri/src/routes/:
+layout.svelte/+layout.ts— global chrome (frameless title bar, toast stack), dark-theme/density application, cross-window event subscriptions, navigation shell.+page.svelte— the main library window. PicksLibraryDesktop.svelteorLibraryTouch.sveltebased on the resolved UI mode, and renders theCloudConflictModalon a save conflict.add/+page.svelte— the Add Game flow (drop/browse an exe → ludusavi auto-identifies → ranked candidate list).edit/+page.svelte— the per-game editor (identity, install folder, launch settings, LAN sharing, cover refresh, remove).splash/+page.svelte— the full-screen Game-Mode launch splash showingrun:phaseprogress.settings/+page.svelte— application settings in a two-pane layout (Display, Library, Sharing & Sync). Live save on commit, no Save button.
Shared code
Section titled “Shared code”Under tauri/src/lib/:
api.ts— the single typed wrapper around Tauri’sinvokeIPC bridge. Every backend command is a method on the exportedapiobject. Components never callinvokedirectly. Also exportsassetUrl()for loading local files into the webview.types.ts— TypeScript mirrors of the Rust serde types (GameEntry,ConfigData,LanPeer, etc.). Keep these in sync with the Rust structs.uiMode.svelte.ts— single source of truth for UI density.auto | desktop | touchresolves todesktop | touch; auto-detection usesmatchMedia('(pointer: coarse)'). Writes<html data-mode>so CSS scales targets/spacing.components/— reusable Svelte components: primitives (Btn,Toggle,TextField, …), the two library layouts, the toast stack, the LAN transfer UI,GameDetail,CloudConflictModal, and more.toasts.svelte.ts/library.svelte.ts— global stores (Svelte 5 runes).format.ts/tokens.ts/nav.ts/updater.ts— display helpers, design tokens, navigation, and the updater wrapper.
UI modes
Section titled “UI modes”Spool adapts between a desktop layout (sidebar list + detail panel, child windows for Add/Edit/Settings) and a big-target touch layout (shelf of large tiles, overlays instead of child windows) for handhelds like the Steam Deck or ROG Ally. The UI is dark-only — there is no theme switcher.
Talking to the backend
Section titled “Talking to the backend”The frontend and backend communicate two ways:
- Commands — the frontend calls
api.someCommand(...), which invokes a Rust#[tauri::command]and awaits a typed result. - Events — the backend broadcasts colon-namespaced events
(
library:changed,run:phase,lan:peers-changed, …) viaAppHandle::emitto all open webviews.