← Portfolio

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

  1. 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
  2. 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
  3. 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.

  4. 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.