Shipping a Node.js server as a native desktop app with Tauri and Bun
Description and use
Building a cross‑platform desktop app for a Node server with Tauri and Bun: compile the server to a single executable, bundle it as a sidecar, configure static assets and download handling, and ensure proper process cleanup.
Problem
Users of a small Node.js LAN file‑transfer tool (MeghXL) needed a double‑clickable desktop app for macOS, Windows and Linux that hides the Node runtime.
Outcome
The resulting installers are 28–41 MB, launch a Tauri UI and a Bun‑compiled server, and run without requiring Node. The app handles static files, downloads, drag‑drop, and cleans up orphaned server processes.
Workflow
- 1. Choose Tauri for small bundle size and OS webview.
- 2. Configure Tauri’s
externalBinto include the compiled server binary. - 3. Compile the Node server to a single executable with
bun build --compile(cross‑compile per target). - 4. Ensure all dependencies are pure JavaScript (no
.nodebinaries). - 5. Name the binary
<name>-<triple>matching the Rust host triple. - 6. Ship static assets as Tauri resources and expose their path via an environment variable (
PUBLIC_DIR). - 7. Handle Tauri quirks: disable native drag‑drop, implement custom download handler, and tie sidecar lifecycle to parent via stdin EOF.
- 8. Build installers for macOS, Windows and Linux separately (Tauri cannot cross‑compile).
Evidence
Tauri resolves sidecars by target triple. The binary must be named <name>-<triple>
Bun won: bun build ./server.js --compile --target=bun-darwin-x64 --outfile meghxl-server-x86_64-apple-darwin
- Record date: 2026-09-15T17:00:10.192Z