FTC

Realtime multiplayer card game with a server-authoritative rules engine.

Services
Product DesignEngineering
Industries
Realtime
Tools
Next.jsSupabaseTypeScript
Highlight
No client decides the outcome.
Live
ftc-game.vercel.app

Top trumps, and the oldest problem in multiplayer

The game is simple: pick a universe, pick a deck, and call the strongest stat on your top card. The problem underneath it is not simple at all, and it is the one every multiplayer game meets on day one — if the client knows what the other player is holding, the game is over.

A card game is the purest version of this. Every card is data, the whole deck has to reach the device somehow, and the moment it does, the outcome is decidable before anyone plays.

Fifty-two cards, eight stats
Rooms, in realtime
A cover is a card back
A universe, a deck of fifty-two, and eight stats to call.

What a deck has to be before it can be played

Decks are content, and content that is wrong breaks a game rather than looking bad. The rule is explicit: a deck needs fifty-two cards, eight stats, complete stat values for every card, and a cover image before it can be made playable. The cover doubles as the card back in play, which is a small thing that makes an authored deck feel finished.

Rooms and turns run over Supabase Realtime — the same shape as the rest of these projects, because a Postgres that can broadcast removes the need for a game server.

Every card is data, and data on a client is data the client can read. Where the comparison happens is the whole design.

Game
Fantasy trump cardsUniverse then deckCall the strongest stat
Decks
52 cards8 statsCover doubles as the back
Realtime
Supabase RealtimeRooms, create or joinSupabase Auth
Stack
Next.js 15React 19Framer Motion + GSAPVercel
Pick a universe
Create or join a room
Call the stat

01 / 03

What it cost

Two animation libraries is one more than a project should have. Framer Motion and GSAP are both here — Motion for component transitions where it is genuinely nicer, GSAP for anything scrubbed or sequenced. It works and it is a cost, and if this were rebuilt today it would pick one.

Deck authoring is where the real work is. Fifty-two complete cards across eight stats is a spreadsheet problem, and the validation rule exists because a deck that is 95% filled in is a deck that produces a broken round somewhere in the middle of a match.

Where it does not work yet

The rules engine is not documented, and this page will not pretend otherwise. The thesis of the project is that no client decides the outcome; what the repository actually shows is Supabase Realtime, Supabase Auth and a deck schema. Whether comparison is server-side today, and where it runs, is not written down anywhere a reader could check.

That gap is the next thing worth closing — not because the code is necessarily wrong, but because on a card game "trust us, the server decides" is a claim that has to be readable to be worth anything.