# Bundled client assets Holds the Android APK (`minstrel.apk` + `minstrel.apk.version`) that the server serves via `/api/client/version` and `/api/client/apk` for the in-app update flow (#397). ## Production CI populates this directory in `release.yml` (no Flutter — the client is native Android, built by the `android-release` job): - **Tag release (`v*`):** the `android-release` job builds + signs the APK, uploads it as a workflow artifact, and attaches it to the Gitea release as `minstrel-.apk`. The `image-release` job (`needs: android-release`) downloads that artifact into this directory as `minstrel.apk` and writes the computed versionName to `minstrel.apk.version`. - **Main push (non-tag `:latest` / `:main`):** no APK is built, but the image still moves `:latest`, so `image-release` pulls the most-recent release's signed APK from the Gitea API and reconstructs its exact versionName — keeping the in-app update channel alive on `:latest` instead of stripping it until the next tag. Either way, `docker buildx build` bakes both files into the image via `COPY client/ /app/client/`. ## Development Empty directory works fine — the endpoints return 404 and the Android update banner stays hidden ("no update channel" graceful degradation). To smoke-test the update flow locally, drop a real APK + a version file into this directory: ```sh cp /path/to/app-release.apk client/minstrel.apk echo "v0.2.0" > client/minstrel.apk.version ``` ## Why a directory and not embed.FS? The APK is 30-60 MB. Embedding bloats the Go binary and slows `go build` for everyone, even when the APK isn't being changed. File-on-disk also lets operators override at runtime via volume mount on `/app/client/` if they want to ship their own build.