Thanks for wanting to help. WaveFlow is a local music player built with Tauri 2 + React 19 + TypeScript on a Rust audio engine, using the bun toolchain. This file is the canonical contributing guide for the WaveFlow family β the satellite repos (server, Android, iOS) link back here and add their own specifics on top.
By participating you agree to the Code of Conduct.
bun install # dependencies
bun run tauri dev # run the desktop app (Vite + Rust backend)Frontend-only and backend-only loops:
bun run dev # Vite dev server, no Tauri shell
bun run typecheck # tsc --noEmit
bun run lint # eslint
cargo check --manifest-path src-tauri/Cargo.toml --workspace --all-targets
cargo test --manifest-path src-tauri/Cargo.toml --workspaceRun the check β CI runs the same commands, so save yourself a round-trip:
bun run typecheck
bun run lint
cargo fmt --manifest-path src-tauri/Cargo.toml --all
cargo clippy --manifest-path src-tauri/Cargo.toml --workspace --all-targets -- -D warnings
cargo check --manifest-path src-tauri/Cargo.toml --workspace --all-targetsIf you bump the pinned compiler, change rust-toolchain.toml and the
toolchain: input of every workflow that installs Rust, then run
python3 scripts/check-toolchain-pin.py β it is what CI runs, and it is
there because missing one of the six sites otherwise fails silently.
If you bump windows or windows-core in src-tauri/crates/app/Cargo.toml,
bump both, in one commit, and run
python3 scripts/check-windows-core-pair.py. The second is not an
independent dependency: it is named only so #[implement] can expand to
::windows_core:: paths, so it has to resolve to the same copy windows
itself was built against. Note that this is not the same as the same
version number β windows-rs numbers the two lines independently, and
windows 0.61.3 shipped against windows-core 0.61.2. The script walks
the lockfile rather than comparing strings, and prints both observed
versions when they part company.
rust-toolchain.toml decides which compiler those run under, so a local
answer and the CI answer are the same answer. Let rustup install it rather
than reaching for your default toolchain.
Expect Rust (ubuntu-latest) to take ~13 minutes whenever your branch
changes a Cargo.toml, Cargo.lock or rust-toolchain.toml, and ~7
otherwise. Swatinem/rust-cache hashes those files into its key and
matches it exactly β a stale Rust cache being worse than none β so
touching any of them is a full miss with no fallback to main's entry.
It is the expected cost of the change, not a broken cache.
If you touched a cross-cutting pattern (a context, the audio pipeline, a
migration, a sync wire shape), update the docs in the same PR β CLAUDE.md
and the relevant page under docs/features/ are the source of truth and are
expected to stay in sync with the code.
Conventional Commits are enforced
locally by a husky commit-msg hook (bunx commitlint). The rules that bite:
type(scope): subjectβ e.g.feat(player): gapless playback.- Scopes are kebab-case and mirror the areas in
.github/labeler.yml. - The subject stays lowercase β not sentence-case, start-case, or PascalCase.
- Header β€ 100 characters.
Examples:
feat(scanner): split multi-artist tags on "; "fix(audio): clamp buffers to unity before the ringperf(artwork): cache covers per album instead of per songdocs(playback): document the DoP idle-frame contract
- Keep a PR focused on one thing; smaller PRs get reviewed faster.
- The PR title also follows Conventional Commits β it drives the
type:label and, with the diff size, thesize:label. - Fill in the PR template: what changed, why, and how you tested it.
- Link issues with
Closes #123/Refs #456so they auto-close on merge.
UI copy ships in 17 locales (src/i18n/locales/<code>.json), with fr
as the source of truth and every locale carrying every key. When you add a key,
propagate it to all locales and leave brand tokens (WaveFlow, Deezer,
Last.fm, ReplayGain, BPMβ¦) and {{placeholder}} tokens untouched.
- Bugs and feature requests: use the issue templates.
- Security vulnerabilities: do not open a public issue β follow SECURITY.md.
WaveFlow is GPL-3.0-only. By submitting a pull request you agree that your contribution is licensed under those terms for inclusion in this repository.