Skip to main content
Version: 2.0 PartyKit

Tech Stack

Production stack (v2.0 PartyKit)​

LayerTechnologyNotes
FrontendAstro 5 (static) + React 19 islandsZero JS by default; interactivity only where needed
StylingTailwind CSS v4Utility-first; no design system dependency
StateZustandOne store each for host and participant
WebSocketsPartySocket (partysocket)Drop-in wrapper with auto-reconnect
BackendPartyKit (Cloudflare Workers + Durable Objects)One DO instance per game session
PersistenceDurable Object storage (SQLite-backed)Game state survives DO eviction
Session indexCloudflare KV (SOMMELIER_HOSTS namespace)Maps host:{id} β†’ list of session codes
DNS + TLSCloudflare (ducatillon.net)Managed; zero cert renewal
Docs proxyCloudflare Worker (proxy-worker/index.ts)Routes /docs/* to Docusaurus Pages project

Design principles​

  1. No server to maintain β€” Durable Objects are managed infrastructure; no VMs, no Docker in production.
  2. €0/month β€” Cloudflare free tier covers all traffic for a casual dinner-party app.
  3. Islands architecture β€” Astro renders everything at build time; React hydrated only for the game UI.
  4. State machine discipline β€” All business logic in back/game.ts. The frontend projects server state.
  5. Single source of truth β€” Session state is DO built-in storage. No database, no ORM.

Backend​

back/ β€” PartyKit Durable Object game logic (back/game.ts). This is the real-time game server.

Why PartyKit over plain Durable Objects?​

ConcernPlain DOPartyKit
WebSocket fan-outManual this.state.getWebSockets()this.room.broadcast()
Local devwrangler dev (requires auth)npx partykit dev (no auth)
Deploywrangler deploynpx partykit deploy
Free tierYesYes