Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LiveRoom

Live poll rooms over FastAPI + JWT + WebSockets.

Open a room, share a short code (or QR), push a question, collect one vote per person, then reveal tallies live. Built for a 3-hour hands-on workshop.

Students work in app/; reference answers for the classic one-vote gap live in solution/ (legacy poll path). The product path is room-scoped.

What you build / run

Piece What it is
Host account Register / login → JWT
Room Short join code + participants by display name
Poll One live question per room
Vote One vote per participant per poll (DB unique + API 409)
Reveal Tallies hidden until the host reveals
Live updates WebSocket room stream
UI React app: join-first, QR, projection mode, dark/light

Prerequisites

  • Python ≥ 3.10
  • Node.js ≥ 18 (for the React UI)
  • Terminal (PowerShell, bash, or Git Bash)

Quick setup (≈10 minutes)

1. Backend

Windows (PowerShell)

# if scripts are blocked:
# Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
.\setup.ps1
.\.venv\Scripts\Activate.ps1
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Linux / macOS / Git Bash

chmod +x setup.sh && ./setup.sh
source .venv/bin/activate
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

2. Frontend (second terminal)

cd frontend
npm install
npm run dev

Demo loop (2 minutes)

  1. Expand Open a room → Register / Log in → Create room
  2. Share code or QR
  3. Phones/laptops: Join with a code
  4. Host: Push live a question
  5. Everyone votes once
  6. Host: Reveal (or open Projection mode on a second screen)

3-hour workshop schedule

Time Focus
0:00–0:15 Setup, tour repo, run API + UI
0:15–0:45 Models: User, Room, Participant, Poll, Option, Vote
0:45–1:15 REST: register, token, create room, join
1:15–1:35 Break
1:35–2:10 Polls, vote, one vote per participant, 409
2:10–2:35 WebSockets: live room state
2:35–2:50 Reveal + projection + QR (product polish)
2:50–3:00 Debug, questions, wrap

Keep scope tight: rooms + vote integrity + live stream are the core. QR / projection / reveal are short demos, not deep dives.

Project layout

app/
  main.py              # FastAPI app, CORS, exception handlers
  config.py            # env / .env settings
  database.py          # SQLite + light migrations
  models.py            # User, Room, Participant, Poll, Option, Vote
  schemas.py           # Pydantic models
  auth.py              # password hashing, host + participant JWT
  ws_manager.py        # WebSocket fan-out by room code
  routers/
    users.py           # POST /users/, POST /token
    rooms.py           # rooms, join, polls, vote, reveal
    polls.py           # legacy poll routes (teaching / starter)
    ws.py              # WS /ws/rooms/{code}
  static/              # optional legacy static UI
frontend/              # React (Vite) product UI
solution/              # answer key for legacy one-vote gap
scripts/               # public regression helpers
requirements.txt
setup.sh / setup.ps1

API sketch (product path)

Method Path Auth Purpose
POST /users/ Register host
POST /token Login → host JWT
POST /rooms/ Host JWT Create room → { code }
POST /rooms/join { code, display_name } → participant JWT
GET /rooms/{code} optional Room state (counts masked until reveal)
POST /rooms/{code}/polls Host New live question (results hidden)
POST /rooms/{code}/polls/{id}/vote Participant Cast one vote
POST /rooms/{code}/polls/{id}/reveal Host Reveal tallies to the room
WS /ws/rooms/{code} Live room updates

Legacy /polls/* remains for the original workshop starter exercises.

One vote per participant

Enforced by:

  1. UniqueConstraint("participant_id", "poll_id") on Vote
  2. Explicit check in cast_vote409
  3. IntegrityError handler for concurrent double-submits

If you change models and SQLite acts up: stop the server, delete liveroom.db, restart (create_all does not fully migrate old tables).

Config

Copy .env.example.env (gitignored):

Variable Purpose
SECRET_KEY JWT signing key (change for any shared deploy)
ACCESS_TOKEN_EXPIRE_MINUTES Token lifetime
DATABASE_URL Optional; default is project-root SQLite
DEBUG 1 only locally (richer 500 detail)

Public repo hygiene

Do not commit:

  • .env, *.db, screenshots (*.png / *.jpg)
  • frontend/node_modules/, local logs
  • Anything under scripts/private/ (maintainer-only)

About

A real-time live polling app that creates a poll, shares the link, and watch votes update instantly as people respond.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages