Ballrs is a multi-sport player guessing game live on iOS and Android. Seven game modes, four sports, twenty-eight daily puzzles.
Built with React Native using AI-assisted development. I'm a designer, not a developer. AI closed the gap.
Poeltl proved sports fans love daily puzzle games. NYT Games proved the multi-game collection model works on mobile. I hadn't seen anyone combine the two. The daily puzzle space was scattered. Single sport, single game, mostly web-only. Ballrs puts it all in one app.
| Feature | Poeltl | NYT Games | Ballrs |
|---|---|---|---|
| Native App | ✗ | ✓ | ✓ |
| Multi-Sport | ✗ | ✗ | ✓ |
| Multi-Mode | ✗ | ✓ | ✓ |
| Mobile-First | ✗ | ✓ | ✓ |
The original concept was a Poeltl clone. A stat comparison grid. But that format rewards process-of-elimination thinking, not sports knowledge. Switching to text-based clues made the game accessible to casual fans, not just stat nerds. Six clues, one mystery player. You either know it or you don't.
"Why not Wordle with player names?" Player names aren't stored in your brain the way English words are. You know Jaylen Brown plays for Boston, not that his name is five letters ending in OWN. When you see _R_WN on a Wordle board, your brain can't do the passive scan it does with regular words. You'd have to consciously go through every team and roster. That's work, not a puzzle. That constraint shaped the entire game format.
Launched with the core game, validated it, then added new modes every few weeks. Each release included a feedback form. Users told me what worked and what didn't, and I shipped fixes the same day.




"Clue Drop scoring: 6 points for 1 clue, down to 1 for 6." Simple and intuitive. Rewards knowledge depth. No complex multipliers, no bonus rounds. You either knew it early or you didn't.
"Feedback form on the 5th play, not the 1st." First play is too early. By the 5th play, users have formed a real opinion. Every new game mode launched with a feedback form built in.
"Server-side game logic." Originally client-side. Moved everything to Supabase Edge Functions after realising client-side scoring was exploitable. Security is an architecture decision, not a feature.
"Over Under: two problems in one game." League position questions were counterintuitive. 43 out of 1,041 questions had users selecting UNDER when the answer was OVER. Added contextual hints like "Lower number = higher finish." Then changed the buttons from red and green to neutral colours. Red for "higher" felt wrong to users.
"Duels: killed live, went async." Real-time meant Player 1 sits waiting if Player 2 doesn't show. A 48-hour async window fixed it. If both players are online, it still feels live.
The home screen changed three times. Not because it was broken, but because the product outgrew it. One game mode became seven. A simple grid wasn't enough anymore.


"The dashboard was the right call for one game. It gave each sport its own space with leaderboards, streaks, and duels. But it couldn't hold seven game modes per sport. The vertical list solved that. Every game mode is visible immediately. Sport tabs filter if you want, but the default shows everything. The layout scales to any number of games without redesigning the screen."
The first version of onboarding was static instruction cards. Text explaining how each game mode worked. Nobody reads instructions for a trivia game. Replaced them with animated demonstrations that simulate actual gameplay.
For existing users who had already passed the onboarding, these screens didn't exist. But new game modes still needed explaining. Built a separate set of introduction screens that appear the first time an existing user opens a new game mode. Same animated approach, just contextual.

