Skip to content

Building and Packaging

Franciszek Ryszka edited this page Jul 24, 2026 · 2 revisions

Building and Packaging

Web app

pnpm build   # -> .next/
pnpm start   # serve it

This is a normal Next.js server build that includes the /api/snippets route handlers and uses better-sqlite3 for storage.

As the sync server (v2.2.0)

The same web build doubles as the self-hosted sync server. The repo ships a multi-stage Dockerfile and docker-compose.yml; pnpm serve (next start -H 0.0.0.0) binds all interfaces for LAN access. CI publishes a prebuilt image to GHCR. See Syncing for running it and Continuous Integration for the image workflow.

Docker build note: the Dockerfile must copy pnpm-workspace.yaml (it holds the onlyBuiltDependencies allowlist) or the better-sqlite3 native addon won't build under a non-interactive pnpm install.

Desktop app

pnpm tauri:build

This runs tauri build, which:

  1. Runs the beforeBuildCommand → pnpm build:tauri.
  2. Compiles the Rust app in src-tauri/.
  3. Produces platform installers.

How the static export works

The desktop app talks to Rust commands, not the Next.js API routes — and Next.js output: "export" cannot coexist with app/api route handlers. So pnpm build:tauri (scripts/build-tauri.mjs) does the following:

  1. Temporarily moves app/api aside to app/_api.tauri-build-tmp.
  2. Runs next build with TAURI_BUILD=true, producing a static export in out/ (configured as frontendDist in tauri.conf.json).
  3. Restores app/api afterward (even if the build fails).

Output locations

Installers land in src-tauri/target/release/bundle/:

Platform Artifacts
Windows msi/SnipVault_<ver>_x64_en-US.msi, nsis/SnipVault_<ver>_x64-setup.exe
macOS dmg/*.dmg, macos/*.app
Linux deb/*.deb, appimage/*.AppImage, rpm/*.rpm

For a universal macOS binary (Intel + Apple Silicon in one .dmg), build with both Rust targets:

rustup target add aarch64-apple-darwin x86_64-apple-darwin
pnpm tauri build --target universal-apple-darwin
# -> src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg

Cross-platform note

Tauri cannot cross-compile. You can only build a platform's installer on that platform:

  • macOS .dmg → requires macOS
  • Windows .msi/.exe → requires Windows
  • Linux bundles → require Linux

To produce all three without owning every machine, use CI — see Continuous Integration.

Versioning

The app version is defined in three places; keep them in sync when releasing:

  • package.json → version
  • src-tauri/tauri.conf.json → version
  • src-tauri/Cargo.toml → package.version

The bundle identifier is com.snipvault.desktop (tauri.conf.json). Tagging a release as vX.Y.Z is what drives the CI pipelines.

Clone this wiki locally