How a match works
- Three lanes, each with a front line and a reserve, so where a creature goes is part of the decision.
- Keyword mechanics (Shield, Taunt, Haste, Deathtouch, Poison) and activated abilities that cost SP.
- 151 cards across 10 factions, from the Order of the Veil to the Legion of the Abyss, plus neutral cards any deck can use. Each faction plays differently: aggression, control, healing, poison, summoning.
- Deck building at 30 cards, with a profile that shows the deck's "DNA": aggression, defence, control and resources.
- Offline against the AI at any time, with no connection, or online PvP with a rating that climbs on each win.
- Progression without paying: coins earned by playing, daily and weekly missions, packs to open. Purchases are optional and only shorten the road.
What I built
- The game rules as a standalone package, in pure TypeScript with vitest, with no interface and no network inside it.
- The card set and the content: 151 cards, the decks and the content i18n, in their own package.
- The app in Expo and React Native, with the screens, the components and the game store.
- The online layer as Supabase Edge Functions (finding a match, playing an action, timing out) that run the same engine on the server.
- The client-side economy: matches against the AI credit a capped daily amount, online matches pay double and are the only ones that count for missions.
- In-app purchases through Google Play Billing, with the receipt validated on the server.
- The pixel-art pipeline: cards, tokens and the pack, generated and trimmed by scripts in the repository.
Technical decisions and trade-offs
- One set of rules, run by the app and by the server. The Edge Functions import the engine bundled for them, instead of keeping a second implementation on the server. Trade-off: an extra build step, because the server artifact is generated rather than imported from source, and a discipline: a rule change has to reach both sides, or the online match plays a different game from the offline one.
- Three delivery channels, chosen per change. Interface and JS changes ship as an over-the-air update, server changes as a function deploy, and anything native needs a new build and a store upload. Trade-off: more paths to remember, in exchange for being able to fix a broken card without waiting for a store review.
- Offline-first, with online as the rewarded path. The match against the AI works with no connection; online pays double and is the only path that counts for missions, with the reward validated on the server. Trade-off: the economy needs a server rule and a daily cap; in exchange, the rewards cannot be farmed by editing the client.
- Google Play Billing for digital items, and nothing else. The game is freemium and not pay-to-win: no purchase is needed to build a competitive deck. Trade-off: the store takes its share and dictates the integration; the alternative is against the platform rules.
- A balancing rule instead of per-card tuning: a high stat has to cost a lot, and every mechanic that raises a stat or SP needs a cap. Trade-off: card design is more constrained, in exchange for a set where a single card does not decide the match.
Where it stands
Published on Google Play: 10 factions, 151 cards with finished art, online matches, daily and weekly challenges, and the in-app purchases built with receipt validation deployed. The repository stays private.