# proto-poker-cf — LLM ACCESS NOTES Free, no-signup planning poker. Create a room, share the link, vote on a Fibonacci deck, reveal together, start a new round. No accounts, no subscriptions, no third-party realtime vendor. **Live app:** https://poker.eswat2.app **Repo:** https://github.com/eswat2/proto-poker-cf > This is a client-rendered single-page app (vanilla Web Components, no > framework). The raw HTML at `/` is nearly empty until JavaScript runs — > fetch this file or `/manifest.json` instead of scraping page source for > anything meaningful. ## What it is - Runs on Cloudflare Workers; each room is a Durable Object. - Rooms are ephemeral — no accounts, no login. A room closes after 1h with no changes and nobody connected, 2h with no changes regardless, or 4h after creation, whichever is first. The room state's `closesAt` says when. - Real-time sync is a WebSocket per browser to the room's Durable Object, with Server-Sent Events as a fallback (server push only — actions are plain HTTP POSTs). - Default card deck: 1, 2, 3, 5, 8, 13, 21, ♠ (wildcard), ? (need more info). - Any participant can reveal votes, start a new round, or edit the topic. Only the creator can close the room early, using the `ownerToken` returned when the room was created (`POST /api/rooms/:roomId/close`). ## Docs - [README](https://github.com/eswat2/proto-poker-cf/blob/main/README.md) — overview and local dev setup - [ARCHITECTURE.md](https://github.com/eswat2/proto-poker-cf/blob/main/docs/ARCHITECTURE.md) — full design rationale, decision log, data model, API - [CLAUDE.md](https://github.com/eswat2/proto-poker-cf/blob/main/CLAUDE.md) — guidance for coding agents working in this repo - [FEATURES.md](https://github.com/eswat2/proto-poker-cf/blob/main/docs/FEATURES.md) — backlog of features not yet built - [/architecture](https://poker.eswat2.app/architecture) — visual system diagram - [/manifest.json](https://poker.eswat2.app/manifest.json) — machine-readable API index ## API — https://poker.eswat2.app/api All JSON in/out. No accounts, no server-side sessions. Creating a room requires a creator key in an `x-create-key` header (`401` without it); everything under `/api/rooms/:roomId` is open to anyone with the room id, using a client-generated `participantId`. See `/manifest.json` for the full structured endpoint list. Every mutation route is rate-limited (per `participantId`+room and per source IP+room) and returns `429` with a `Retry-After` header if exceeded. Requests for room ids that don't exist are also capped per IP across all room routes. Example flow: ``` # create a room curl -s -X POST https://poker.eswat2.app/api/rooms \ -H 'Content-Type: application/json' -H 'x-create-key: ' \ -d '{"name":"Alice"}' # -> {"roomId":"brave-otter-k7m2qx9p","participantId":"...","ownerToken":"..."} # cast a vote curl -s -X POST https://poker.eswat2.app/api/rooms/brave-otter-k7m2qx9p/vote \ -H 'Content-Type: application/json' \ -d '{"participantId":"...","value":5}' # reveal curl -s -X POST https://poker.eswat2.app/api/rooms/brave-otter-k7m2qx9p/reveal \ -H 'Content-Type: application/json' \ -d '{"participantId":"..."}' ``` Realtime updates for a room come two ways, carrying the same full room state on connect and after every mutation above: - Server-Sent Events at `GET /api/rooms/:roomId/stream` — easiest from a script: `curl -N https://poker.eswat2.app/api/rooms/brave-otter-k7m2qx9p/stream`. Each change is a `data:` line of JSON; `: ping` comments arrive every 25s; when the room closes, a final `event: closed` frame carries `{ "code", "reason" }` and the stream ends. - WebSocket at `GET /api/rooms/:roomId/ws` — the state as a JSON text message; send `ping` to get `pong`. When the room closes, a final `{"event":"closed","code","reason"}` message arrives, then the socket is closed with the same code: 4404 (idle), 4408 (lifetime) or 4410 (closed by host).