Introducing flutpak - automating Flathub submission for Flutter apps
Introducing flutpak - automating Flathub submission for Flutter apps
Repo: GitHub - o-murphy/flutpak: Automates Flatpak packaging and offline builds for Flutter apps from pubspec.yaml. · GitHub Version: 0.4.0-rc.2 (pre-1.0, breaking changes expected until stable)
The problem
Flathub requires every source to be declared upfront with a SHA-256 checksum - no network access at build time. For a typical Flutter project that means:
- Every pub.dev dependency needs two source entries in
generated-sources.json: an archive download and an inline hash file thatpub get --offlinelooks for separately. Miss the hash file and the build fails even if the archive is present. - The Flutter SDK brings its own set of artifacts - engine binaries, Dart SDK, material fonts, Gradle wrapper - each with architecture-specific variants for x86_64 and aarch64, all requiring correct checksums at a specific engine revision.
- Packages like
objectbox_flutter_libsrequire patch sources whosedest:path embeds the exact package version (.pub-cache/hosted/pub.dev/objectbox_flutter_libs-5.3.1). Update the package and that path silently goes stale, producing a manifest that passes linting but breaks at build time. - The Flutter SDK bootstrap script (
shared.sh) callspub upgrade, which requires network. It needs to be patched topub get --offlinefor every Flatpak build, every Flutter version. - None of the existing generator tooling (flatpak-pip-generator and its siblings) understands the Dart/Flutter ecosystem.
Doing all of this by hand for a non-trivial app means tracking hundreds of source entries, re-verifying checksums on every dependency bump, and re-hunting Flutter artifact URLs on every Flutter release. This is the main reason Flutter apps are underrepresented on Flathub - not lack of interest, but the sheer amount of manual work required just to get to the point where you can open a submission PR.
What flutpak targets
flutpak is not a general Flatpak build tool. It is specifically aimed at producing the output that a Flathub submission expects:
- A
generated-sources.jsonin the format Flathub reviewers are familiar with - A manifest that passes
flatpak-builder-lint --exceptionswithout manual tweaks - A
flathub.jsonwith correct submission metadata - Metainfo and desktop entry validation via
appstreamclias part of the generate step - GitHub Actions that mirror the
flathub-buildpipeline used in Flathub CI, so what passes locally also passes in review
The goal is to reduce the gap between “my app builds with Flutter” and “my app is published on Flathub” to a config file and two commands.
Where flutpak started
The first version (0.1.0, May 2026) was a single prepare command that
generated generated-sources.json from a lock file and patched a manifest
using __FLATPAK_TAG__ / __FLATPAK_COMMIT__ placeholder strings. It also
generated metainfo XML and .desktop files from config, and had lint,
validate, and export wrapper commands around the official Flatpak toolchain.
It worked for one app. It was also immediately clear what was wrong with it:
- The metainfo and desktop file generators were fragile and duplicated what
appstreamcliand the Flathub submission process already validate. Removed in0.2.8. - The
lintandvalidatewrappers around official tools added complexity without value. Removed in0.2.5-0.2.6. - Patch sources were baked into
generated-sources.jsonatinittime. Thedest:path included the package version, so any version bump silently produced a broken manifest. Fixed in0.4.0-beta.2by moving patch injection togeneratetime, where the currentpubspec.lockis always available. - The manifest template carried
__FLATPAK_TAG__and__FLATPAK_COMMIT__strings thatgeneratereplaced withsed. Any YAML structural change near those strings risked breaking substitution. Replaced in0.4.0-rc.1with directyaml_editinjection into the correct YAML node - no strings to maintain, no fragile text replacement. - Config keys were inconsistently cased (
app_id,runtime_version, etc.) and mixed flutpak-specific fields with Flatpak manifest fields in the same section. Cleaned up in0.4.0-rc.1: all keys are now kebab-case, and flutpak-specific fields (repo-url,metainfo-path,icons) live at the root level rather than insidemanifest:.
The general direction has been: remove everything that duplicates official tooling, automate everything that is mechanical and error-prone, and keep the config minimal.
What it looks like now
Two commands cover the full workflow:
flutpak init - run once. Generates the editable template manifest, a
Flutter wrapper shell script, flathub.json, and .gitignore. Validates that
your metainfo, desktop entry, and icon files exist before writing anything.
flutpak generate --tag vX.Y.Z - run on every CI build. Reads the
committed template, writes tag: and commit: directly into the git source
block via yaml_edit, generates generated-sources.json, and copies
everything to flatpak/generated/ ready for flatpak-builder.
The minimum config to get started:
# flutpak.yaml
flutter:
sdk: $FLUTTER_ROOT
manifest:
app-id: io.github.YourOrg.YourApp
Everything else - command name, repo URL, flutter version file path, sandbox
permissions - is either auto-detected or written into the template on init
with sensible defaults. You edit the template directly; flutpak never
overwrites it.
The known-patches/ directory ships reference patch files and companion
Flatpak module files for packages that commonly need offline build
modifications. For example, objectbox_flutter_libs needs a CMakeLists.txt
patch to use a prebuilt library instead of fetching it at build time. Copying
the relevant files and adding two lines to config is enough - generate handles
the rest, including the version-stamped dest: path and stripping CRLF line
endings if the upstream archive has them.
GitHub Actions composite actions are provided for CI, mirroring the Flathub build pipeline:
- uses: o-murphy/flutpak/.github/actions/generate@v0.4.0-rc.2
with:
tag: ${{ github.ref_name }}
metainfo-path: app/share/metainfo/<app-id>.metainfo.xml
- uses: o-murphy/flutpak/.github/actions/build-flatpak@v0.4.0-rc.2
with:
manifest: flatpak/generated/<app-id>.yml
app-id: io.github.YourOrg.YourApp
Dogfooding
I am using flutpak to package ebalistyka
for Flathub. The tool exists because I needed it and nothing else filled this
gap. That submission is still in progress - which is exactly why the API is not
stable yet. Working through a real Flathub submission is what surfaces the
remaining rough edges.
Where community help matters most
known-patches/ is where the most useful community contributions can land.
If you use a Flutter package that requires a patch source - pre-built native
libraries, CMake modifications, anything that needs a type: patch or
type: shell source in the manifest - contributing a patch file and companion
module there makes it work automatically for everyone using that package.
Beyond patches:
- Bug reports and edge cases from real apps are the most valuable feedback at this stage
- Feedback on the manifest structure that
flutpak initgenerates - Packages that require source handling not yet covered
Issue tracker: Issues · o-murphy/flutpak · GitHub
*Pre-1.0 means breaking changes are possible between minor versions. The changelog documents them. If you are packaging a Flutter app for Flathub - or have been putting it off because the source generation work seemed too painful
- this is worth a look.*
Discussion in the ATmosphere