MM2-0/fdroid: The App Store That Runs on GitHub Artifacts

A self-hosted F-Droid pipeline that turns release assets and GitHub Actions builds into a browsable Android repo, with no database, no build farm, and no manual packaging loop.

8 min read • View on GitHub • More from MM2-0

A wide black-ink editorial scene of a print shop turning raw parcels into neatly cataloged shelves. A GitHub-shaped dispatch chute drops APK packages onto a conveyor, where they pass through stamping wheels, a ledger desk, and a storefront window before ending up as organized app tiles. It explains how this project converts temporary CI outputs into a durable distribution system.
GitHub artifacts arrive as temporary byproducts. This repo treats them like inventory and turns them into a real app catalog.
Key Takeaways

Most app-store projects begin with a backend. This one begins with a trust decision. MM2-0/fdroid treats GitHub as the source of packaged truth, then wraps those binaries in the plumbing F-Droid needs to look like a real repository.

The strange part is the premise

The repo does not try to be a general Android build farm. It pulls APKs from GitHub Releases or GitHub Actions artifacts, validates them, extracts metadata, signs the result, and publishes an index that F-Droid clients can read. In practice, that means temporary CI outputs are promoted into a durable catalog instead of being treated as disposable leftovers.

That is the whole trick. The configuration lives in `/config`, the ingestion logic lives in `/repo`, and the storefront lives in `/frontend`. The pipeline is narrow on purpose, which is why it feels so clean.

Why someone would want this

If you run a small Android app catalog, you may not want the full F-Droid source-rebuild model. You may already trust your GitHub releases, or you may want nightly builds without maintaining a separate build server. This project gives you a middle path: more control than a download page, far less infrastructure than a traditional F-Droid build farm.

The repo also appears tuned to a specific ecosystem, especially the Kvaesitso launcher world. That matters because the best distribution tools are usually boring to everyone except the people who need them, and this one solves a real operational edge case.

The pipeline: from artifact to repo entry

The build sequence is deliberately split into small stages. GitHub Actions prepares the machine, the repo ingests APKs, F-Droid tools generate the index, and the frontend consumes the finished JSON. There is no database in the middle, just files moving through a controlled chain.

The system is a file pipeline, not a server farm. GitHub supplies artifacts, TypeScript assembles them, F-Droid indexes them, and the frontend reads the finished catalog.

The implementation details reinforce the same idea. `gh-release-source.ts` pulls release APKs, while `gh-action-source.ts` turns successful workflow artifacts into first-class inputs and can synthesize changelogs from commit ranges. `node-apk` extracts package metadata from the binary itself, and `fdroidserver` turns the result into the repository index.

scripts/setup.sh
scripts/populate.sh
scripts/build.sh
frontend/scripts/build.sh
A close-up black-ink scene of a single APK envelope under a magnifying loupe. On the left, a GitHub Actions artifact tag and a release asset tag feed into the file. On the right, the same file receives a manifest stamp, a version card, and a sealed repository mark. It explains how the project turns one binary into a validated package entry.
The interesting work happens at the handoff point. One binary becomes a signed, indexed repo entry with metadata pulled from the file itself.

The cleverest trick: nightly builds without a build farm

`gh-action-source.ts` is the most interesting file in the repo because it treats CI output as a distribution channel. Instead of waiting for a source build, it can publish the artifact that already exists, then label it as a stable or nightly track depending on the source and metadata. That is a practical answer to the question most app maintainers eventually ask: how do we ship fast without adding another server?

The clever bit is not only speed. The source can also derive a changelog by comparing commit SHAs between runs, which means the nightly track is still legible to humans. The result is a repo that feels current without turning into a manual packaging treadmill.

Why the frontend matters

The SvelteKit frontend is doing real work, not cosmetic work. It reads `index-v2.json`, flattens the F-Droid data model into something browseable, and serves the whole experience from static hosting. That keeps the system cheap to run and easy to deploy, because the UI is just another generated artifact.

This is why the architecture feels unusually tight. The backend produces files, the frontend consumes files, and GitHub Pages can host the result. There is nowhere for state to accumulate except the repository itself.

A medium editorial scene of a tiny storefront window built from shelves and catalog cards. Behind the wall, a single file cabinet labeled `index-v2.json` feeds the display, while the front window shows neatly arranged app tiles. It explains that the user interface is a thin layer over generated static data.
The storefront is only a thin skin over generated data. The real product is the index file, not a running app server.

What this replaces

DimensionStandard F-Droid modelMM2-0/fdroid
Source of truthUpstream source code and F-Droid recipesGitHub releases, Actions artifacts, and YAML config
APK provenanceRebuilt from source by the F-Droid build systemImported from upstream binaries
Build responsibilityCentral F-Droid infrastructure compiles and signsThis repo's workflow assembles, signs, and indexes
Update cadenceBound to recipe maintenance and build queue timingBound to upstream releases and CI output
Trust modelTrust the source rebuild pathTrust the upstream binary and GitHub artifact integrity
Infra requiredBuild servers, metadata upkeep, and storageStatic hosting plus GitHub Actions, with no database
Frontend deliveryClient apps browse repository dataSvelteKit storefront reads `index-v2.json`
Best forCanonical FOSS distribution with source rebuild disciplinePrivate, semi-public, or CI-led app catalogs

The real trade-off

This repository is compelling because it makes its trade-offs explicit. You get control, speed, and a clean static deployment model, but you also accept the risks of upstream binaries, GitHub availability, and the maintenance cost of a custom pipeline. That is not a flaw. It is the point.

In other words, MM2-0/fdroid is less a toy repo than a distribution thesis. It says GitHub can be more than source control, and that a carefully designed file pipeline can stand in for a much heavier app-store backend when the problem is narrow enough.