A live classroom Q&A portal used in a real venue — four screens, one reactive data source, and the fairness rules a room full of students will always try to break. Built and deployed solo, front to back.




Shy students stay quiet, loud ones dominate, and the instructor can't tell what most people actually want answered. The fix needed a projector view the whole room sees, an instructor console to drive it, and a student view with no sign-up friction — all showing the same thing at the same instant, live.
Four surfaces, always in agreement. Student, instructor, projector, and admin views must never disagree about what's on screen — even for a second.
Students will try to game it. Double-voting, voting for themselves, spamming questions — fairness had to be guaranteed by the server, not trusted to the client.
No accounts for students. Asking a room to sign up would kill participation — identity had to be anonymous but still one-vote-per-person.
Every view subscribes to the same Convex reactive queries — the backend pushes changes to all of them. No socket wiring, no manual refetching, no cache to keep in sync. The data source is the sync.
One open session per campus, one projected question, one question per student, no self-voting or double-voting, and cron auto-close — all enforced in the backend where they can't be faked.
Students join by QR into a UUID-based anonymous identity — zero sign-up friction, while the server still ties one vote and one question to each person.
Dual-token JWT with silent refresh, bcrypt hashing in a Convex node action, httpOnly SameSite=Strict cookies, route guards, and campus vs super-admin roles.
Instructors export the full Q&A to Excel or PowerPoint, and generate a QR join-poster for the room.
The whole thing — frontend, reactive backend, auth, and deploy — was built and shipped solo.
The obvious build is sockets: broadcast every change to every client and reconcile on each end. That's a lot of plumbing — and four chances for the projector to lag behind the instructor. Instead I leaned on Convex's reactive queries as the source of truth: each surface simply subscribes to the state it cares about, and the backend recomputes and pushes when anything changes.
That decision collapsed a class of bugs before they existed. There's no client cache to invalidate and no socket reconnect logic — consistency is a property of the data layer, so the projector and the instructor are looking at the same query result by construction.
Students joined by QR, the top questions rose on the projector as votes landed, and the instructor ran the whole session from one console. Fairness held under a room actively testing it, and every session archived itself to Excel and PowerPoint. A complete solo build — frontend, reactive backend, auth, and deployment.