Skip to content

Architecture

SpinDeck is a SPA frontend plus desktop-only Rust capabilities (Tauri invoke + cover://). The UI never talks to a remote SpinDeck backend; playlist import and local playback control run inside the desktop app process.

mermaid
flowchart LR
  subgraph webApp ["apps/web SPA"]
    UI[React Router UI]
    PlayerPkg["@spindeck/player client"]
  end
  subgraph desktopApp ["apps/desktop Tauri"]
    Invoke["Tauri invoke"]
    Cover["cover:// protocol"]
    Playlist[playlist providers]
    Playback[playback control]
  end
  UI -->|"invoke"| Invoke
  UI -->|"img / canvas"| Cover
  PlayerPkg --> UI
  Invoke --> Playlist
  Invoke --> Playback

Runtime model

ModeWhat runsNotes
Browser / web-onlyVite SPAUI preview. Playlist import / local playback need the desktop app
Desktop (recommended)Tauri + native WebViewSPA via frontendDist; features via invoke. No Node.js on the user’s machine

Monorepo layout

PathRole
apps/webSPA (React Router, ssr: false). Calls desktop features via invoke
apps/desktop / src-tauriTauri shell + Rust (app/, commands/, cover, playlist/, playback/, util/)
packages/playerClient playback strategy, deep links, session (setDesktopBridge)
packages/vinyl-ui / ui / pickerShared UI and cover color helpers
docsVitePress documentation

Playlist import used to live in a TypeScript @spindeck/core package; that logic now lives in Rust under apps/desktop/src-tauri/src/playlist/.

Desktop IPC

CommandPurpose
import_playlistImport / refresh playlist
play_songStart playback in the local music app
pause_songPause / stop
resume_songResume
playback_statusQuery local client playback state
set_play_modeSet play mode when supported

Cover art is proxied through the custom protocol cover://localhost/?url=... (on Windows: http://cover.localhost/?url=...) with Referer headers and size limits.

Frontend notes

  • Playlist metadata stays in browser localStorage; song lists are fetched through import_playlist.
  • In browse mode the 3D shelf mounts meshes/covers in a scroll viewport window; after playback settle it unloads other books and keeps only the selected cover. See Performance & Visuals for the full policy.
  • Empty slots show a loading state until song metadata and covers are ready.
  • @spindeck/player is a browser client — the desktop app wires Tauri via setDesktopBridge; critical logs can land in the desktop session log (see Desktop App).

Contributors

Changelog

Released under the Apache License 2.0.