Repository navigation
Building and Packaging
pnpm build # -> .next/
pnpm start # serve itThis is a normal Next.js server build that includes the /api/snippets route handlers and uses better-sqlite3 for storage.
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
Dockerfilemust copypnpm-workspace.yaml(it holds theonlyBuiltDependenciesallowlist) or thebetter-sqlite3native addon won't build under a non-interactivepnpm install.
pnpm tauri:buildThis runs tauri build, which:
- Runs the
beforeBuildCommand→pnpm build:tauri. - Compiles the Rust app in
src-tauri/. - Produces platform installers.
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:
- Temporarily moves
app/apiaside toapp/_api.tauri-build-tmp. - Runs
next buildwithTAURI_BUILD=true, producing a static export inout/(configured asfrontendDistintauri.conf.json). - Restores
app/apiafterward (even if the build fails).
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/*.dmgTauri 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.
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.
Using SnipVault
Development
Operations