Inspiration

I like playing a quick little game now and then. But nothing currently on the market satisfies me, and there's so much that inspires me to make small games myself that I just wanted to go for it and create an experience that, I think, fits better into the current era. I grew up with the Game Boy and its peers. It was simple and clear. You usually didn't need the sound, or it was even annoying. Because that's exactly what bothers me most today. Everything is loud, kitschy, and completely overstimulating. I want an exciting, varied game that gives me exactly that — the game — not eye cancer. The same should go for the sound. When I want to play a few quick rounds on the train or at the bus stop, I want to play. I don't want to have to check first whether I'm annoying everyone around me with some jingle. Just as much, when I've got headphones on, I want to hear my music, not some bing-bong on top of it.

Games today are none of that. They're wild, restless, stressful, way too colorful, and way too loud. And yet most of them still offer only one game in a slightly different variation, spread across hundreds of levels.

Which is why I look back to a time when games were "games" — not a complete entertainment package for every sense. You should be able to lose yourself in the game, whether for a few rounds or a few hours, using the right strategy to unlock the right games and eventually collect them all.

As a developer, I have to make money with apps, just like every other developer. But why bombard players with pay-to-win or pay-to-play options just moments after their first launch? Here's an offer, here's a timer, buy this in-app currency here, or trade it through the marketplace instead, and on and on. It was simply too much for me. There has to be a way for players to have a varied experience and switch from game to game without having to pull out a calculator to figure out which purchase actually gets them anything.

What the app does

Right now there are sixteen short mini-games. A few are unlocked from the start, the rest you trade in for tickets you've earned by playing.

Every finished round credits the same amount to two separate accounts. That amount is 5 points for completing the round, plus your own score from that round as points — and the same number of tickets.

Both accounts receive that amount at the exact same moment. The separation is the core of the design. Points are permanent — they're never spent and never deducted, and they're what the leaderboard is sorted by. The ticket balance is spendable, and it's the only currency that unlocks a game. Until the first redemption, the two are identical; after that they diverge, because only tickets can ever go down.

That's exactly what makes "no pay-to-win" structurally true, not just a marketing line: even if I ever sold tickets for real money, they couldn't buy a single spot on the leaderboard — because rank is tied to the account that nothing but playing can ever add to. Even the zero case counts: whoever opens a game and does nothing gets nothing for that round. Otherwise the fastest way up would be to just open and close a game over and over.

Revenue comes from a subscription that removes ads. Nothing else. It doesn't unlock any games, doesn't grant any tickets, and doesn't touch the leaderboard.

How I built it

Flutter and Riverpod on-device, Supabase (Postgres, Row Level Security, SECURITY DEFINER functions) for accounts and leaderboards, RevenueCat for the subscription and its paywall, AdMob for ads.

A handful of decisions shaped everything else.

Offline-first, and the queue is the source of truth. A round that ends in a tunnel still counts. Results land in a local queue and go out later through an idempotent server function, so a retry can never make a round count twice. A write comes back with one of three answers, not two: accepted, rejected (the server refused it because of some condition — so discard it), or unreachable (no network, no permission — so it stays queued). Anyone who lumps those last two together as "failed" either loses a player's whole evening of playing, or bombards the server forever with a record it will never accept.

You can play without an account. Anonymous sessions are the default; signing in is an upgrade, not a gate.

Ads are shown sparingly to the user at the start. Once they're further in and have built a connection to the game, they'll be more willing to watch an ad to play the next round — or to have the points they just earned actually count. If they'd rather not see ads at all, they can subscribe and make the whole game ad-free. Nothing else about the game changes — whether they subscribe monthly, quarterly, or yearly. With or without a subscription, the player can play the same games and has the same chances of climbing the leaderboard.

What I struggled with

Offering as creative and varied a set of mini-games as possible, for as many kinds of players and interests as possible. A good mix matters. But also making sure every game explains itself as much as possible, or that the penny drops for the player at the latest after their first mistake — so they go into the next attempt with an "I've got this!" instead of a "No," without losing interest.

"Present" and "prominent" are two different checks. Apple rejected the app under Guideline 3.1.2(c). I had checked whether the paywall showed price, duration, renewal notice, and the legal links — all present, and that's exactly what I'd written in my review notes. What I'd never actually looked at was the visual weighting: the amount actually charged sat there in 13pt regular, in gray, while the calculated monthly value next to it was in 15pt semibold. The rule is that the price actually charged has to be the most prominent one, and mine was the least prominent. I removed the monthly value entirely instead of just shrinking it — where there's no second number, there's no hierarchy you can get wrong.

And then the part that turned me into a true believer: fixing this rejection didn't need a new build at all. The paywall loads at runtime from the dashboard, so I changed it, published revision 21, and replied in the Resolution Center asking them to re-review the same binary. A store-policy violation in software that was already out in the world, fixed in twenty minutes, for everyone who already had the app installed. I'd chosen a remote-controlled paywall for the A/B testing. Its real value turned out to be something else: the paywall is the one part of an app that can be wrong in a way that gets you thrown out of the store — and the only part that doesn't need a new release to fix.

What I learned

That it pays off to deliberately choose which parts of an app you can change without a new release — because those are the parts where you can still fix a mistake in front of real users' eyes. And that the honest version of "no pay-to-win" isn't a promise in a store description — it's a data model where the currency that ranks you and the currency you spend are two different columns, and only one of them can ever go down.

What's next

More games, gathering experience across even more screens, and working to adapt the games, language, and the app's overall offering to more players and more countries.

Built With

Share this project:

Updates

posted an update —

When brainstorming ideas for the app, I initially tried to find a name that quickly conveyed that it's a game featuring many mini-games you can play for quick sessions. So, I first came up with "miniJoy." Even my research prior to release didn't reveal any issues with the name. However, after launch, it turned out that the Apple App Store in particular frequently mistook "Joy" for "Job." No matter what you did, the app usually wouldn't show up in search results. Since it's crucial for both marketing and word-of-mouth that the app is easy to find in the stores, I couldn't leave it as it was. So, I looked for alternatives that better reflected that the app is a collection of mini-games that are simple, engaging, and not as sensory-overloading as many others on the market. I reflected on the design of competing products and focused on how they always feature bright colors, cotton candy, and candy. Since my app was meant to be the exact opposite, I ultimately decided on "No Sugar Arcade."

Log in or sign up for Devpost to join the conversation.

Submission history