# Desktop packaging (Linux, Arch, Windows)

How to produce distributable desktop packages for JellyTau. All three flows can run in Docker so no host toolchain setup is required. Outputs land in `./dist`.

## One builder image (shared with CI)

The deb/rpm and Windows-cross flows build on the unified registry builder (../Dockerfile.builder → `gitea.tourolle.paris/dtourolle/jellytau-builder`), the same image CI uses. It carries every packaging tool: Android SDK/NDK, `rpm`/`file` (Linux bundler), `cargo-xwin` + `lld` + `llvm` + `nsis` + the `x86_64-pc-windows-msvc` rust target (Windows). There is one dependency source of truth — no per-stage tool installs.

The desktop stages in ../Dockerfile are thin `FROM ${BUILDER_IMAGE}` environments; the actual build runs at container-run time on your bind-mounted source (like the `dev` service), so source edits need no image rebuild.

If you changed `Dockerfile.builder` (e.g. added a tool), rebuild and push it first, or the packaging flows use the stale registry image:

    scripts/build-builder-image.sh           # build + push :latest to the registry
    # ...or iterate locally without pushing:
    docker build -f Dockerfile.builder -t jellytau-builder:latest .
    BUILDER_IMAGE=jellytau-builder:latest bun run docker:build:windows

Arch uses a separate `archlinux` image (../Dockerfile.arch) because `makepkg` is Arch-specific — it is not part of the unified builder.

Target | Format | Docker command | Functional?
--- | --- | --- | ---
Debian/Ubuntu, Fedora | `.deb`, `.rpm` | `bun run docker:build:linux` | ✅ yes
Arch Linux | `.pkg.tar.zst` | `bun run docker:build:arch` | ✅ yes
Windows | NSIS installer + `.exe` | `bun run docker:build:windows` | ✅ yes (unsigned)

## Linux: deb + rpm

Tauri's bundler produces these natively. The build runs on the existing Ubuntu builder image (../Dockerfile, `desktop-linux-build` stage):

    bun run docker:build:linux            # deb + rpm -> ./dist
    # or, on a host with the Tauri Linux deps installed:
    BUNDLES="deb,rpm" scripts/build-desktop-linux.sh

Runtime dependency: the app links libmpv (audio) and WebKitGTK (webview + HTML5 transcoded video). The deb/rpm declare these.

> Note: `appimage` is also a valid Tauri target if you want a portable bundle — add it to `BUNDLES`.

## Arch Linux: pacman package

Tauri has no `pacman` bundle target (as of tauri-cli 2.9.x — valid targets are deb/rpm/appimage/msi/nsis/app/dmg). So we ship a hand-written PKGBUILD in ../packaging/arch/PKGBUILD and build it with `makepkg` on an Arch base image (../Dockerfile.arch):

    bun run docker:build:arch             # .pkg.tar.zst -> ./dist

The PKGBUILD is AUR-ready: swap its `source=()` for a release tarball/VCS URL to publish. Runtime deps: `webkit2gtk-4.1`, `mpv`, `gtk3`, `libayatana-appindicator`.

`makepkg` refuses to run as root, so the Docker stage builds as a non-root `builder` user. Because the image `COPY`s the source at build time, the `arch-build` compose service does not bind-mount the repo — rebuild the image to pick up source changes.

## Windows: NSIS installer cross-compiled from Linux

Produces a working (unsigned) NSIS installer + `.exe` via the official Tauri cross-compile path — the `x86_64-pc-windows-msvc` target driven by `cargo-xwin`. Video plays via WebView2 and audio via the webview `<audio>` backend. See build-windows.md for the full explanation.

    bun run docker:build:windows                     # NSIS installer + .exe -> ./dist
    WIN_BUNDLES=none bun run docker:build:windows     # exe only, skip bundling

The Docker `windows-cross` stage is a thin layer over the builder, which carries `cargo-xwin` + `lld` + `llvm` + `nsis` + the `x86_64-pc-windows-msvc` target. Cross-compilation is Tauri's "last resort" path (less tested than building on Windows); a `windows-latest` CI job is the fallback if it misbehaves.