Skip to content
Rymflux Documentation
Esc
navigateopen⌘Jpreview
On this page

Dev environment — Rymflux v2

Dev environment — Rymflux v2

Status

Draft v1 — 2026-07-31

Purpose

This document is the setup and day-to-day reference for developers working on the Rymflux v2 desktop app. It covers the repository layout (the Cargo workspace plus the SvelteKit frontend), the toolchain and version floor, one-time bootstrap, the everyday run / lint / test / build commands, and the environment variables and on-disk paths the app reads and writes.

It is how you get code running. It is deliberately not about how the app is engineered — runtime model, layer rules, the IPC bridge, and the state layer are owned by frontend-architecture.md; the backend services are described in container-diagram.md; user data and logging conventions are in cross-cutting-concerns.md.

Repository layout

rymflux/
├── Cargo.toml                   # virtual workspace manifest (edition 2024, resolver "3")
├── Cargo.lock                   # one lockfile for the whole workspace
├── crates/                      # Rust workspace members (container-diagram services)
│   ├── contracts/               # serde types mirroring api-specs/data-models.md (snake_case)
│   ├── plugin-runtime/          # JSON-RPC plugin supervision (ADR-001, ADR-011)
│   ├── search-manager/          # parallel search dispatch + merge (ADR-007)
│   ├── playback-engine/         # phonic (symphonia + rubato + cpal) (ADR-004)
│   └── library-service/         # rusqlite; favorites, playlists, history, resolution (ADR-002)
├── src-tauri/                   # Tauri app crate (the single binary; wires the crates)
│   ├── src/                     # command/event handlers, managed state, migrations runner
│   ├── migrations/              # SQL migrations (001_*.sql …)
│   └── tauri.conf.json          # CSP, window, build.frontendDist / devUrl
├── components.json              # shadcn-svelte contract (ui alias → src/lib/ui)
├── vitest.config.ts             # Vitest node + browser projects (testing/strategy.md)
├── svelte.config.js             # adapter-static SPA + aliases
├── vite.config.ts               # sveltekit(), strictPort
├── package.json
├── tsconfig.json
├── eslint.config.js
├── .prettierrc
├── README.md
└── src/                         # SvelteKit frontend (see frontend-architecture.md §2)

Docs-as-Code: this doc and the rest of the docs scaffold live in the sibling rymflux-v2/ repository, not in the code repo shown above.

Cargo workspace

The backend is a single Rust process (container-diagram.md). The workspace expresses that as one binary crate (src-tauri) that depends on a set of library crates under crates/. This preserves the documented single-process design while keeping each service unit-testable in isolation — the crates are logical modules, not separate deployable units.

  • The root Cargo.toml is a virtual manifest (no [package]): it declares only [workspace], [workspace.dependencies], and resolver = "3".
  • edition = "2024" (requires Rust 1.85+; see Toolchain). resolver = "3" is the edition 2024 default and is spelled out explicitly.
  • Shared dependencies are pinned once in [workspace.dependencies] and referenced from each member crate so versions never drift. The full inventory is the dependency manifest below.
  • There is one Cargo.lock and one shared target/ at the workspace root; the crates/ layout is flat (single level) — no nested workspace crates.
  • src-tauri is the only [[bin]]. Library crates declare no binaries.

Dependency manifest

Every crate in [workspace.dependencies], its role, and where the requirement comes from. Versions are the v1 reference pins — proven by the previous incarnation’s Cargo.toml — and are provenance only: re-verify all of them when the workspace is first scaffolded; nothing below is asserted as current.

Crate Type Purpose Primary consumer Source
tauri (^2) runtime App shell, IPC, events, windowing src-tauri frontend-architecture.md §1.1
serde (derive) runtime Strict-type JSON-RPC parsing + data-models.md mirror contracts, all services data-models.md, cross-cutting-concerns.md
serde_json (1.0) runtime JSON-RPC 2.0 wire format plugin-runtime, search-manager v1 provenance
toml runtime config.toml + plugin.toml manifest parsing plugin-runtime cross-cutting-concerns.md, ADR-011
tokio runtime Async runtime — io, select!, timeouts, sync::mpsc all services container-diagram.md
uuid runtime UUIDv4 content IDs library-service, contracts ADR-003
phonic (0.16, cpal-output, default-features off) runtime Audio engine — wraps symphonia + rubato + cpal playback-engine container-diagram.md, ADR-004
rusqlite (0.39, bundled) runtime Library storage; migrations via pragma user_version library-service ADR-002
reqwest (0.13, blocking + rustls, default-features off) runtime Fetch stream URLs (URL-only streaming) playback-engine ADR-006
tracing runtime Structured logging all services cross-cutting-concerns.md
tracing-subscriber (0.3, env-filter, registry) runtime Log output to app.log/stdout; implements RUST_LOG src-tauri cross-cutting-concerns.md; v1 provenance
thiserror (2.0) runtime Typed three-tier error model all services cross-cutting-concerns.md; v1 provenance
chrono (0.4, serde) runtime ISO 8601 timestamps, added_at library-service, logging cross-cutting-concerns.md; v1 provenance
image (0.25) runtime ADR-016 dominant color — decode + 1×1 resize + oklch average library-service ADR-016; v1 provenance
tempfile (3.27) dev Temp database for Rust integration tests src-tauri tests testing/strategy.md; v1 provenance
phonic wav-output dev Audio test fixtures (render to wav for assertions) playback-engine tests v1 provenance

