.claude/skills/tauri-2/tauri-impl/tauri-impl-build-deploy/SKILL.md
Use when building for production, configuring installers, setting up code signing, or creating CI/CD pipelines. Prevents unsigned builds being rejected by OS gatekeepers and missing resource files in bundled installers. Covers tauri build command, platform bundlers (NSIS/MSI/DMG/AppImage/deb), sidecars, code signing, updater, and GitHub Actions CI/CD. Keywords: tauri build, deploy, NSIS, MSI, DMG, AppImage, code signing, auto-updater, CI/CD, GitHub Actions, sidecar.
npx skillsauth add OpenAEC-Foundation/OpenAEC-Workspace-Composer tauri-impl-build-deployInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Command | Purpose |
|---------|---------|
| tauri build | Full production build with bundling |
| tauri build --no-bundle | Compile only, skip installers |
| tauri bundle --bundles app,dmg | Bundle specific formats only |
| tauri bundle --config src-tauri/tauri.appstore.conf.json | Build with alternate config |
| tauri android build | Android production build |
| tauri ios build | iOS production build |
| Platform | Formats | Notes | |----------|---------|-------| | Windows | NSIS installer, MSI (WiX), portable exe | WebView2 install mode configurable | | macOS | App bundle (.app), DMG | Code signing + notarization required for distribution | | Linux | AppImage, .deb, .rpm, Snap, Flatpak | AppImage is the most universal | | Android | APK, AAB | Play Store requires AAB | | iOS | IPA | App Store or TestFlight distribution |
NEVER lose the updater private key -- it is impossible to push updates to existing installations without it. Back it up securely.
NEVER set createUpdaterArtifacts: true without setting the TAURI_SIGNING_PRIVATE_KEY environment variable -- the build will fail.
NEVER distribute unsigned macOS builds -- Gatekeeper quarantines them. Use at minimum ad-hoc signing ("-").
NEVER use "v1Compatible" for createUpdaterArtifacts in new projects -- only for migrating from v1 updater.
ALWAYS commit src-tauri/Cargo.lock for deterministic builds across environments.
ALWAYS set GitHub token permissions to "Read and write" when using tauri-action for releases.
The bundle section in tauri.conf.json controls all packaging:
{
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/[email protected]",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "com.example.myapp",
"resources": {
"models/": "models/",
"config.toml": "config.toml"
},
"externalBin": ["binaries/ffmpeg"],
"category": "Utility",
"copyright": "Copyright 2026 Example Inc.",
"publisher": "Example Inc.",
"license": "MIT",
"createUpdaterArtifacts": true
}
}
Resources are additional files bundled with the app. External binaries (sidecars) are executables embedded and spawnable at runtime.
{
"bundle": {
"resources": {
"models/": "models/",
"config.toml": "config.toml"
},
"externalBin": ["binaries/ffmpeg"]
}
}
Access bundled resources at runtime:
import { resolveResource } from '@tauri-apps/api/path';
const modelPath = await resolveResource('models/default.bin');
OV Certificate in tauri.conf.json:
{
"bundle": {
"windows": {
"certificateThumbprint": "A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.comodoca.com"
}
}
}
Custom signing (Azure Key Vault):
{
"bundle": {
"windows": {
"signCommand": "relic sign --file %1 --key azure --config relic.conf"
}
}
}
Local signing:
{
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Your Name (TEAMID)",
"hardenedRuntime": true,
"minimumSystemVersion": "10.13"
}
}
}
Or use APPLE_SIGNING_IDENTITY environment variable. For ad-hoc signing (testing only): set signingIdentity to "-".
Notarization environment variables:
| Method | Variables |
|--------|-----------|
| App Store Connect API | APPLE_API_ISSUER, APPLE_API_KEY, APPLE_API_KEY_PATH |
| Apple ID | APPLE_ID, APPLE_PASSWORD (app-specific), APPLE_TEAM_ID |
Step 1: Install the updater plugin:
npm run tauri add updater
cargo add tauri-plugin-updater --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
Step 2: Initialize in Rust:
#[cfg(desktop)]
app.handle().plugin(tauri_plugin_updater::Builder::new().build());
Step 3: Generate signing keys:
npm run tauri signer generate -- -w ~/.tauri/myapp.key
Step 4: Set build environment variables:
export TAURI_SIGNING_PRIVATE_KEY="path or content"
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
Step 5: Configure in tauri.conf.json:
{
"bundle": {
"createUpdaterArtifacts": true
},
"plugins": {
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6...",
"endpoints": [
"https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}"
],
"windows": {
"installMode": "passive"
}
}
}
}
URL template variables: {{current_version}}, {{target}} (linux/windows/darwin), {{arch}} (x86_64/i686/aarch64/armv7).
Windows install modes: "passive" (no interaction, default), "basicUi" (user interaction), "quiet" (no feedback).
import { check } from '@tauri-apps/plugin-updater';
import { relaunch } from '@tauri-apps/plugin-process';
const update = await check();
if (update) {
await update.downloadAndInstall((event) => {
switch (event.event) {
case 'Started':
console.log(`Downloading: ${event.data.contentLength} bytes`);
break;
case 'Progress':
console.log(`Downloaded: ${event.data.chunkLength}`);
break;
case 'Finished':
console.log('Download complete');
break;
}
});
await relaunch();
}
use tauri_plugin_updater::UpdaterExt;
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
if let Some(update) = app.updater()?.check().await? {
update.download_and_install(
|chunk_length, content_length| {
println!("Downloaded: {chunk_length}/{content_length:?}");
},
|| println!("Finished"),
).await?;
app.restart();
}
Ok(())
}
name: Release
on:
push:
branches: [release]
workflow_dispatch:
permissions:
contents: write
jobs:
release:
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
args: --target aarch64-apple-darwin
- platform: macos-latest
args: --target x86_64-apple-darwin
- platform: ubuntu-22.04
args: ''
- platform: ubuntu-22.04-arm
args: ''
- platform: windows-latest
args: ''
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
- name: Install frontend dependencies
run: npm install
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: app-v__VERSION__
releaseName: 'App v__VERSION__'
releaseBody: 'See the assets to download and install.'
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}
__VERSION__ is auto-replaced with the version from tauri.conf.json.
Required secrets: WINDOWS_CERTIFICATE (base64 .pfx), WINDOWS_CERTIFICATE_PASSWORD.
Required secrets: APPLE_CERTIFICATE (base64 .p12), APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITY, KEYCHAIN_PASSWORD, APPLE_API_ISSUER, APPLE_API_KEY, APPLE_API_KEY_PATH.
| Platform | Update Artifact | Signature File |
|----------|----------------|----------------|
| Linux | .AppImage.tar.gz | .AppImage.tar.gz.sig |
| macOS | .app.tar.gz | .app.tar.gz.sig |
| Windows | .exe or .msi | .exe.sig or .msi.sig |
Static JSON (CDN/GitHub Releases):
{
"version": "1.0.0",
"notes": "Bug fixes and improvements",
"pub_date": "2024-01-15T10:30:00Z",
"platforms": {
"linux-x86_64": {
"signature": "...",
"url": "https://cdn.example.com/app-1.0.0.AppImage.tar.gz"
},
"windows-x86_64": {
"signature": "...",
"url": "https://cdn.example.com/app-1.0.0-setup.exe"
},
"darwin-x86_64": {
"signature": "...",
"url": "https://cdn.example.com/app-1.0.0.app.tar.gz"
}
}
}
Dynamic server: Return HTTP 204 (no update) or HTTP 200 with version, url, signature, pub_date, notes.
development
Use when integrating Vite with a backend framework, rendering Vite assets from server-side templates, or setting up dev/production HTML serving. Prevents incorrect manifest.json traversal and missing CSS chunk resolution in production. Covers build.manifest configuration, .vite/manifest.json structure, ManifestChunk properties, dev mode HTML setup, production rendering, CSS/JS chunk resolution, and modulepreload polyfill. Keywords: backend integration, manifest.json, ManifestChunk, Django, Laravel, Rails, modulepreload.
development
Use when encountering dev server startup failures, HMR issues, proxy errors, CORS blocks, or module not found errors during development. Prevents misconfiguring server.hmr behind reverse proxies and forgetting appType: 'custom' in middleware mode. Covers HMR full-reload debugging, proxy configuration, CORS setup, HTTPS certificates, server.fs.strict violations, port conflicts, WebSocket failures, file watcher issues, and middleware mode. Keywords: dev server, HMR, proxy, CORS, HTTPS, WebSocket, port conflict, server.fs.strict, middleware mode, file watcher.
development
Use when encountering pre-bundling errors, dependency resolution failures, stale cache issues, or slow development server startup. Prevents excluding CJS dependencies from pre-bundling (which breaks runtime module resolution) and misconfiguring optimizeDeps. Covers CJS/ESM conversion failures, missing dependency auto-discovery, optimizeDeps configuration, monorepo linked dependencies, cache invalidation, browser cache staleness, and large dependency tree performance. Keywords: pre-bundling, optimizeDeps, CJS, ESM, cache, dependency resolution, monorepo, node_modules/.vite.
development
Use when encountering Vite build failures, chunk size warnings, or version-specific build errors. Prevents the common mistake of using deprecated rollupOptions in v8 or misconfiguring build targets and minifiers. Covers Rolldown/Rollup bundling failures, CSS minification errors, sourcemap problems, library mode build failures, BundleError handling, and asset processing errors. Keywords: build error, Rolldown, chunk size, sourcemap, library mode, minify, BundleError, rollupOptions, build.target.