A live, real-time cinema quiz competition platform built for events with large audiences. Participants join on their phones, answer movie-clue questions each round, and the system automatically eliminates wrong/slow answers โ progressively narrowing down to finalists. A projector screen shows live results to the audience.
Participants (phones) Admin Panel Projector Screen
โ โ โ
โ Register with Roll No. โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ>โ โ
โ โ Create Round โ
โ โ (set emoji clue, โ
โ โ correct answers, โ
โ โ time limit) โ
โ Receive clue + timer โ โ
โ<โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ Shows: emoji clue
โ Submit answer option โ โ + timer
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ>โ โ + submission count
โ โ End Round โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Receive: Qualified โ
โ โ Shows: โ
Qualified list
โ or Eliminated โ โ โ โ Eliminated list
โ โ Repeat for next round โ
โ โ (up to 4 rounds) โ
โ โ โ
โ FINALISTS REVEALED โ ๐ Finalist roll numbers
| Layer | Technology |
|---|---|
| Frontend | React + TypeScript + Vite + TailwindCSS |
| Backend | Node.js + Express + TypeScript |
| Real-time | Socket.IO (WebSockets) |
| Database | SQLite (via node:sqlite) |
| Auth | JWT (admin) + session tokens (participants) |
| Package Manager | pnpm (monorepo workspace) |
โโโ artifacts/
โ โโโ api-server/ # Backend Express + Socket.IO server
โ โ โโโ src/
โ โ โ โโโ database/ # SQLite setup, schema, seed data
โ โ โ โโโ middleware/ # JWT auth middleware
โ โ โ โโโ routes/ # REST API routes
โ โ โ โโโ services/ # Business logic
โ โ โ โโโ eliminationService.ts โ elimination logic
โ โ โ โโโ socketService.ts โ real-time events
โ โ โ โโโ timerService.ts โ round timer
โ โ โโโ cinequiz.db # SQLite database (auto-created, gitignored)
โ โ
โ โโโ cinequiz/ # Frontend React app
โ โโโ src/
โ โ โโโ pages/
โ โ โ โโโ Landing.tsx โ Participant registration
โ โ โ โโโ Projector.tsx โ Big screen display
โ โ โ โโโ AdminLogin.tsx โ Admin sign-in
โ โ โ โโโ AdminDashboard.tsx โ Admin control panel
โ โ โ admin-tabs/
โ โ โ โโโ SetupTab.tsx โ Create/manage rounds
โ โ โ โโโ LiveTab.tsx โ Start/end rounds live
โ โ โ โโโ ParticipantsTab.tsx
โ โ โโโ hooks/
โ โ โโโ useSocket.ts โ Socket.IO client hook
โ โโโ load-test.mjs โ Bot simulator for load testing
โ โโโ vite.config.local.ts โ Local dev config (no env vars needed)
- Node.js v18+
- pnpm (
npm install -g pnpm)
pnpm installcd artifacts/api-server
npm run dev
# If it asks for PORT:
$env:PORT=3000; node --enable-source-maps ./dist/index.mjscd artifacts/cinequiz
npm run dev -- --config vite.config.local.ts| URL | Purpose |
|---|---|
http://localhost:5173/ |
Participant registration page |
http://localhost:5173/admin/login |
Admin control panel |
http://localhost:5173/projector |
Big screen / projector display |
| Field | Value |
|---|---|
| Username | ******* |
| Password | ******** |
โ ๏ธ Change these before any real event โ see Customization below.
- Admin logs in โ
http://localhost:5173/admin/login - Participants register on
http://localhost:5173/with their roll number - Open Projector on the big screen:
http://localhost:5173/projector - Admin โ Setup tab โ Create a round (set emoji clue, correct answers, time limit)
- Admin โ Live tab โ Click Start Round
- Projector shows the emoji clue + countdown timer
- Participants see the question on their phones
- Participants submit answers before time runs out
- Admin โ Click End Round
- System auto-eliminates based on: wrong answers first, then slowest correct
- Projector shows two columns: โ Qualified and โ Eliminated
- Repeat for up to 4 rounds
- Final round โ Finalists revealed with confetti on the projector ๐
Simulate multiple participants for testing:
cd artifacts/cinequiz
# Spawn 20 bots (resets competition to 'waiting' first)
node load-test.mjs 20 --reset
# Spawn 50 bots
node load-test.mjs 50 --reset
# Spawn 100 bots
node load-test.mjs 100 --resetEach run generates a unique run ID so bot roll numbers never clash across runs (e.g. B472P001, B472P002...).
Each round, participants are ranked by:
- Correctness โ wrong answers are eliminated first
- Response time โ among correct answers, slower responses are eliminated
| Round | % that advance |
|---|---|
| Round 1 | 40% (of correct answerers) |
| Round 2 | 30% |
| Round 3 | 25% |
| Round 4 | Top 2 โ Finalists |
Key rule: Wrong answers always eliminate regardless of how few participants remain.
If everyone gets it wrong, 1 person advances (to avoid a deadlock).
File: artifacts/api-server/src/database/db.ts
// Line ~52 โ change "CineQuiz Fest 2024" to your event name
compId, "CineQuiz Fest 2024", "waiting", 0
// โ Change thisNote: Delete
cinequiz.dband restart the server to apply (it re-seeds on fresh DB).
File: artifacts/api-server/src/database/db.ts
const passwordHash = bcrypt.hashSync("cinequiz2024", 10); // โ change password
db.prepare(...).run(adminId, "admin", passwordHash); // โ change usernameFile: artifacts/api-server/src/services/eliminationService.ts
switch (round.round_number) {
case 1: targetCount = Math.floor(n * 0.4); break; // โ 40% advance
case 2: targetCount = Math.floor(n * 0.3); break; // โ 30% advance
case 3: targetCount = Math.floor(n * 0.25); break; // โ 25% advance
case 4: targetCount = 2; break; // โ always 2 finalists
}- Tab title:
artifacts/cinequiz/index.htmlโ<title>tag - Landing page heading:
artifacts/cinequiz/src/pages/Landing.tsx - Projector header:
artifacts/cinequiz/src/pages/Projector.tsx
Set the PORT environment variable when starting the API server:
$env:PORT=4000; node --enable-source-maps ./dist/index.mjsThen update the proxy in artifacts/cinequiz/vite.config.local.ts:
proxy: {
'/api': { target: 'http://localhost:4000' },
'/socket.io': { target: 'http://localhost:4000', ws: true },
}Set in the Admin panel โ Setup tab when creating a round (default: 30 seconds).
Or change the default in artifacts/api-server/src/database/db.ts in the seed data.
| Event | Direction | Description |
|---|---|---|
participant_join |
Client โ Server | Participant joins with session token |
round_started |
Server โ Client | Round begins, sends clue + timer |
submit_answer |
Client โ Server | Participant submits answer |
round_ended |
Server โ Client | Round ends |
qualification_result |
Server โ Participant | { qualified: true/false } |
qualification_summary |
Server โ Projector | Lists of qualified/eliminated roll numbers |
finalists_ready |
Server โ Projector | Final 2 contestants |
@devBitt Licensed