The challenge
What we delivered
One backend for a whole network of apps
With two apps you can keep the content in files inside each one. With twenty-four, every edit to a line of text turns into a new release on Google Play and a week of waiting.
We built a platform where the content lives apart from the apps: an editor changes it in the admin, and the phones pull the updated bundle themselves — without updating the app.
Each tile is an app: how many items it holds and which content version is currently published.
The app only reads
The central architectural decision is simple: the phone writes nothing to the platform except anonymous events. It fetches the manifest, fetches the bundle of items in its own language, and that is all. No accounts, no synchronisation, no conflicts.
Because of that, a new app is set up almost without code: create a record in the admin, a key is generated, fill in categories and items, press Publish — and the content version goes up by one. The key and the address go into the app, and from then on it runs by itself.
Twenty-four apps in one table
Each has its own access key, its own set of languages, its own content version and its own state. You can see what is published, what is in progress and what is still an idea. This is not a showcase — it is the working list the whole network is run from.
Items of different shapes
A recipe, a guide, a quiz question, a party-game card, an error code, a riddle, a fact — each format has its own editing form, not one field called “text”. A hundred items can be added by import: paste an array, choose the type and the language, and the system reports row by row — what was accepted, what was not and why.
Not paying for what has not changed
A bundle for one app runs to hundreds of kilobytes. Downloading it on every launch makes no sense, so the response carries a version tag: if the phone already has the current bundle, the server answers “nothing changed” and sends nothing.
And here was the trap that quietly defeated the saving: a proxy that compresses responses rewrites the tag into its “weak” form, and a strict comparison stops matching. The phone re-downloaded everything, every time. The comparison had to be taught to accept all three shapes of the tag — strong, weak and comma-separated.
Media that does not bloat the app
Every image is converted to WebP on upload and kept in two sizes: full up to 1200 pixels and a thumbnail up to 400. The server hands them out with a long cache, and the app receives ready-made addresses — no conversion on the phone.
Statistics without personal data
The apps send anonymous events — an open, a navigation, an action. No identifiers of a person, no contacts. At most fifty events per request, and malformed rows are simply dropped rather than failing the whole call.
Alongside that, the platform pulls in figures from the app store and the ad network — so installs and revenue are read in the same place the content lives, not across three separate consoles.
How it was done
Under the hood
Platform
Laravel with a Filament admin. It lives on ordinary hosting: no root, no containers, queue and cache in the database, images converted the moment they are uploaded.
API
Four read endpoints, a key in the header, limits per key and per address, a version tag with a “nothing changed” response. Errors are plain JSON with a code.
Vault
A separate place for builds and store material: icons, screenshots, descriptions. Plus cross-links between the apps in the network.
How it turned out
A network of twenty-four apps in which a text edit reaches the user in minutes rather than a week. A new app is set up in the admin in a few minutes: create, fill, publish, paste the key.
And all of it runs on ordinary hosting — with no separate server, no in-memory queues and no containers, none of which there is anywhere to start.



