Case study · Self-directed, fully owned
The game platform
A shared backend and content pipeline serving several daily puzzle games — live on the App Store and Play Store as Decode Daily.
Nobody asked for this one. I built it to carry a complete product lifecycle end to end, on my own terms: platform design, daily content generation, store review, and a full monetization stack.
- Backend Laravel 12 · Elastic Beanstalk
- Client Flutter · Riverpod
- Targets iOS 14+ · Android 21+
- Monetization AdMob
- Live Decode Daily — App Store & Play Store
The game platform — one backend, many games
Built so that shipping another game means writing a client, not another backend. Daily content is generated ahead of time rather than on request.
Content pipeline — runs on a schedule, ahead of demand
-
Scheduled generator
An artisan command generates seven days of challenges at a time, targetable per game.
-
Validated & stored
Each challenge is checked for solvability before it is persisted — a broken daily puzzle is a broken day.
-
Served as "today"
Clients fetch the current challenge; nothing is generated during a user's request.
Shared backend
Laravel 12 REST API on Elastic Beanstalk
- Challenge scheduling
- Player profiles & streaks
- Achievements
- Leaderboards & stats
- Categories
- RDS MySQL
Game clients
-
Decode Daily
Flutter cryptogram game, live on the App Store and Play Store. iOS 14+ / Android 21+, Riverpod state, AdMob monetization.
-
Stack & Sort
Second game on the same platform contract.
-
Number Crunch
Third game. Adding one is a client and a seeder, not a new system.
This is the self-directed work — fully owned, built to keep the craft sharp and to carry a full monetization stack end to end: ads, in-app purchase, store review, and the release cadence that comes with a daily game.
A platform, not a game
The straightforward way to ship a daily puzzle game is to build the game. The backend follows from whatever that one game needs, and the second game — if there ever is one — gets its own backend, its own accounts, and its own analytics.
I built the platform first instead. Challenges, player profiles, streaks, achievements, leaderboards, and categories are game-agnostic; the game identifier is a parameter, not a fork. Adding a game means writing a client and a seeder. That is why three of them sit on one contract rather than in three codebases.
Generate the content before anyone asks for it
A daily game has an unforgiving property: at midnight, in every timezone, a specific puzzle must exist and must be solvable. Generating it when the first player opens the app puts a content generator on the critical path of a cold start.
So generation is a scheduled command that produces seven days of challenges ahead of time, targetable per game, with solvability checked before anything is stored. By the time a player asks for today's puzzle, it has existed for a week and has already been validated.
A slow generator or an unlucky seed becomes an operational problem days before it could ever become a player-facing one.
The parts that are actually hard
The puzzle logic was the easy half. What takes the time is everything around it: store
listings, age ratings, privacy declarations, an ads SDK and its consent requirements,
the app-ads.txt file that has to resolve at a stable URL for ad serving to
work at all, and the review cycles.
That is the reason this project exists. A developer who has only ever shipped backends will confidently underestimate all of it. Having carried the full monetization stack — ads here, in-app purchase and subscription billing elsewhere — means I can give a straight answer about what a mobile launch actually costs, rather than a hopeful one.