Superseded v1 crates — do not re-add: blake3 and sha2 (v1 content addressing / cache keys — superseded by UUIDv4, ADR-003) and crossbeam-channel (superseded by tokio::sync::mpsc, container-diagram.md). v1’s reqwest download-to-cache flow (archive.org / LibriVox) is dead: in v2, reqwest serves URL streaming only (ADR-006), never a local cache.

Tooling (cargo subcommands, not dependencies): cargo llvm-cov (coverage), cargo-audit (security scan) — see testing/strategy.md.

Toolchain

Tool Version floor Notes
Rust stable 1.85+ edition = "2024" needs 1.85. Backend MSRV floor is 1.77 (Tauri 2.9.x); the repo uses the latest stable — no pinning below stable unless CI requires it.
rustup components rustfmt, clippy, rust-analyzer Installed once; required for the fmt/lint gates.
Node 20 LTS+ (22/24 LTS fine) Tauri v2 requirement.
pnpm current Package manager (ui-design-system.md pins pnpm add); enable via corepack or install directly.
Tauri CLI v2 (^2) Use @tauri-apps/cli as a dev dependency and run pnpm tauri … so the CLI version matches the app’s Tauri version.
SvelteKit / Svelte SvelteKit 2.x, Svelte 5 SPA mode via adapter-static (frontend-architecture.md §1.1).
Tailwind v4 @tailwindcss/vite, tw-animate-css; config lives in CSS (@theme, @custom-variant dark), no tailwind.config.
shadcn-svelte latest (Tailwind v4 support) Style: Rhea (compact Luma). Init sets components.json aliases so components land in src/lib/ui/.

System dependencies (one-time, per platform)

Linux (apt-based):

sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file \
  libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev

macOS: xcode-select --install only — the webview (WKWebView) and windowing toolkit are part of the OS.

Windows: Visual Studio Build Tools (Desktop development with C++) and the WebView2 runtime (preinstalled on current Windows 10/11).

Bootstrap

# 1. Rust toolchain + components
rustup toolchain install stable && rustup component add rustfmt clippy rust-analyzer

# 2. Node + pnpm (once)
corepack enable            # or: npm install -g pnpm

# 3. Frontend dependencies
pnpm install

# 4. shadcn-svelte (Rhea), with the ui alias pointing at src/lib/ui
pnpm dlx shadcn-svelte@latest init
#   → confirms components.json aliases: ui → src/lib/ui

# 5. First Rust compile (slow — fetches and builds the dependency tree)
cargo build --workspace

The first cargo build is the only long step; after it the incremental build and pnpm tauri dev are fast.

Day-to-day commands

Command Purpose
pnpm tauri dev Full app: builds the workspace, boots the Rust process, serves the SvelteKit app with HMR on the Vite dev server (port 1420, strictPort).
pnpm dev Frontend-only Vite dev server. No IPC backend — usable for markup/state work only where the ipc/ bridge is mocked (see strategy.md).
pnpm build Production SvelteKit build (SPA bundle into build/).
pnpm tauri build Release bundle (frontend build + optimized Rust + platform installer).
pnpm check svelte-check — type-checks Svelte components, routes, and the .svelte.ts state layer. Run before pushing.
pnpm lint / pnpm format ESLint / Prettier (configs at repo root).
pnpm test Frontend tests: Vitest node project (state layer) + browser project (component/integration, chromium) — see strategy.md.
cargo test --workspace All Rust unit + integration tests across crates/ and src-tauri.
cargo clippy --workspace --all-targets Rust lint gate (deny-warnings in CI).
cargo fmt --check Rust format gate.

Configuration & environment

Setting Where Notes
CSP src-tauri/tauri.conf.jsonapp.security.csp Set once; allows self and ipc:. No separate web CSP (frontend-architecture.md §1.1).
app.withGlobalTauri src-tauri/tauri.conf.json false; the frontend imports @tauri-apps/api explicitly through the ipc/ bridge.
frontendDist / devUrl src-tauri/tauri.conf.json ../build and the Vite dev server respectively.
RUST_LOG shell RUST_LOG=rymflux=debug pnpm tauri dev for full backend debug logs on stdout (cross-cutting-concerns.md §Logging).
App data ~/.rymflux/ config.toml, data/library.db, logs/app.log + logs/plugins/<id>.log, plugins/, crash-reports/. macOS-first v1; XDG directories considered for later (cross-cutting-concerns.md).

Debugging notes

  • Backend: RUST_LOG=rymflux=debug is the primary diagnostic; every JSON-RPC message, Tauri command invocation, and SQL query is logged at debug (cross-cutting-concerns.md).
  • Frontend: the webview console is supplementary. Logs carry the same contextual fields (content_id, plugin_id, query) as the backend so logs/app.log and the console tell one story.
  • Plugin problems: per-plugin stderr is captured to ~/.rymflux/logs/plugins/<plugin_id>.log (ADR-001).
  • Crashes: std::panic::set_hook writes a report to ~/.rymflux/crash-reports/ and shows a non-blocking dialog.
  • First-launch hydration follows first-time-setup.md — if the UI hangs on the loading gate, the platform_ready event has not arrived; check the backend log first.
  • pnpm tauri dev on a stale browser-mode cache can surface as weird DOM failures in tests — see strategy.md for the chromium install / flushSync() notes.

Platform notes

  • Linux: requires webkit2gtk-4.1 (not the older 4.0); a missing system dep shows up at cargo build / first pnpm tauri dev.
  • macOS: no extra webview deps; code-signing/notarization are out of scope for local dev. E2E later uses the tauri-wd automation server (strategy.md).
  • Windows: WebView2 runtime is preinstalled on current builds; the E2E WebDriver path (tauri-driver) is the same as Linux.

Was this page helpful?