Β
Β
Estimate user stories together in real time β free, no account required.
Features β’ Quick Start β’ How It Works β’ Development
Β
- π Real-time rooms β a tiny PartyKit room server on Cloudflare's edge keeps everyone in sync over WebSockets; rooms survive host refreshes and reconnects
- π Friendly room codes β six-character codes (e.g.
PKD8QC) that are easy to read out loud or paste in chat - π Multiple deck presets β Fibonacci (0β21 + ? + β), Numeric, T-shirt (XSβXXL), or a fully custom deck; your favourite is remembered for next time
- π° Casino-style reveal β votes stay face-down on the felt until the host flips them all at once
- π€ Speaker ritual β after the reveal, pass the mic: highest vote explains first, lowest second, then the rest; space drives the whole flow
- β¨οΈ Hotkeys β 1β9 to vote, space to reveal / next speaker / new round
- π€΅ A table with a soul β a pixel croupier announces rounds and commentates results, a waiter delivers coffee when someone plays β, and a cat wanders by (it purrs if you're lucky)
- π Subtle sound design β synthesized card swishes, reveal flips, consensus chimes; one-click mute, persisted
- π Pixel-art avatars β DiceBear-generated, selectable on join and changeable mid-session
- π Consensus confetti β fires automatically when everyone votes the same value
- π± Mobile-friendly & installable β a roster layout on phones and a PWA manifest for Add-to-Home-Screen
- π Dark & light theme β toggled with a single click, preference persisted across sessions
# Clone and install
git clone https://github.com/kud/planning-poker.git
cd planning-poker
npm install
# Start the PartyKit room server and the Next.js dev server
npm run party:dev # terminal 1 β ws://127.0.0.1:1999
npm run dev # terminal 2 β http://localhost:3000Open http://localhost:3000 in your browser.
- Click Create room β a six-character room code and shareable link are generated instantly.
- Share the link (or code) with your team.
- Each guest opens the link, picks a name and avatar, and joins.
- Everyone votes; the host clicks Reveal to flip all cards simultaneously.
- Celebrate consensus with confetti, or discuss and re-vote.
Host ββββββββββββββββ
β WebSockets
Guest 1 ββββββββββββββββ€
Guest 2 ββββββββββββββββΌβββΊ PartyKit room server (Cloudflare edge)
Guest 3 ββββββββββββββββ βββ authoritative room state
Each room is a stateful PartyKit server running on Cloudflare's edge (free tier). Every participant β host included β connects over a WebSocket; the server holds the authoritative room state and broadcasts every change to all connections. The deck and host identity are persisted in room storage, so the room survives refreshes and reconnects.
Hosting is a capability, not a page: creating a room generates a secret kept in localStorage, and whoever presents it to the room server gets the host controls. No accounts, no database.
| Route | Purpose |
|---|---|
/ |
Landing page β create or join a room |
/room/[id] |
The room β vote and watch results |
| Preset | Cards |
|---|---|
| Fibonacci | 0, Β½, 1, 2, 3, 5, 8, 13, 21, ?, β |
| Numeric | 1 (XS), 2 (S), 4 (M), 8 (L), 16 (XL), 32 (XXL) |
| T-shirt | XS, S, M, L, XL, XXL |
| Custom | Comma-separated values of your choice |
party/
βββ index.ts # PartyKit room server β authoritative state
src/
βββ app/
β βββ page.tsx # Landing β create or join
β βββ room/[id]/ # The room view
βββ components/
β βββ room-view.tsx # Core voting UI
β βββ participant-card.tsx
β βββ playing-card.tsx
β βββ avatar-picker.tsx
β βββ deck-selector.tsx
β βββ settings-dialog.tsx
β βββ vote-summary.tsx
β βββ ui/ # Base UI primitives
βββ hooks/
β βββ use-party-room.ts # WebSocket connection & room actions
β βββ use-share-room.ts # Copy room code / link
βββ lib/
βββ decks.ts # Deck presets & parser
βββ room-code.ts # Room code generation
βββ types.ts # Shared TypeScript types
βββ settings.ts # localStorage persistence
βββ avatar.ts # DiceBear helpers
βββ utils.ts # Shared utilities
| Script | Description |
|---|---|
npm run dev |
Start Next.js dev server with HMR |
npm run party:dev |
Start the PartyKit room server locally |
npm run party:deploy |
Deploy the room server to PartyKit |
npm run crew -- CODE |
Inject auto-voting fake users for testing (--count N, --prod) |
npm run build |
Production build |
npm run start |
Serve the production build |
npm run lint |
Run ESLint |
The client connects to NEXT_PUBLIC_PARTYKIT_HOST when set, and falls back to
127.0.0.1:1999 in development and planning-poker.kud.partykit.dev in
production builds.
| Package | Purpose |
|---|---|
| Next.js 16 | React framework & routing |
| React 19 | UI rendering |
| PartyKit | Real-time room server (WebSockets) |
| Framer Motion 12 | Card flip & flying-card animations |
| Base UI | Unstyled accessible primitives |
| Tailwind CSS v4 | Utility-first styling |
| DiceBear | Pixel-art avatar generation |
| canvas-confetti | Consensus celebration effect |
| Lucide React | Icon set |
MIT Β© kud β Made with β€οΈ
