Hanabi
The cooperative fireworks card game, built for a phone screen and a private table of friends. You can only get in with an emailed invite, so the link below will show you a sign-in page and nothing else.
Hanabi is a card game played backwards: you hold your hand facing away from you, everybody else can see it, and the whole game is the table telling you just enough, one colour or one number at a time, to play the right card at the right moment. It is a lovely game to play with people you trust and a terrible one to play with strangers, which is why this version is not open to the public.
It is built for an iPhone held in one hand: your cards along the bottom thumb, the fireworks and the discard piles at the top, your friends' hands in between. Tap a teammate's card to give a clue, tap your own to play or discard. Everyone's screen updates the moment a move is made.
Who gets in
- Invite by email only: an allowlist decides who may sign in at all. There is no sign-up form, no guest mode, and an address that is not on the list gets the same polite refusal as one that is.
- No passwords to lose: signing in sends a one-time link that expires in minutes and is spent the moment it is used. The token in the link is stored hashed, so the database never holds anything a leak could replay.
- Sessions you can pull: a signed, HttpOnly, Secure cookie carries the session; revoking an address from the admin page ends every session it owns.
- The boring hardening: security headers, rate limits on sign-in and on writes, an origin check on every mutating request and WebSocket, and a Claude subprocess that runs with no tools and none of the server's secrets in its environment.
At the table
- The real rules: five colours, three 1s down to a single 5, clues that must touch at least one card, eight clue tokens, three strikes, and one final round for everyone once the deck runs dry. Twenty-five is perfect.
- Both expansions, as toggles: multicolor as a normal sixth suit, as a brutal one-of-each suit, or as a wild suit that answers to every colour clue; and the 5 Flamboyants tiles, which hand out a bonus for each completed firework instead of a clue.
- Claude fills the empty seats: bots see exactly what a player in that seat would see and reason about it before they move. Each one has a play style, from cautious to chaotic to a strict convention player, or a paragraph of instructions you write yourself.
- Bots that play like your friends: point a bot at someone who has finished a few games and it builds a profile from their logged moves, how often they clue, play or discard, how much risk they take, and imitates it.
After the game
Every move is written down as it happens: whose turn it was, what they did, what they knew at the time, and for a bot, why. When the game ends the log becomes a review: each player's clue efficiency, risky plays and critical discards, the turning points, and a short coaching note from Claude on what the table could do differently next time. An admin page cleans up abandoned tables and old games.
Built with
React 19 · TypeScript · Vite · Tailwind v4 on the phone; Express 5, SQLite and WebSockets on the server; Claude Code for the bots and the coaching. Self-hosted on a small VPS behind Caddy, deployed from a develop branch with a systemd unit. The game engine is a pure module with its own test suite, so the rules can be checked without a browser.
Not open to the public This is a private table for friends. If you know me and want a seat, ask and I will add your email to the list.