All work
Case study 02Closed beta

Zaptopia

A roguelike card battler for phones — goofy creatures, a 3D table and combos that multiply.

Role
Solo — game design, development, art direction, release
Timeline
September 2026 — ongoing
Version 1.35
Stack
TypeScript · Phaser 3 · Three.js · Vite · Capacitor · Supabase
Status
Closed testing on Google Play and TestFlight. Ask me for an invite
Roguelike deck-builder · iOS & Android
Main menu with creatures standing on the 3D table
A battle against the Grumpy Gnome on a four-lane table
The shop between fights: cards, Jokers and services

01 — The pitch

Lane battles from the board-game tradition, with the “just one more run” pull of modern roguelikes.

Four lanes, four terrains: Swamp, Volcano, Clouds and Crypt. A creature can only be played on the lane of its own terrain, so every hand is a small placement puzzle. Attack, and each creature hits the lane in front of it. Hits add to Damage; doubles, triples and all-out attacks add to Combo. The boss takes the product.

Between fights you walk a branching path — shop, campfire, mystery event, treasure — and pick up Jokers that bend the rules, Balatro-style. Runs are short, playable with one hand, and work offline.

02 — What’s in it

95
illustrated cards — 60 creatures, 35 spells
46
Jokers, four rarities, special editions
4
worlds, each with a boss and its own rule
1
daily challenge, the same deck for everyone

Around the core loop: starter decks and a deck editor, card upgrades and evolutions, an album to complete, daily missions, player levels, a login streak and cosmetics — painted card backs, animated environments, shiny creatures.

03 — Engineering

One TypeScript codebase, two renderers, both app stores.

A · Rendering

Two renderers, one screen.

Three.js draws the table, the 3D creatures and the boss environments; a transparent Phaser canvas on top handles cards, UI and input. The camera sits low across the table, like sitting opposite the boss.

WhyPhaser is great at 2D UI and game flow, Three.js at real 3D. Layering them kept each one doing what it’s good at.
CareA battery saver turns itself on for low-end phones on first launch.
B · Balance

Let a bot play it first.

A headless bot plays complete runs through the real game code, so balance changes are measured, not guessed. Before one tuning pass it won 0 of 10 runs and cleared 6.7 fights on average; after it, 1 win and 8.4 fights.

RuleCard costs follow a budget: one energy is worth about 4–5 stat points plus a small effect. Outliers get fixed.
C · Online

No accounts, no e-mail.

World leaderboards and cloud saves run on Supabase without asking players to sign up. Each phone gets a random id and a 16-character secret; the code restores progress on a new device.

SecurityTables aren’t readable from the app, wrong codes are rejected, anonymous stats can be switched off. Offline, the game simply keeps working.
D · Fairness

Pay for looks, never for power.

The whole game is free. Real money only buys cosmetics; card packs are paid for with stars earned by playing — no paid loot boxes. Rewarded videos are optional.

DetailNo emoji in the interface: a custom colour icon font keeps every symbol identical on every phone.

04 — Screens

Portrait-only, thumb-friendly, readable at a glance.

Battle: lanes, damage and combo counters, the hand of cards
Battle
World map with the next battle and a choice of path
Choose your path
Album with all 95 cards
Album
Shop selling cards, a card pack, Jokers and services
Shop

05 — Shipping

36 release builds in the first three weeks.

Every build is signed, smoke-tested on an emulator for crashes and uploaded to Google Play’s closed track and TestFlight. Testers get an in-app prompt when a new version is out, and a small news feed lets me talk to them without shipping an update.

The pipeline around the game is code too: Python scripts generate the icon font, logo variants and card backs, and a headless-Chrome script captures the store screenshots straight from the running game.