A websocket scrum poker web app built on top of the SmallOS framework.
The app now runs one premium permanent room plus a pool of ephemeral GUID rooms on one cooperative SmallOS runtime. A shared host task owns the listener, public landing/setup flow, room registry, and expiry cleanup.
- Join a session with your name
- Create ephemeral rooms from
/setupRoom - Auto-claim admin in the room you just created
- Promote yourself to admin with the room password or
SUPER_USER_PASSPHRASE - Keep one configurable premium room locked behind its premium admin password
- Cast point votes in real time
- Switch between point voting and 128-character short answers as an admin
- Mark short answers Ready or Not Ready before revealing them
- See when teammates have voted without revealing hidden values
- Show or hide all votes on the board
- Discard the current round's votes
- Open and close joining from the browser as an admin
- Kick users off the board as an admin
- Show admins with a badge on the board
- Control room sessions from the SmallOS shell
- Includes a top-right
Powered by SmallOSlink to the upstream project - Serves HTML, CSS, and JavaScript from external static asset files
- Keeps a browser session token so refreshes preserve the same joined/admin status
- Destroys expired ephemeral rooms fully so room state does not accumulate in memory
- Uses one namespaced terminal shell to control the premium room and active GUID rooms
- Python 3
- Git (used by
pipto install SmallOS from GitHub)
Install the Python dependencies before running the app:
python3 -m pip install -r requirements.txtSmallOS is pinned to a specific upstream commit in requirements.txt so installs are reproducible.
From the project root:
cp .env.example .env
# edit .env and set PREMIUM_ROOM_* / SUPER_USER_PASSPHRASE
# optionally change HOST / PORT
python3 app.pyThen open:
http://127.0.0.1:8082/
http://127.0.0.1:8082/setupRoom
http://127.0.0.1:8082/premium
If you set PREMIUM_ROOM_SLUG=yourcompany, that last URL becomes http://127.0.0.1:8082/yourcompany.
If you leave HOST=0.0.0.0, the app binds on all local interfaces so other devices on your LAN can reach it using your machine's local IP address and the configured PORT.
When the app starts, it also opens a SmallOS shell in the terminal.
Useful commands:
poker rooms: list the premium room and every active ephemeral GUID roompoker apps: alias forpoker roomspoker premium session open: allow new users to join the premium board whenPREMIUM_ROOM_SLUG=premiumpoker premium session close: prevent new users from joining the premium board whenPREMIUM_ROOM_SLUG=premiumpoker <guid> session open|close|status|toggle: manage an active ephemeral roompoker <room_id> idle status: inspect the idle timer for one roompoker <room_id> clear everyone: kick everyone off one room and close its sessionps: list running SmallOS tasksstat <pid>: inspect a tasktoggle: switch between shell output and application outputhelp: show available commands
Users can:
- Visit
/setupRoom, choose a room password, and get redirected into a private GUID room - Enter a display name and join the session
- Click
Become Admin, enter the room password, and receive success or failure feedback - Vote using the on-screen cards
- Enter a short answer and explicitly mark it Ready when the room is in short-answer mode
- See who has already voted
- Reveal or hide the board
- Clear the current round
Admins can:
- Open the session for new users
- Close the session for new users
- Kick users off the board
- Switch the room between Pointing and Short Answer modes
- Appear with an
Adminbadge beside their name
The creator of a new ephemeral room is auto-promoted to admin in that browser session. Premium-room admin access uses PREMIUM_ROOM_ADMIN_PASSPHRASE, then falls back to ADMIN_PASSPHRASE, and SUPER_USER_PASSPHRASE works everywhere.
Refreshing the page in the same tab keeps the same browser session token, so the user stays associated with the same name, vote, and admin status during reconnects. Separate tabs use separate tab identities so they do not fight over the same websocket session.
Each GUID room and the premium room use different browser storage keys, so you can keep multiple rooms open in one browser without their names or reconnect tokens colliding.
While votes are hidden:
- each user still sees their own vote
- other users only appear as "voted" or "waiting"
Ephemeral room limits:
- max
19active public rooms at once - max
8named participants per ephemeral room - automatic cleanup after
5minutes with no joined users - hard expiry after
2hours from creation - idle destruction after
1hour with no activity
Premium room limits:
- defaults to
/premium, or whatever you set withPREMIUM_ROOM_SLUG - max
20named participants
/: landing page/setupRoom: public room setup page/api/rooms: create a new ephemeral room/healthz: host health check/premium: default premium room UI/premium/ws: default premium room WebSocket endpoint/premium/api/state: default premium room JSON snapshot/premium/healthz: default premium room health check/<guid>: ephemeral room UI/<guid>/ws: ephemeral room WebSocket endpoint/<guid>/api/state: ephemeral room JSON snapshot/<guid>/healthz: ephemeral room health check/static/app.cssand/static/setup_room.js: host-level setup/landing assets/<room>/static/app.cssand/<room>/static/app.js: room assets
The lightweight GitHub Actions workflow in .github/workflows/tests.yml runs on pushes to master, pull requests, and manual dispatches. It installs the pinned SmallOS dependency, runs the focused test suite, and checks Python and JavaScript syntax.
When a pull request is merged into master, .github/workflows/release.yml creates a GitHub Release. Releases use the next vX.Y.Z patch version after the latest semantic-version tag (for example, 1.0.0 becomes v1.0.1) and include automatically generated release notes.
Focused scrum poker tests:
python3 -m unittest tests.test_scrum_poker_app tests.test_smallos_websocket_server -vLocal benchmark helper:
python3 benchmark_scrum_poker.pyapp.py: executable SmallOS entrypoint and premium-room compositionscrum_poker_app.py: mounted scrum poker room class and idle watchdogscrum_poker_core.py: shared poker state helpers, HTTP helpers, dotenv loading, and runtime wiring utilitiesscrum_poker_host.py: shared host/router, public setup flow, and ephemeral room registryscrum_poker_shell.py: SmallOS shell commands for premium and GUID roomsbenchmark_scrum_poker.py: lightweight benchmark for room fanout behaviorsmallos_websocket_server.py: local SmallOS-friendly websocket server helper used by the appsmallos.config.json: SmallOS runtime configuration for this applicationrequirements.txt: Python dependencies, including the pinned SmallOS Git dependency.env.example: sample environment file for premium-room slug/label/admin settings, super-user access, and global limitsstatic/index.html: room page markupstatic/landing.html: public landing pagestatic/setup_room.html: room setup pagestatic/app.css: shared UI stylingstatic/app.js: client-side websocket and room UI logicstatic/setup_room.js: room creation flowtests/test_scrum_poker_app.py: tests for room creation, auth, cleanup, and shell controlstests/test_smallos_websocket_server.py: tests for the local websocket server helper