Building from Source
Requirements, development mode, builds, tests, packaging, cross-compilation, and common build failures.
Requirements
- Node.js 24 and npm
- Python (required by
node-gyp) - A C++17 toolchain supported by
node-gyp
Platform toolchains:
| Platform | Toolchain |
|---|---|
| Linux | build-essential, python3 |
| macOS | Xcode Command Line Tools |
| Windows | Visual Studio Build Tools with the C++ workload |
For Orchard Mobile you additionally need JDK 17 and Android SDK 36.
Clone and install
git clone https://github.com/SFG5453/Orchard.git
cd Orchard
npm ci
Use npm ci rather than npm install so you get the locked dependency tree.
Development
npm run dev
This builds the native audio analyzer, starts Vite on 127.0.0.1:5173, and launches
Electron against the dev server. The two run concurrently and both stop together.
DevTools are available in non-packaged builds.
Build
npm run build
Runs build:native then build:frontend. To build only one half:
npm run build:native # N-API audio analyzer only
npm run build:frontend # Vue renderer only
Run the locally built app:
npm run start
Tests
npm test
Runs the whole suite with Node’s built-in test runner (node --test test/*.test.js).
The audio-specific subset, useful while working on the analysis or transition pipeline:
npm run test:native
That covers nativeAudioAnalysis, audioAnalysisService, smartCrossfadeAnalysis,
queueTransitionSort, transitionPlanner, crossfadeMixer, autoCrossfade,
subscribedArtists, and libraryCategory.
Packaging
| Command | Result |
|---|---|
npm run package | Unpacked Electron application directory |
npm run make | Distributable packages for the current platform |
npm run package:linux-system | Package against a system Electron on Linux |
npm run make:mac | Cross-build a universal macOS ZIP from Linux |
Packaging is configured in electron-builder.config.cjs.
Cross-compiling the native addon
npm run build:native:windows # Windows addon from Linux
npm run build:native:macos:cross # macOS addon from Linux
These back the cross-build scripts in scripts/.
Models
The beat-tracking model is fetched rather than committed:
npm run fetch:beat-model
See mobile/docs/BEAT_MODEL.md for details on the model and its quantization.
Artist packs
npm run build:artist-pack
Builds the official artist pack from workers/artist-packs/content/. See
Artist Packs.
Workers
Each worker in workers/ is a separate npm project with its own wrangler.jsonc, secrets,
and deploy command. See Cloudflare Workers.
Mobile
cd mobile/android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
Tests and lint:
./gradlew testDebugUnitTest assembleDebug lintDebug
Common build problems
node-gyp fails immediately. Almost always a missing Python or C++ toolchain. Confirm
python3 --version and that a compiler is on PATH.
Native addon builds but does not load. Check that the addon architecture matches your Node and Electron architecture. Release CI includes an explicit architecture-verification step for arm64 Linux builds for exactly this reason.
Vite starts but Electron shows a blank window. The dev launcher waits on
http://127.0.0.1:5173. If something else holds that port, the launcher attaches to the
wrong server.
Tests pass locally but fail in CI. CI runs on Node 24 with a clean npm ci tree.
Reproduce with rm -rf node_modules && npm ci.
Architecture
How the Vue renderer, Electron main process, native addon, and edge services fit together, and why there are two channels into the main process.
Native Audio Analyzer
The N-API addon: exported functions, every field analysis returns, model child processes, and the vendored Rubber Band build.