"No email, no friction." Account creation asks for a username (with a random generator if you can't think of one), a flag to represent where you're from, and nothing else. No email required. At level 5, the app asks if you want to link an email to protect your progress. By then you've got streaks, XP, and unlocks worth keeping. Users link their email because they want to, not because they had to.
"Profanity filter from day one." Random name generator and custom usernames both run through a profanity filter. Learned this the hard way when a leaderboard username had to be manually corrected in the database.
Bold, tactile, high contrast. Thick black borders, offset shadows, and sport-specific accent colours. Every element follows one rule: if it's filled with colour, you can tap it. If it's white, it's information.
The icon went through three versions. The final one uses the neubrutalist pill shape from the app's button system.
Custom icons generated with AI (Nano Banana) in the neubrutalist style. Bold outlines, solid fills, no gradients. Unlocked as players level up.
Every day, every sport, every game mode resets. 28 puzzles daily. The engagement system ties it all together. Streaks, XP, levels, duels, and leagues give players reasons to keep playing beyond the puzzles themselves.


"The level-up moment is intentionally dramatic." Full-screen modal, confetti animation, spring bounce, haptic feedback. In an app with no sound effects and minimal animation elsewhere, this moment stands out on purpose. It tells the player: this matters.
"Review prompt on the 5th win, not the 5th play." Asking happy players, not frustrated ones. Limited to 3 prompts total (games 5, 25, 50) with 60-day cooldowns.
"Ad slots from day one, not day one hundred." The app ships with Ballrs-branded banners in every ad slot — home screen, leaderboard, leagues, profile, duel results. No paid ads yet. But when a sponsor fills the slot, nothing changes for the user. The experience stays the same. "I want to start with ads because I don't want the experience to suddenly change for people."
"Archive replay exploit." Users could give up on a puzzle and replay it later for full first-completion rewards. Failed attempts weren't creating completion records, so the system treated every retry as the first attempt. Fix: a completion record is created the moment a user finishes a puzzle — win, lose, or give up. First finish counts. After that, it's a replay. Full XP on the first replay, nothing after that.
Shipping a live product means things break. These are the biggest problems I hit and how I fixed them.
All game logic ran client-side. XP, points, streaks, duel winners. Anyone with basic tools could cheat. Fix: rewrote everything as server-side Supabase Edge Functions. The client sends what happened, the server decides what it's worth. "If users can gain an advantage by lying to your server, they will."
Backend went down the same day the app launched on Google Play. App wouldn't load past the splash screen. Turned out to be a regional AWS outage in US East, not a capacity issue. Lasted about 90 minutes. Paused all promotion until it was back.
The app opened, splash screen appeared, then died. No JavaScript errors. Nothing in the console. Had to learn ADB logcat to find it. The error was native code corruption in a library. Fix: cleared the cache and rebuilt from scratch.
43 out of 1,041 questions had counterintuitive answers because "higher" and "lower" mean different things in different sports contexts. Users were getting the right answer marked wrong. Fix: contextual hints on every affected question.
I built a pipeline to produce trivia videos for YouTube and TikTok (detailed in Growth). One of them had a mistake.
Carmelo Anthony was listed as having played for the Nets. He didn't. A viewer caught it on a published video. Fixed the database, left the video up to preserve engagement, and established a verification rule for all future content.
The product works. 7.44 sessions per device proves retention. 44% store conversion proves the listing works. The challenge is getting the app in front of new people.
Apple Search Ads drove installs at $2.84 each with a 40% tap-to-install rate. Best keywords: "sports trivia" at 64% conversion and "trivia" at 69% conversion. Meta Ads got 107 clicks and zero attributed installs. Paused it. Apple targets people searching for apps. Meta targets people scrolling their feed. Different intent entirely.
I made the ads too. Two approaches: a fake group chat to mimic organic sharing, and a gameplay video showing the UI.
"The ads set the expectation for the habit." These aren't just install drivers. They show the daily loop — puzzles resetting, streaks building, duels firing. Users who download after watching already understand the rhythm.
Designed QR code stickers linking to the App Store. Took them to sports bars showing live games. One outing: about 10 people scanned and downloaded. People watching sports in a bar, you show them a trivia app about sports. The context sells itself.
Landing page for app store links, privacy policy, and social media bios. Hosted on Vercel. Redesigned once with all seven game modes, scroll animations, and a stats ticker. After someone on Reddit flagged missing security headers, added them the same day via vercel.json.
Two tools I built to produce marketing content faster:
Converts screenshots and screen recordings into device mockups. Built frames for iPhone 16 Pro and Google Pixel 7a.
Pick a sport and questions, pull player photos from Wikipedia, generate voiceover via ElevenLabs, paste one render command. Idea to finished video in under 5 minutes.
"The product converts. The problem is getting people to the listing." 44% of everyone who sees the App Store page downloads the app. Discovery, not conversion, is the bottleneck. Everything in this section — ads, stickers, content tools, the website — is about solving that one problem.