{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreidqn4efvqc5zktkdbnsubttz5aqhfauqfzrk7ajwppyjjb5um5x3m",
"uri": "at://did:plc:yrn4rbgwenb6lfhhzjegbtnc/app.bsky.feed.post/3mncwahpsxcw2"
},
"path": "/t/introducing-flutpak-automating-flathub-submission-for-flutter-apps/12294#post_1",
"publishedAt": "2026-06-02T14:36:03.000Z",
"site": "https://discourse.flathub.org",
"tags": [
"GitHub - o-murphy/flutpak: Automates Flatpak packaging and offline builds for Flutter apps from pubspec.yaml. · GitHub",
"ebalistyka",
"Issues · o-murphy/flutpak · GitHub"
],
"textContent": "# Introducing flutpak - automating Flathub submission for Flutter apps\n\n**Repo:** GitHub - o-murphy/flutpak: Automates Flatpak packaging and offline builds for Flutter apps from pubspec.yaml. · GitHub\n**Version:** 0.4.0-rc.2 (pre-1.0, breaking changes expected until stable)\n\n* * *\n\n## The problem\n\nFlathub requires every source to be declared upfront with a SHA-256 checksum -\nno network access at build time. For a typical Flutter project that means:\n\n * Every pub.dev dependency needs **two** source entries in\n`generated-sources.json`: an archive download and an inline hash file that\n`pub get --offline` looks for separately. Miss the hash file and the build\nfails even if the archive is present.\n * The Flutter SDK brings its own set of artifacts - engine binaries, Dart SDK,\nmaterial fonts, Gradle wrapper - each with architecture-specific variants for\nx86_64 and aarch64, all requiring correct checksums at a specific engine\nrevision.\n * Packages like `objectbox_flutter_libs` require patch sources whose `dest:`\npath embeds the exact package version\n(`.pub-cache/hosted/pub.dev/objectbox_flutter_libs-5.3.1`). Update the\npackage and that path silently goes stale, producing a manifest that passes\nlinting but breaks at build time.\n * The Flutter SDK bootstrap script (`shared.sh`) calls `pub upgrade`, which\nrequires network. It needs to be patched to `pub get --offline` for every\nFlatpak build, every Flutter version.\n * None of the existing generator tooling (flatpak-pip-generator and its\nsiblings) understands the Dart/Flutter ecosystem.\n\n\n\nDoing all of this by hand for a non-trivial app means tracking hundreds of\nsource entries, re-verifying checksums on every dependency bump, and\nre-hunting Flutter artifact URLs on every Flutter release. This is the main\nreason Flutter apps are underrepresented on Flathub - not lack of interest, but\nthe sheer amount of manual work required just to get to the point where you can\nopen a submission PR.\n\n* * *\n\n## What flutpak targets\n\nflutpak is not a general Flatpak build tool. It is specifically aimed at\nproducing the output that a Flathub submission expects:\n\n * A `generated-sources.json` in the format Flathub reviewers are familiar with\n * A manifest that passes `flatpak-builder-lint --exceptions` without manual\ntweaks\n * A `flathub.json` with correct submission metadata\n * Metainfo and desktop entry validation via `appstreamcli` as part of the\ngenerate step\n * GitHub Actions that mirror the `flathub-build` pipeline used in Flathub CI,\nso what passes locally also passes in review\n\n\n\nThe goal is to reduce the gap between “my app builds with Flutter” and “my app\nis published on Flathub” to a config file and two commands.\n\n* * *\n\n## Where flutpak started\n\nThe first version (`0.1.0`, May 2026) was a single `prepare` command that\ngenerated `generated-sources.json` from a lock file and patched a manifest\nusing `__FLATPAK_TAG__` / `__FLATPAK_COMMIT__` placeholder strings. It also\ngenerated metainfo XML and `.desktop` files from config, and had `lint`,\n`validate`, and `export` wrapper commands around the official Flatpak toolchain.\n\nIt worked for one app. It was also immediately clear what was wrong with it:\n\n * The metainfo and desktop file generators were fragile and duplicated what\n`appstreamcli` and the Flathub submission process already validate. Removed\nin `0.2.8`.\n * The `lint` and `validate` wrappers around official tools added complexity\nwithout value. Removed in `0.2.5`-`0.2.6`.\n * Patch sources were baked into `generated-sources.json` at `init` time. The\n`dest:` path included the package version, so any version bump silently\nproduced a broken manifest. Fixed in `0.4.0-beta.2` by moving patch injection\nto `generate` time, where the current `pubspec.lock` is always available.\n * The manifest template carried `__FLATPAK_TAG__` and `__FLATPAK_COMMIT__`\nstrings that `generate` replaced with `sed`. Any YAML structural change near\nthose strings risked breaking substitution. Replaced in `0.4.0-rc.1` with\ndirect `yaml_edit` injection into the correct YAML node - no strings to\nmaintain, no fragile text replacement.\n * Config keys were inconsistently cased (`app_id`, `runtime_version`, etc.)\nand mixed flutpak-specific fields with Flatpak manifest fields in the same\nsection. Cleaned up in `0.4.0-rc.1`: all keys are now kebab-case, and\nflutpak-specific fields (`repo-url`, `metainfo-path`, `icons`) live at the\nroot level rather than inside `manifest:`.\n\n\n\nThe general direction has been: remove everything that duplicates official\ntooling, automate everything that is mechanical and error-prone, and keep\nthe config minimal.\n\n* * *\n\n## What it looks like now\n\nTwo commands cover the full workflow:\n\n**`flutpak init`** - run once. Generates the editable template manifest, a\nFlutter wrapper shell script, `flathub.json`, and `.gitignore`. Validates that\nyour metainfo, desktop entry, and icon files exist before writing anything.\n\n**`flutpak generate --tag vX.Y.Z`** - run on every CI build. Reads the\ncommitted template, writes `tag:` and `commit:` directly into the git source\nblock via `yaml_edit`, generates `generated-sources.json`, and copies\neverything to `flatpak/generated/` ready for `flatpak-builder`.\n\nThe minimum config to get started:\n\n\n # flutpak.yaml\n flutter:\n sdk: $FLUTTER_ROOT\n manifest:\n app-id: io.github.YourOrg.YourApp\n\n\nEverything else - command name, repo URL, flutter version file path, sandbox\npermissions - is either auto-detected or written into the template on `init`\nwith sensible defaults. You edit the template directly; `flutpak` never\noverwrites it.\n\nThe `known-patches/` directory ships reference patch files and companion\nFlatpak module files for packages that commonly need offline build\nmodifications. For example, `objectbox_flutter_libs` needs a CMakeLists.txt\npatch to use a prebuilt library instead of fetching it at build time. Copying\nthe relevant files and adding two lines to config is enough - `generate` handles\nthe rest, including the version-stamped `dest:` path and stripping CRLF line\nendings if the upstream archive has them.\n\nGitHub Actions composite actions are provided for CI, mirroring the Flathub\nbuild pipeline:\n\n\n - uses: o-murphy/flutpak/.github/actions/generate@v0.4.0-rc.2\n with:\n tag: ${{ github.ref_name }}\n metainfo-path: app/share/metainfo/<app-id>.metainfo.xml\n - uses: o-murphy/flutpak/.github/actions/build-flatpak@v0.4.0-rc.2\n with:\n manifest: flatpak/generated/<app-id>.yml\n app-id: io.github.YourOrg.YourApp\n\n\n* * *\n\n## Dogfooding\n\nI am using `flutpak` to package ebalistyka\nfor Flathub. The tool exists because I needed it and nothing else filled this\ngap. That submission is still in progress - which is exactly why the API is not\nstable yet. Working through a real Flathub submission is what surfaces the\nremaining rough edges.\n\n* * *\n\n## Where community help matters most\n\n**`known-patches/`** is where the most useful community contributions can land.\nIf you use a Flutter package that requires a patch source - pre-built native\nlibraries, CMake modifications, anything that needs a `type: patch` or\n`type: shell` source in the manifest - contributing a patch file and companion\nmodule there makes it work automatically for everyone using that package.\n\nBeyond patches:\n\n * Bug reports and edge cases from real apps are the most valuable feedback at\nthis stage\n * Feedback on the manifest structure that `flutpak init` generates\n * Packages that require source handling not yet covered\n\n\n\nIssue tracker: Issues · o-murphy/flutpak · GitHub\n\n* * *\n\n*Pre-1.0 means breaking changes are possible between minor versions. The\nchangelog documents them. If you are packaging a Flutter app for Flathub - or\nhave been putting it off because the source generation work seemed too painful\n\n * this is worth a look.*\n\n",
"title": "Introducing flutpak - automating Flathub submission for Flutter apps"
}