- Go 63.3%
- HTML 34.1%
- Makefile 1.9%
- Dockerfile 0.7%
|
|
||
|---|---|---|
| .devcontainer | ||
| .forgejo/workflows | ||
| api | ||
| hub | ||
| models | ||
| web | ||
| .editorconfig | ||
| .gitignore | ||
| .golangci.yml | ||
| CLAUDE.md | ||
| config.json | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.apline | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| main.go | ||
| main_test.go | ||
| Makefile | ||
| README.md | ||
Story Points Finder
A real-time Planning Poker server for agile estimation. Teams join a shared room, vote simultaneously, and reveal all votes at once to surface disagreement and reach consensus.
Getting started
Run locally
go run .
Run with Docker
make docker-build # build binary + Docker image
docker compose up # start the container
Open http://localhost:8080 in your browser.
Makefile targets
| Target | Description |
|---|---|
make build |
Compile Linux amd64 binary |
make build-windows |
Compile Windows amd64 binary |
make test |
Run all tests |
make run |
Run locally without Docker |
make docker-build |
Build binary and Docker image |
make up |
Start via Docker Compose |
make clean |
Remove compiled binaries |
How it works
- Enter a username and a room ID — the room is created automatically on first join.
- Share the room ID with your team.
- Everyone selects a card and submits their vote.
- Any participant reveals the votes once everyone has voted.
- After discussion, anyone can reset the round to start over.
Viewer mode — join with ?viewer=true in the WebSocket URL to observe without voting. Viewers can still reveal votes and reset rounds.
Planning cards
1 2 3 5 8 13 21 ? Coffee Joker
WebSocket API
Connect to ws://localhost:8080/ws?username=<name>&room=<id>[&viewer=true].
Client → Server
type |
Fields | Description |
|---|---|---|
BET_SUBMIT |
card |
Submit a vote |
WITHDRAW_VOTE |
— | Retract your vote (not allowed after reveal) |
REVEAL_VOTES |
— | Reveal all votes |
RESET_ROUND |
— | Clear votes and start a new round |
KICK_PLAYER |
targetUsername |
Remove a player from the room |
Server → Client
type |
Description |
|---|---|
CONNECTED |
Sent on successful join; includes allowedCards |
STATE_UPDATE |
Full room snapshot after any state change |
ERROR |
Operation failed; reason in roomState |
KICKED |
You have been removed from the room |
Project structure
├── main.go # Entry point
├── hub/hub.go # WebSocket hub and game logic
├── hub/hub_integration_test.go # Integration tests
├── models/types.go # Shared data structures
├── api/poker.go # Auxiliary game logic
├── web/index.html # Browser client
├── Dockerfile # Runtime image (uses pre-built binary)
├── Makefile # Build, test, and Docker targets
└── docker-compose.yml
Running tests
go test ./...
Versioning & releases
The version is baked into the binary at build time via -ldflags. Without a tag the version defaults to dev. It is visible in the browser footer, the startup log, and the /api/config endpoint.
Create a release:
git tag v1.0.0
git push origin v1.0.0
The CI pipeline picks up the tag automatically and stamps all four binaries (amd64, exe, arm64, armv7) with it before packaging the artifact.
Version format:
| Situation | Example |
|---|---|
| Exactly on a tag | v1.0.0 |
| Commits after a tag | v1.0.0-3-gabcdef |
| Uncommitted local changes | v1.0.0-dirty |
| No tags at all | dev |
License
Apache 2.0 — see LICENSE.