Repository navigation
Releases: nishadsukumaran/smash-queue
Release list
v1.1.0 — SmashQ
SmashQ v1.1.0: new brand, accounts for every player, owner-run communities and push notifications. Live at https://smashq.aiopsgroup.ai
New
- Shuttle Q brand. New mark and SmashQ wordmark in the app, new app icons, full kit in
docs/brand. - Accounts for everyone. Register with a 4-digit email code; every account gets a player number (#1001 on) and a phone PIN.
- Owner-run communities. Players ask for a community, the platform approves, the requester owns it. The platform admin can also start one directly for a named owner. Public or private; open, approval or invite-only.
- Push notifications. Put on court, waitlist spot opened, community notices, invitations, day-of reminder. One-tap prompt after booking and in the home-screen app.
- New home screen. Live court card, "you tonight", upcoming sessions, notices and recent fairness.
- Short codes. 4-digit sign-in codes and 4-character invite codes, protected by per-address daily and per-account hourly guess limits.
- PIN control. Owners can switch the shared coordinator PIN off; ten wrong guesses in an hour lock it.
Fixed
- Live court board and session page crashed while a session was live.
- Header hid behind the iPhone status bar in the home-screen app.
- Finished sessions now count players who left early in "played" and fairness.
- Expired sign-in tokens were pruned too early, which reset the rate limits.
Upgrading a self-hosted copy
- Run
npm run db:migrate(migrations 0008 to 0010). - Set
CRON_SECRET, and for pushNEXT_PUBLIC_VAPID_PUBLIC_KEY+VAPID_PRIVATE_KEY(seedocs/DEPLOYING.md) before deploying. - Existing 8-character invite codes keep working until an owner replaces them.
v1.0.0 — Smash Queue
Smash Queue is a badminton session manager for real WhatsApp groups: players book from a link, scan a QR at the door, and their phone answers "when am I next?" so the coordinator stops being asked. Feature-complete against PRD §31, tested, and running in production at smashq.aiopsgroup.ai.
What it does
| Fair rotation | A queue engine that bands players by games played and walks the bands, so fairness is structural rather than a weight that team balance can outbid |
| QR check-in | HMAC-signed, session-scoped, 24-hour expiry, plus manual and walk-in |
| Live court board | Each open court shows the recommended four, already split into teams, with a plain-English line explaining why |
| Money | Cash / transfer / waive, expected vs collected vs outstanding, minus court hire and shuttles |
| Close-out | No-show marking, session summary, and a single fairness score for the night |
| Stats | Player history, personal stats, doubles Elo with a margin multiplier |
No passwords, no signup. Players identify themselves once per phone; coordinator and organizer screens sit behind a group PIN.
Fairness, measured
The PRD's success metric is a games-played spread of ≤ 1. Current simulator output across five session shapes, five runs each:
| Scenario | Spread | Fairness | Avg wait |
|---|---|---|---|
| 24 players, 4 courts, 3 hours | 1 | 91–94% | 6.9 min |
| 28 players, 4 courts, 3 hours | 1 | 92–100% | 10.3 min |
| 20 players, 3 courts, 2 hours | 2 | 80–100% | 8.7 min |
| 13 players, 3 courts, 2 hours | 1 | 91% | 1.1 min |
| 26 players, 6 arriving 30–70 min late | 3 | 63–79% | 7.1 min |
The two looser limits are declared rather than hidden: a two-hour session can land one extra game on the final rotation, and somebody arriving 70 minutes late cannot catch up — the engine closes the gap as far as the clock allows and no further.
Reproduce with npm test (38 tests) and npm run sim.
Since 1.0.0-beta.1
- Moved to its own domain, smashq.aiopsgroup.ai. QR codes needed no change: they are built from the request origin rather than from configuration, so they follow whichever domain serves the page
- The user guide now ships inside the app at
/guide, generated fromdocs/USER-GUIDE.mdat build time so the two cannot drift - Open sourced under Apache 2.0, with a
NOTICEfile carrying the visible-attribution requirement - Seeded demo sessions take their name from the weekday they actually land on
- Dropped the beta label:
RELEASE_CHANNELis now nullable, so a future prerelease sets one string and the label returns everywhere at once
What v1.0.0 does not mean
It has not yet run thirty people on a Saturday night with patchy venue wifi, which is the only test that really counts. Expect the queue weights to want tuning after the first few real sessions — that is tuning, not repair. A weight change that widens the spread shows up in the simulator before it reaches a court.
Known limits are listed plainly in the README: the staff PIN is the only access control, live screens poll rather than push, and the Neon HTTP driver has no interactive transactions (which costs nothing today, since every write is a single statement).
Install
npm install
cp .env.example .env.local # set DATABASE_URL
npm run setup # schema + demo data
npm run devNeeds Node 22+ and a Postgres connection string. docs/DEPLOYING.md covers Vercel and Neon.
Apache 2.0 — commercial use, forks and modification all fine. Keep the copyright notice and the Built by AIOps credit visible in the running app; see NOTICE. Different terms are a conversation: hello@aiops.ae
Smash Queue 1.0.0-beta.1
First beta. Everything in the MVP scope is built and tested; what it has not yet done is survive a real Saturday with thirty people and patchy venue wifi.
What works
- Booking from a shareable session link, capacity limit, waitlist with automatic promotion and renumbering
- Signed QR check-in (session-scoped, 24-hour expiry), plus manual and walk-in check-in
- Live multi-court board: engine picks four, splits the teams, explains why; assisted and manual override with a silent audit trail
- Optional scores, doubles Elo, session fairness score, player and group statistics
- Payment tracking (cash / transfer / waive), session costs, revenue against cost
- Session close with no-show marking and a summary
- Installable PWA, no external CDN or font dependencies
The queue engine
Games played is a structural rule, not a weight. Players are banded by games played and the engine takes whole bands from the bottom up, so waiting time, rest, pairing history and team balance only ever decide between players who are already equal.
Across five simulated session shapes this holds games-per-player to a spread of one, with average waiting time around seven minutes. npm run sim reproduces it.
Verification
38 unit tests, 5 fairness simulations, 35 end-to-end browser checks covering the full flow from booking through payment.
Known limits
- The staff PIN is the only access control. Fine for one trusted group, not for anything public.
- Live screens poll every 5-6 seconds rather than pushing.
- Player score confirmation exists in the data model but is off by default.
- SQLite means one machine. See
docs/MIGRATE-TO-SUPABASE.mdfor the Postgres path.
Running it
Node 22 or newer.
npm install
npm run setup
npm run dev
Live demo session TONITE, staff PIN 1234. Set QR_SECRET before using it for a real session.
Built by AIOps. Support: hello@aiops.ae
