This project uses Nix Flakes for reproducible development environments across Linux and macOS, with specialized shells for different GUI backends and components.
# Full development environment (all GUI backends)
nix develop
# Minimal CI environment
nix develop .#ci# Server components
nix develop .#server # Main server with SQLite, libclang
nix develop .#tunnel-server # Tunnel server (minimal)
# GTK-based applications
nix develop .#gtk-marketing-site # Marketing site
# Tauri applications (Linux uses GTK/WebKitGTK; macOS uses the system WebKit)
nix develop .#tauri-solidjs # Tauri with SolidJS/Astro frontend
nix develop .#tauri-hyperchad-vanilla-js # Tauri with HyperChad Vanilla JS frontend
nix develop .#tauri-solidjs-bundled # Tauri SolidJS with embedded server
nix develop .#tauri-hyperchad-vanilla-js-bundled # Tauri HyperChad Vanilla JS with embedded server
nix develop .#tauri-full # Full Tauri development (all backends)
# FLTK-based applications
nix develop .#fltk-renderer # FLTK renderer
nix develop .#fltk-hyperchad # Hyperchad FLTK interface
# Egui-based applications
nix develop .#egui-native # Native app with Vulkan/WGPU
nix develop .#egui-player # Egui music player
# Android development
nix develop .#android # Android SDK, NDK, Java, Gradlenix flake show- Graphics: GTK3, WebKit, GStreamer, Cairo, Pango
- Display: X11, Wayland support
- Audio: ALSA, PulseAudio, GStreamer plugins
- Use cases: Web-based UIs, traditional Linux desktop apps
- Graphics: FLTK, OpenGL, Mesa, Cairo
- Display: X11 (primarily)
- Audio: ALSA, PortAudio
- Use cases: Lightweight native GUIs, cross-platform compatibility
- Graphics: Vulkan, WGPU, OpenGL
- Display: X11, Wayland (Linux), Metal (macOS)
- Audio: ALSA, PortAudio, PipeWire
- Use cases: Modern GPU-accelerated interfaces, immediate mode GUIs
- SDK: Android SDK with API levels 33, 34
- NDK: Android NDK for native development
- Tools: ADB, Gradle, platform tools
- Java: OpenJDK 17 for Android builds
- Rust targets: Automatically installs Android Rust targets
- Use cases: Building Android apps with Tauri v2
- Rust toolchain (stable, with rust-analyzer, clippy, rustfmt)
- Build tools (cmake, ninja, pkg-config, gcc)
- Development tools (cargo-watch, cargo-edit, cargo-audit)
- GTK environments: WebKit, GStreamer, desktop integration
- FLTK environments: FLTK toolkit, OpenGL, minimal dependencies
- Egui environments: Vulkan validation layers, GPU drivers, WGPU
- Linux: Full support for all backends
- macOS: Automatic clang setup, Metal framework for Egui
# Work on server code
nix develop .#server --command cargo build -p moosicbox_server
# Work on FLTK interface
nix develop .#fltk-renderer --command cargo run --bin fltk_renderer
# Work on Tauri app with SolidJS
nix develop .#tauri-solidjs --command cargo tauri dev
# Work on Tauri app with HyperChad Vanilla JS
cd packages/app/tauri
nix develop ../../..#tauri-hyperchad-vanilla-js --command pnpm tauri dev \
--config src-tauri/tauri.hyperchad.conf.json \
--features desktop,client,moosicbox-app-native
cd ../../..
# Work on Android development
nix develop .#android --command bash -c 'cargo tauri android init && cargo tauri android build'Create .envrc files in specific packages:
# packages/server/.envrc
use flake ../..#server
# packages/app/tauri/.envrc
use flake ../../..#tauri-solidjsThen:
direnv allow
cd packages/server # Environment loads automatically- Version: Latest stable via rust-overlay
- Extensions: rust-src, rust-analyzer, clippy, rustfmt
- Consistency: Same version across all environments
- Linux: Automatic GUI backend library configuration
- macOS: Clang compiler, Metal/OpenGL framework setup
- Library paths: Automatically configured per backend
- GTK:
GDK_BACKEND=x11,wayland - Egui:
VK_ICD_FILENAMESfor Vulkan - macOS:
CC,CXXset to Nix clang
# Build specific components
nix develop .#server --command cargo build -p moosicbox_server
nix develop .#fltk-renderer --command cargo build -p hyperchad
# Run tests with appropriate environment
nix develop .#tauri-solidjs --command cargo test -p moosicbox_app
# Format code (any environment)
nix develop .#ci --command cargo fmt
# Lint code (any environment)
nix develop .#ci --command cargo clippyMoosicBox supports multiple database backends with some behavior differences to be aware of:
PostgreSQL enforces strict transaction semantics. When any error occurs within a transaction, the entire transaction enters an ABORTED state:
- No new operations allowed (including savepoint creation)
- Only ROLLBACK or ROLLBACK TO SAVEPOINT commands work
- Error message: "current transaction is aborted, commands ignored until end of transaction block"
// Create savepoint BEFORE risky operation
let sp = tx.savepoint("safety").await?;
match risky_operation(&tx).await {
Ok(result) => {
sp.release().await?; // Success - release savepoint
Ok(result)
}
Err(error) => {
sp.rollback().await?; // Must rollback to continue transaction
// Transaction is now viable again
handle_error(error)
}
}// Can create savepoint AFTER error occurs
let _error = risky_operation(&tx).await.unwrap_err();
let sp = tx.savepoint("recovery").await?; // Works in SQLite/MySQL
// Continue with recovery operations...Some tests are backend-specific due to these differences:
test_savepoint_after_failed_operation- Excluded from PostgreSQL test suites- Use
nix develop --command cargo test -p switchy_database --test savepoint_integrationto run backend-specific tests
Build MoosicBox as a Nix package:
# Build the complete package
nix build
# Run the built package
nix run# Update all flake inputs
nix flake update
# Update specific input
nix flake update rust-overlay# Clean Nix store
nix store gc
# Clean build outputs
cargo clean- GTK not loading: Check
GDK_BACKENDenvironment variable - FLTK compilation errors: Ensure OpenGL libraries are available
- Egui/Vulkan errors: Verify GPU drivers and Vulkan support
- Linux: Check ALSA/PulseAudio configuration
- macOS: Verify PortAudio/CoreAudio access
Add missing packages to the appropriate backend section in flake.nix:
gtkPackagesfor GTK backend dependenciesfltkPackagesfor FLTK backend dependencieseguiPackagesfor Egui backend dependencies
The development environment is organized around GUI backends to avoid dependency conflicts:
MoosicBox Project
├── Server Components (headless)
│ ├── server (SQLite, libclang, bindgen)
│ └── tunnel-server (minimal)
├── GTK Backend Apps
│ └── marketing-site (WebKit)
├── Tauri Apps (system webview)
│ ├── tauri-solidjs (SolidJS/Astro frontend)
│ ├── tauri-hyperchad-vanilla-js (generated HyperChad HTML/Vanilla JS frontend)
│ └── tauri-*-bundled (with embedded server)
├── FLTK Backend Apps
│ ├── renderer (OpenGL)
│ └── hyperchad (FLTK toolkit)
└── Egui Backend Apps
├── native (Vulkan/WGPU)
└── player (GPU-accelerated)
This separation ensures each backend gets exactly the dependencies it needs without conflicts or bloat.
