The lab · Games
Bar Darts
A darts scorekeeper for Cricket and X01, built for one group of friends.
A phone keeps score next to the board and the bar TV follows along live. Every dart is recorded against the player who threw it, so the arguments about who carried the team now have data.
- Status
- Friends only
- Domain
- Games
- Since
- 2026
- Role
- Design, engineering
The problem
Darts apps score the team, not the thrower. In doubles nobody knows who actually closed the 20s, and the chalkboard gets wiped at the end of the night.
What was built
- Cricket and X01, each with its own game logic, game screen and post-game screen.
- Team play with every dart attributed to the player who threw it.
- Live sync over WebSocket, so a phone, a laptop and the bar TV show the same game. Spectators follow from a shared link.
- History of every finished game, built from a table that records each dart.
- Player stats: win rate, Cricket marks per round, X01 three-dart average, a dartboard heatmap, trend charts, and head-to-head comparison of up to four players.
- An installable PWA that still opens on a flaky bar connection and saves the game in progress on the device first.
How it was built
- 01
Score the dart, not the turn
The data model starts at a single throw. Team totals, history and every stat are built up from that one table.
- Postgres
- Drizzle
- 02
Sync before polish
The device that scores saves over REST and broadcasts over the socket. Every other screen in the room updates from the broadcast and keeps a local copy.
- WebSocket
- Express
- 03
Make it read from across the room
Big mono numerals, amber on navy, buttons in thumb reach. The post-game screen is the only place it gets loud.
- 04
Ship to the group
Behind an access code the group shares. Feature requests arrive mid-game.
- Claude Code
- Replit
Stack
- Frontend
- React 18
- Vite
- Wouter
- Framer Motion
- Tailwind CSS
- shadcn/ui
- Recharts
- Backend
- Express 5
- A WebSocket server for room-based sync
- Drizzle ORM on Postgres
- Shared
- One schema and one set of typed WebSocket messages, imported by client and server
- Tooling
- Vitest, 120 tests on the game logic
- Claude Code
- Replit
How it works: a game is a room. The phone at the board records each dart against its thrower, saves the game, and broadcasts it to the room. The TV and any spectator link render the same state. When the game ends, its throws feed the leaderboards and each player's career page.