@yearbook2026/shared
v0.1.0
Published
Shared game rules, types and wire codecs for YEARBOOK 2026 (generated from docs/01-CONSTANTS.md)
Readme
@yearbook2026/shared
Game rules, wire types and binary codecs for YEARBOOK 2026. Consumed by both repos (kit tooling and the server) so there is exactly one copy of every number.
src/constants.ts is generated from yearbook-kit/docs/01-CONSTANTS.md. Change the
doc first, then the file; test/constants.doc.test.ts re-reads the doc in CI and fails
on any drift. Never inline a game-rule number anywhere else. Server-internal tunables
(tile size, TTLs, rate limits) belong in yearbook-server/docs/05-ARCHITECTURE.md, not here.
Contents
| Module | What |
|---|---|
| constants.ts | canvas size, price(n), immunity, freeze, free tier, payment identifiers |
| palette.json / palette.ts | the locked r/place 2022 32-colour palette + loader. Index 0 = blank/white; wire order, never reordered |
| types.ts | Pixel, Job, Quote, Receipt, PixelMeta, DiffFrame, ErrorCode (04-API / 03-PROTOCOL shapes) |
| codecs/w1.ts | snapshot / region grid: row-major w*h bytes, one palette index per pixel, no header |
| codecs/w2.ts | WS diff frame: u8 version, u32 seq, u16 count, count × {u16 x, u16 y, u8 c, u8 kind} |
Money and time rules baked in
- Integer USDC atomic units (6 decimals) everywhere;
price(n)uses capped doubling, never<<(n is a u16 in storage and a 32-bit shift would wrap instead of saturating). - Epoch ms, UTC.
isFrozen(t)is the single freeze test: writes are valid ifft < FREEZE_AT. immunityMsAt(t)switches 60s → 30s atDECEMBER_SWITCH_AT.
Open items (human decisions, not agent-fillable)
LAUNCH_AT,YEARBOOK_DOMAIN—nulluntil decided.
W2 byte order is big-endian, locked in 04-API "Wire formats" — not an open item.
Commands
npm install # from the yearbook-kit root (workspaces)
npm test -w @yearbook2026/shared
npm run build -w @yearbook2026/shared