Build & release
How VoiceFlow is compiled and packaged — Electron Forge with Vite for the app, Cargo for the native listener, and a GitHub Action for signed DMG releases.
Bundler
Electron Forge + Vite
Native
Cargo release build
Output
DMG + ZIP (darwin)
Toolchain
Electron Forge + Vite
The Forge Vite plugin builds four bundles: main, preload, and two renderers (main_window and overlay_window).
Cargo
The Rust key listener is compiled to a release binary for the target triple and copied into resources/binaries.
TypeScript
Typecheck with tsc --noEmit; the CI runs this before building distributables.
Makers
maker-zip and maker-dmg (ULFO format) produce the darwin artifacts.
Build scripts
npm start # build native listener, then electron-forge start
npm run package # build native listener, then forge package
npm run make # build native listener, then forge make (DMG + ZIP)
npm run lint
npm run typecheckEvery run first invokes build:native:key-listener, which shells out to Cargo:
cargo build --release \
--manifest-path native/global-key-listener/Cargo.toml \
--target aarch64-apple-darwin # or x86_64-* / windows
# then the compiled binary is copied to resources/binaries/TARGET_ARCH
Packaging
- asar: true packs the app; the native binary and assets ship as extraResourceso they're reachable at runtime.
- In a packaged build the listener is resolved from process.resourcesPath/binaries; in dev it's read from the Cargo target directory.
- The worklet and other renderer assets are bundled by Vite; the audio worklet in particular is inlined to survive asar packaging.
Release automation
A GitHub Action builds and publishes the DMG when a v* tag is pushed (or on manual dispatch):
- 01Set up Node & RustNode 20 with npm cache, plus the aarch64-apple-darwin Rust target on a macOS runner.
- 02Install & typechecknpm ci, then npm run typecheck as a gate.
- 03Build the native binary & makeBuild the key listener, then electron-forge make --arch=arm64.
- 04Publish the DMGThe produced .dmg from out/make is attached to the GitHub release.