Inspiration
I published my first mobile app this year, BlueBaħar (https://bluebahar.com/) and it now has about 3,800 active users in Malta. Building it gave me an opportunity to see how a community of passionate people genuinely forms and creates a virtuous cycle of improving the product cause they care about it.
For my next app I wanted to try that with something lighter, that could still captivate people but could also transcend the borders of a small country like Malta so I built a game. People always argue about what things cost, like a flat in Rome, a luxury watch, or a car: I thought that argument could become a daily game for all ages.
Did you know that I got pictures for the expensive sailboats myself strolling around the Maltese Grand Harbour?
The Game
Every day everyone gets the same five items. You don't guess an exact price. You drag a slider to bet on a range, and the narrower the range, the bigger your multiplier. If the price falls outside your range, you get zero points. There's also a quick mode and head-to-head matches against friends.
How I built it
CashOrTrash is a React Native app built with Expo, for iOS and Android. The backend is NestJS with Postgres to store user data, a Redis cache and Bull queue to handle background jobs like points expiry and push notifications.
All game logic runs on the server while the app is just a UI, it shows the round and sends in the user bet and the server decides everything else to avoid cheating.
Challenges
Definitely finding good images, resizing them and removing the background was a hellish job. Every item needs a real photo of a real thing with a real price. The photos come from many different sources, in different sizes, formats and shapes.
I first cropped and polished each image in Figma, then built a pipeline that crops every image to the same 5:4 card, removes the metadata and renames the file to a hash. Before that, the file name itself could give the price away and the user could just inspect the app with a proxy to find out.
Preventing cheats
In a price-guessing game, anything that leaks the answer is a cheat.
- The server sets the 10-second timer once, and the app never sends a timestamp. Reloading a round shows you the time you have left, not a fresh 10 seconds
- You can't bet on a round the server hasn't dealt you yet
- The slider itself turned out to leak the answer. In early versions the real price almost always sat about a quarter of the way along, so a narrow bet placed there beat people who actually knew the item. Now the price's position on the slider and the slider's width are both randomised separately.
What I learned
Monetisation
The app is freemium. Daily games and matches are free and premium unlocks unlimited quick rounds. I learned to implement RevenueCat and implement monetisation in an app. What to monetise is equally important as well as the pricing logic.
Proper error handling
Handling app closures mid-game. Phones pause timers when an app goes to the background. If you left during a round and came back, the old countdown would pick up where it stopped. Now the app gets the remaining time from the server whenever it comes back, so if your time ran out while you were away, the round shows as lost.
Game fairness
My first scoring system had a big hole. Stretching the range across the whole slider was always a hit and the multiplier stopped dropping after 60% width. A lazy player could beat people making real, narrow guesses. I fixed it with some math magic. Now the lazy bet can never be the right strategy!
Built With
- claude
- expo.io
- react-native
- revenuecat
Log in or sign up for Devpost to join the conversation.