Skip to content
Shaurya Punj, WorkServer authoritative
Own the world · 72 tiles · 59 countries

DOMINION

The server owns the only true board.

A real-time, server-authoritative multiplayer property-trading game for 2 to 8 players. Buy 59 countries, build houses and hotels, run live auctions, and bankrupt each other on a 72-tile board — rebuilt on a pure deterministic engine so every match is provably fair and replayable.

2–8 players · provably fair · byte-identical recovery
The one rulethe client never computes anything that matters
SERVER-AUTHORITATIVE/SEEDED DICE/EVENT-SOURCED/ZERO DESYNC/72 TILES/59 COUNTRIES/20 TIERS/2–8 PLAYERS/BYTE-IDENTICAL RECOVERY/ZOD CONTRACT/NO CLIENT TRUST/LIVE AUCTIONS/ATOMIC TRADES/TURN TIMER/SERVER-AUTHORITATIVE/SEEDED DICE/EVENT-SOURCED/ZERO DESYNC/72 TILES/59 COUNTRIES/20 TIERS/2–8 PLAYERS/BYTE-IDENTICAL RECOVERY/ZOD CONTRACT/NO CLIENT TRUST/LIVE AUCTIONS/ATOMIC TRADES/TURN TIMER/
The thesis

Online board games break four ways. DOMINION fixes all four.

01Desync

The client is trusted to compute state

One authoritative server owns the only true board

02Cheatable

Dice and money live on the client

Seeded, server-side dice; money never touches the client

03Stalls

One dropout freezes the whole table

Reconnect, plus an optional per-turn timer

04Small board

40 tiles, 28 properties

72 tiles · 59 countries · 20 tiers

The DOMINION world board — a holographic gold globe ringed by 59 country tiles, with skyscraper title cards for New York, London, and Hong Kong.
The world, as a board
The problem

Nobody owns the truth.

Online board games desync, because the client is trusted to compute state. They are cheatable, because the dice and the money live on that same client. They stall the moment a player drops. And the classic board is small — 40 tiles, 28 properties.

DOMINION fixes all four at the root. One authoritative server owns the only true board. Dice are seeded and rolled server-side. An optional turn timer keeps a dropout from freezing the table. And the board grows to 72 tiles, 59 countries, and 20 tiers — until every street owns the world.

The architecture

Four parts. One source of truth.

Engine

pure

apply(state, action) returns the next game — zero side effects. Pure reducer + seeded dice means the whole match is a deterministic replay.

Contract

Zod

Every message is Zod-validated on the way in. The wire is the schema; nothing malformed ever reaches the engine.

Server

authoritative

Fastify + Socket.IO, one gate: rate-limit → validate → force identity → apply → broadcast. The client is never trusted.

Web

render-only

The client only renders server state. It computes nothing that matters, so a desync is not even representable.

The DOMINION board interface — a tilted holographic board with a Pennsylvania Avenue title deed, its full rent ladder from one house to a hotel, and houses upgrading to a hotel.

Every street is a real title deed. The rent ladder climbs exactly as the deed says — 72 properties, until every street owns the world.

The board
0tiles on the board, up from the classic 40
0countries to buy, build, and bankrupt across
0property tiers, from Baltic to New York
2–0players per table, all in real time
0client-side trust — the server owns the truth
0%deterministic — byte-identical crash recovery from Postgres
The table, live
What it ships
01

Real-time authoritative multiplayer — no client trust, no desync. One server owns the only true board and broadcasts it to everyone.

02

Live auctions the instant a property is declined, every bid validated server-side.

03

Houses to hotels with real title-deed rent ladders — the rent climbs exactly like the deed says.

04

Deep trading — cash, property, and jail cards, swapped atomically or not at all.

05

Never stalls — reconnect mid-match and an optional turn timer stops one dropout from freezing the table.

06

Provably fair and crash-proof — seeded dice, an event-sourced action log, and byte-identical recovery.

The stack

Client

TypeScriptNext.js 15React 19Zustandframer-motionTailwindsocket.io-clientPlaywright

Server

NodeFastify 5Socket.IO 4.8ZodHMAC tokenspinoPrometheusSentry

AI

None — by designDeterministic + auditableNo black box(that is the flex)

Data

PostgreSQL / DrizzleRedis (optional)Event-sourced log + snapshotslocalStorage
System architecture
01Create room
02Join by code
03Ready + pick piece
04Host starts
05Roll + move
06Buy / Auction / Rent
07Build / Trade / Mortgage
08Jail / Bankruptcy
09Win
10Persist + Recover
Client
  • Pages
  • Store · Zustand
  • Components
  • Renders server state only
Contract
  • Zod schemas
  • Every message validated
  • The wire is the schema
Server
  • Gate: rate-limit → validate → identity → apply → broadcast
  • Rooms
  • Auth · HMAC
  • Turn timer + kick
  • Observability · pino / Prom / Sentry
Engine
  • Pure reducer · apply(state, action)
  • Seeded RNG
  • 72-tile board
Data
  • Drizzle + Postgres
  • ActionLog · event-sourced
  • Snapshotter
  • Recovery · byte-identical
The film
The reel
Hardening a fake multiplayer engine

No client trust. No desync.

  • One authoritative server, the only true board.
  • Seeded server-side dice — provably fair.
  • Event-sourced log — byte-identical recovery.
Why this one

I made the client stop lying.

Every online board game I played eventually desynced, or let someone nudge the dice, or froze the moment a friend’s phone died. The bug was never the game — it was the architecture. The client was allowed to compute things it had no business computing.

So I rebuilt it around a single idea: the server owns the only true board, and the client only draws it. A pure engine, a validated contract, seeded dice, and an event-sourced log. Because the whole match is a deterministic replay, a server can crash and come back byte-identical from Postgres.

No AI, on purpose — every number is auditable, nothing hides in a black box. It is a small game with a serious spine, and I would run a tournament on it tomorrow.

Until every street owns the world

TAKE THE TABLE

Want to see a full match, or help build it out? Book a live demo, or bring ideas and pull requests — the engine is open to contribution.