A production-ready, real-time interactive trivia game platform built with Vue 3, Socket.IO, and PostgreSQL. Designed for educators, event organizers, and trivia enthusiasts with robust connection stability, persistent player sessions, and estimated capacity for 50+ concurrent players.
Latest Release: v5.15.0 - Open-Ended (Short Answer) Questions (see ROADMAP.md for full release history)
- 🎯 Production-Ready: Tested with simulated sessions of 50+ concurrent players
- ⚡ Persistent Player Sessions: Dual-ID architecture (PlayerID + RoomSessionID) for seamless reconnection and state preservation
- 📱 Mobile-Optimized: HTTP-compatible UUID generation, CORS/CSRF configured for cross-origin mobile access
- 🏗️ Modular Architecture: Clean separation of concerns with controllers, services, middleware, and routes (v4.0.0)
- 🧪 Fully Tested: Comprehensive automated testing suite with 8 scenarios (quick to extreme load)
- 🔒 Secure: bcrypt password hashing, session-based auth, CSRF protection, rate limiting, SQL injection prevention
- 📊 Scalable: PostgreSQL connection pooling optimized for concurrent sessions with in-memory session tracking
- 🐳 Easy Deploy: Single-command Docker Compose setup with automatic database initialization
- Quiz Management: Create, edit, and delete custom quizzes with an intuitive interface
- Quiz Visibility Controls: Toggle quizzes for Live mode (presenter-led) and/or Solo mode (self-study) with visual badges
- Question Bank: Centralized question management across all quizzes with search, filter, and archive capabilities
- Tag System: Organize questions with customizable color-coded tags
- Duplicate Detection: Find and manage duplicate questions with similarity-based detection and merge tools
- Question Types: Support for Multiple Choice, True/False, and Open-Ended (Short Answer) questions
- Open-Ended Answer Grading: Fuzzy-match auto-grading against admin-supplied accepted answers, with an admin-configurable match strictness threshold
- Image Support: Add images to questions via file upload or external URL
- Timer Settings: Configure per-quiz question timers and reveal delays for auto-mode
- Results Display Toggle: Per-quiz option to show celebratory results podium with gold/silver/bronze when quiz completes
- Drag-and-Drop Reordering: Reorganize questions and answer choices with visual drag-and-drop or arrow buttons
- Smart Answer Tracking: Correct answer automatically updates when reordering choices
- Excel Import: Bulk import quizzes from professionally formatted Excel templates with duplicate review (supports 2-10 answer choices)
- Session Management: Resume interrupted sessions with full state preservation
- Real-time Monitoring: Track active rooms and player participation live
- User Management: View and manage all user accounts (guest, registered players, and admins)
- Password Reset: Reset player passwords and manage account types
- Multi-Admin Support: Multiple admin accounts with isolated quizzes and sessions
- Admin Management (Root Admin): Create/delete admin accounts, reset admin passwords
- Account Settings: Update email and password from any admin page
- Session Health Monitoring: View memory usage, active sessions, and live room statistics in real-time
- Server Settings: Configure the server URL for QR codes directly from the admin panel (no container rebuild needed)
- PDF Export: Export richly formatted session reports as PDF — includes podium leaderboard, full player rankings, per-question accuracy chart, and detailed question breakdown with embedded images
- Bulk PDF Export: Select multiple sessions and download a ZIP archive of individual PDF reports
- Database Backups: Automatic daily backups (10 most recent retained) plus on-demand manual backups, with download, delete, and one-click restore. Backup files can also be re-imported into a freshly rebuilt instance (e.g. after a container/volume rebuild) so they're restorable even without the original
backupsvolume - Quiz Library Export/Import: Export the full quiz library (or a single quiz) as JSON, or all questions as CSV, for sharing between instances or backing up separately from the full database
Question Bank |
User Management |
Two-Factor Authentication |
- Live Quiz Control: Present questions, reveal answers, and navigate through quizzes in real-time
- Auto-Mode Timer System: Server-side timers run independently of presenter's browser with pause/resume support
- Configurable Timers: Question timer (10-120 seconds) and reveal delay (2-30 seconds) per quiz or global defaults
- Auto-Advance: Automatically advance to next question after reveal delay expires
- Smart Timer Skip: All players answered detection skips remaining question timer automatically
- Player Management: See connected players with live status indicators, organized by connection status (connected/away/disconnected)
- Real-time Answer Progress: Track how many players have answered with percentage and animated progress bar
- All Players Answered Notification: Visual notification when all active players have submitted answers
- Auto-Reveal Option: Configurable 3-second auto-reveal countdown when all players answer (can be canceled)
- Kick Player: Remove disruptive players from sessions with confirmation dialog
- Ban Display Names: Block offensive display names globally to prevent rejoining
- Live Standings Dashboard: Real-time leaderboard showing all players' scores, accuracy, and rankings with medal recognition for top performers
- QR Code Generation: Quick player join via scannable QR codes
- Session Resume: Continue interrupted quizzes exactly where you left off
- Multi-room Support: Manage multiple concurrent trivia sessions
- Class Performance Analytics: View overall class statistics (total correct/incorrect, class accuracy percentage, average performance)
- Question Progress Counter: Live "X / Y" counter showing revealed questions vs total
- Auto-Complete Detection: Quiz automatically completes when all questions have been revealed (both manual and auto-mode)
- Mobile-Optimized Interface: Responsive design that works seamlessly on all devices (HTTP and HTTPS)
- Solo Play Mode: Self-study mode without a presenter - browse solo-enabled quizzes and play at your own pace
- Per-Question Timer: Countdown timer for each question with visual progress bar
- Immediate Feedback: See correct/incorrect status immediately after answering in solo mode
- Results Summary: Detailed breakdown of performance with per-question review after completing a quiz
- Guest Solo Play: No account required - play solo quizzes as a guest
- Persistent Player Identity: UUID-based PlayerID stored in localStorage for seamless reconnection across sessions
- Wake Lock Support: Keeps mobile screens on during games (Chrome 84+, Safari 16.4+) with visual indicator
- Enhanced Connection Stability: Infinite reconnection attempts with intelligent page visibility detection (30-second debounce)
- Real-time Feedback: Instant answer submission and result display in live games
- Open-Ended Answers: Type free-text answers for short-answer questions, with automatic grading; a timed-out answer auto-submits whatever's currently typed
- Answer Locking: Prevents re-answering after submission (even on reconnection)
- Smart Reconnection: Automatically restore progress when rejoining with full state preservation via RoomSessionID
- Progress Tracking: Comprehensive modal showing detailed session statistics and question-by-question history with correct/incorrect/pending status (persists across disconnections)
- Question Progress Counter: Live "X / Y" counter in navbar showing game progress
- End-of-Game Results: Celebratory podium display showing top 3 players with gold/silver/bronze and full rankings
- Quiz Complete Notification: Clear "Quiz Complete!" screen with countdown transition when results are enabled
- Account System: Guest accounts with optional registration for persistent profiles
- Recent Rooms: Quick rejoin to recently played active rooms
- Account Management: Update display names and manage account settings
- Session Persistence: Stay logged in for extended periods without re-authentication
- Cross-Origin Support: Join games from any device on the local network with proper CORS/CSRF handling
- Player Stats Dashboard: Dedicated
/statspage for registered players with game history, summary stats, and trend charts - Performance Summary: View total games, overall accuracy, best score, multiplayer wins, average rank, and play streak
- Trend Charts: Accuracy and score trends over time with theme-aware Chart.js visualizations
- Game History: Paginated table of past games with quiz name, score, accuracy, rank, and type filter (solo/multiplayer)
Player Lobby |
Answering Questions |
Answer Confirmation |
Desktop Player View |
Countdown Timer |
Player Standings |
Theme Selection |
Mobile Interface |
Solo Mode Landing |
Solo Mode Playing |
- Display Mode: Large-screen view perfect for projectors and TVs
- Live Results: Real-time answer distribution and statistics
- Reveal Animations: Engaging answer reveals with visual feedback
- Multiple Displays: Connect multiple spectator screens to the same room simultaneously
- Question Progress Counter: Live tracking of revealed questions
- End-of-Game Results: Full podium display on spectator screens when quiz completes
- Runtime: Node.js (v20+) with ES Modules
- Framework: Express.js (^4.18.2) with modular architecture (v4.0.0)
- Architecture: MVC pattern with controllers, services, middleware, and routes
- Real-time: Socket.IO (^4.7.2) with WebSocket transport and persistent session tracking
- Database: PostgreSQL 18 with connection pooling (pg ^8.11.0)
- Authentication: bcrypt (^6.0.0) for password hashing, session-based tokens
- Security: CSRF protection (csrf-csrf), rate limiting (express-rate-limit), CORS (cors)
- File Processing: ExcelJS (^4.4.0), XLSX (^0.18.5), Multer (^2.0.2)
- Utilities: crypto (built-in), QRCode (^1.5.1), dotenv (^16.1.4), cookie-parser (^1.4.7)
- Framework: Vue 3 (^3.3.0) - Composition API
- Build Tool: Vite (^8.0.8) - Fast HMR and optimized builds
- State Management: Pinia (^2.1.0) - Vue's official state management
- Routing: Vue Router (^4.2.0) - SPA navigation
- HTTP Client: Axios (^1.6.0)
- Charts: Chart.js (^4.5.1) + vue-chartjs (^5.3.3) - Theme-aware data visualization
- Real-time Client: Socket.IO Client (^4.7.0)
- Styling: Modern CSS3 with custom properties and responsive design
- Theme System: 4-theme support (Light, Dark, Grey, System) with enhanced light theme visibility
- Containerization: Docker & Docker Compose
- CI/CD: GitHub Actions — automatically builds and pushes Docker images to Docker Hub on version tag push (
v*.*.*) - Database: PostgreSQL 18 (official Docker image)
- Schema: Fully normalized relational design with foreign keys
- Connection Pooling: Optimized for concurrent sessions
- Session Persistence: Database-backed session storage
- Testing: Custom automated testing framework (HTTP-based)
- Debug Tools: Built-in debug API and CLI tools
- Logging: Conditional logging with connection state tracking
- Linting: ESLint for code quality
- Docker and Docker Compose (recommended)
- OR Node.js (v20 or higher) + PostgreSQL 18
Important: TriviaForge requires TWO containers to run:
triviagame-app- The Node.js application (pulls from Docker Hub)triviagame-db- PostgreSQL 18 database (pulls from Docker Hub)You MUST use docker-compose to start both containers together.
Choose your preferred setup method:
-
Clone the repository
git clone git@github.com:EmanTemplar/TriviaForge.git cd TriviaForge -
⚠️ IMPORTANT: Configure environment variables BEFORE startingCreate your
.envfile from the template:cp .env.example .env
Now open the
.envfile in a text editor and configure these REQUIRED settings:# REQUIRED: Set your admin password (login won't work without this!) ADMIN_PASSWORD=your_secure_password_here # Optional: Server URL for QR codes (can also be set in Admin > Settings tab) # SERVER_URL=http://192.168.1.100:3000 # Optional: Set your host IP (helps with network detection) HOST_IP=192.168.1.100 # Replace with YOUR actual IP
Find your IP address:
- Windows: Run
ipconfigin Command Prompt (look for IPv4 Address) - Mac/Linux: Run
ifconfigorip addrin Terminal
Do not proceed until you've set
ADMIN_PASSWORDin your .env file! - Windows: Run
-
Start the application
docker-compose up -d
This will:
- Pull
postgres:18from Docker Hub - Pull
emancodetemplar/triviaforge:latestfrom Docker Hub - Start the database and wait for it to be healthy
- Initialize the database schema automatically (takes 30-60 seconds)
- Start the application
- Pull
-
Verify startup
docker-compose logs -f app
Wait for these success messages:
✅ Database connection established✅ Database initialization completed successfullyServer running on port 3000
-
Access the application
- Landing Page:
http://localhost:3000(or use your SERVER_URL) - Admin Panel:
http://localhost:3000/index.html - Use the ADMIN_PASSWORD you set in your .env file
- Landing Page:
-
Clone the repository
git clone git@github.com:EmanTemplar/TriviaForge.git cd TriviaForge -
⚠️ IMPORTANT: Configure .env file FIRSTcp .env.example .env
Open
.envin a text editor and set at minimum:ADMIN_PASSWORD=your_secure_passwordSERVER_URL=http://YOUR_IP:3000HOST_IP=YOUR_IP
(See Option A step 2 for details)
-
Start via Docker Desktop
- Open Docker Desktop
- Open a terminal in the TriviaForge directory
- Run:
docker-compose up -d - OR drag the project folder into Docker Desktop (if supported)
-
Monitor in Docker Desktop UI
- Go to Containers tab
- You should see both containers running:
triviagame-apptriviagame-db
- Click on
triviagame-appto view logs - Wait for:
Server running on port 3000
-
Access the application
- Landing Page:
http://localhost:3000 - Use the ADMIN_PASSWORD from your .env file
- Landing Page:
View logs:
docker-compose logs -f # All services
docker-compose logs -f app # Just the application
docker-compose logs -f db # Just the databaseStop the application:
docker-compose down # Stop and remove containers
docker-compose down -v # Also remove database volume (fresh start)Restart after changes:
docker-compose restart # Restart existing containers
docker-compose up -d # Recreate containers if neededStarting with this release, docker-compose.yml moves from postgres:15 to postgres:18. The official Postgres 18 image also changed its data volume layout, so it will refuse to start against a volume initialized by Postgres 15/16/17 — this is expected, not a bug, and no data is destroyed by the failed start.
If you have an existing deployment with real data, back up and migrate before pulling this update:
-
On your current (pre-upgrade) install, go to Admin → Settings → Database Backups and click Create Backup. It's also worth clicking Download to keep a copy outside the container as a safety net, but it isn't strictly required — the backup file lives in the separate
backupsDocker volume, notpgdata, so it survives step 2 untouched. -
Stop the stack and remove only the old Postgres volume:
docker-compose down docker volume rm <project>_pgdata # e.g. triviagame_pgdata — check `docker volume ls`. Do NOT remove the `backups` or `uploads` volumes.
-
Pull and start the updated stack (this initializes a fresh, empty Postgres 18 volume and lets the app run its normal schema migrations):
docker-compose pull docker-compose up -d
-
Restore your backup — go to Admin → Settings → Database Backups, find the backup from step 1 in the list, and click Restore. The app applies it and restarts automatically.
If you're running a fresh install with no existing data, skip all of this — Postgres 18 will initialize normally.
-
Install PostgreSQL 18
-
Create database
createdb trivia psql trivia < app/init/tables.sql -
Install Node.js dependencies
cd app npm install -
Configure environment variables
Create
.envfile inappdirectory:DATABASE_URL=postgres://your_user:your_password@localhost:5432/trivia ADMIN_PASSWORD=your_secure_password_here APP_PORT=3000
-
Start the server
npm start
- Navigate to the Admin panel
- Enter admin password
- Fill in quiz title and description
- Add questions with 2-10 answer choices
- Mark the correct answer for each question
- Click "Save Quiz"
- Download the Excel template from the Admin panel
- Fill in your quiz data following the template format:
- Column A: Question text
- Columns B-K: Answer choices (2-10 choices)
- Column L: Correct answer index (0-9)
- Upload the completed Excel file
- Review and save the imported quiz
-
Presenter Setup
- Open the Presenter page
- Select a quiz from the dropdown
- Click "Make Live" to create a room
- Share the room code or QR code with players
-
Player Join
- Players open the Player page
- Enter room code and their name
- Wait for questions to be presented
-
Presenting Questions
- Navigate through questions using Previous/Next buttons
- Click "Present Question to Players" to show current question
- Players submit their answers
- Click "Reveal Answer" to show correct answer and results
-
Completing the Session
- Click "Complete Quiz & Save Results" to finish
- Session data is automatically saved
If a session is interrupted (server restart, connection loss, etc.):
- Go to Presenter or Admin page
- Find the session in "Resume Session" or "Incomplete Sessions" dropdown
- Click "Resume"
- A new room code is generated
- Players rejoin with their original names to restore their progress
- Continue from where you left off
All completed and interrupted sessions are saved and can be reviewed:
- Navigate to the Admin panel
- Scroll to the "Completed Sessions" section
- View session details including:
- Quiz title and room code
- Start/resume timestamps
- Player names and scores
- Individual question results
TriviaForge includes a comprehensive automated testing suite for validating functionality and performance.
# Windows
test.bat quick
# Linux/Mac
./test.sh quickQuick Tests (Development)
quick- Fast validation (3 players) - ~10ssession- Default test (5 players, 3 questions) - ~25sverbose- Detailed logging - ~25s
Stress Tests (Performance)
light- Light load (5 players) - ~25smedium- Medium load (15 players) - ~45sheavy- Large event simulation (25 players) - ~2minextreme- Maximum capacity (50 players) - ~3minstress- Standard stress (20 players) - ~1min
# Run default test
test.bat
# Run specific scenario
test.bat heavy
# View all options
test.bat helpSet environment variables for custom scenarios:
# Example: 30 players, 10 questions
docker-compose exec -e TEST_PLAYERS=30 app node testing/test-runner.jsAvailable Environment Variables:
TEST_PLAYERS- Number of simulated players (default: 5)TEST_QUIZ_ID- Quiz to use (default: 1)TEST_ANSWER_DELAY- Max delay between answers in ms (default: 2000)TEST_QUESTION_DELAY- Delay between questions in ms (default: 5000)TEST_VERBOSE- Detailed logging (default: false)
For comprehensive testing documentation, see:
- app/testing/README.md - Testing suite overview
- app/testing/TESTING.md - Complete testing guide
- app/testing/stress-test.config.js - Scenario configurations
TriviaForge/
├── app/
│ ├── src/ # Backend source (v4.0.0+ Modular Architecture)
│ │ ├── config/ # Configuration modules
│ │ │ ├── constants.js # Application constants
│ │ │ ├── database.js # PostgreSQL connection pool
│ │ │ ├── environment.js # Environment variable access
│ │ │ └── version.js # Centralized version management
│ │ ├── controllers/ # REST API controllers
│ │ │ ├── auth.controller.js
│ │ │ ├── backup.controller.js # Database backup/restore/import API
│ │ │ ├── quiz.controller.js
│ │ │ ├── questionBank.controller.js
│ │ │ ├── session.controller.js
│ │ │ ├── solo.controller.js # Solo play REST API
│ │ │ ├── stats.controller.js # Player stats API
│ │ │ ├── tag.controller.js # Tag management
│ │ │ └── user.controller.js
│ │ ├── middleware/ # Express middleware
│ │ │ ├── auth.js # Authentication middleware
│ │ │ └── errorHandler.js # Global error handler
│ │ ├── routes/ # REST API routes
│ │ │ ├── auth.routes.js
│ │ │ ├── backup.routes.js # Database backup/restore/import routes
│ │ │ ├── quiz.routes.js
│ │ │ ├── questionBank.routes.js
│ │ │ ├── session.routes.js
│ │ │ ├── solo.routes.js # Solo play routes
│ │ │ ├── stats.routes.js # Player stats routes
│ │ │ ├── tag.routes.js # Tag routes
│ │ │ └── user.routes.js
│ │ ├── services/ # Business logic services
│ │ │ ├── autoMode.service.js # Server-side auto-mode timer engine
│ │ │ ├── backup.service.js # pg_dump/restore, backup import & metadata parsing
│ │ │ ├── export.service.js # CSV export functionality
│ │ │ ├── quiz.service.js # Quiz data access
│ │ │ ├── room.service.js # Live room state management
│ │ │ ├── session.service.js # Session persistence
│ │ │ └── totp.service.js # Two-factor authentication
│ │ └── utils/ # Utility modules
│ │ ├── constants.js # Shared constants
│ │ ├── errors.js # Custom error classes
│ │ ├── helpers.js # Helper functions
│ │ ├── responses.js # API response helpers
│ │ ├── similarity.js # Duplicate detection algorithm
│ │ └── validators.js # Input validation
│ ├── src/ # Frontend source (Vue 3 + Vite)
│ │ ├── main.js # Vue app entry point
│ │ ├── App.vue # Root component
│ │ ├── router.js # Vue Router configuration
│ │ ├── pages/ # Page components
│ │ │ ├── LoginPage.vue
│ │ │ ├── AdminPage.vue
│ │ │ ├── PresenterPage.vue
│ │ │ ├── PlayerPage.vue
│ │ │ ├── PlayerManagePage.vue
│ │ │ ├── DisplayPage.vue
│ │ │ ├── SoloPlayPage.vue # Solo play mode
│ │ │ └── StatsPage.vue # Player stats dashboard
│ │ ├── components/ # Reusable Vue components
│ │ │ ├── admin/ # Admin panel components (Question Bank, Tags, Duplicates)
│ │ │ ├── common/ # Shared components (Modal, Button, AppIcon, etc.)
│ │ │ ├── modals/ # Modal components
│ │ │ ├── player/ # Player page components (CountdownTimer, etc.)
│ │ │ ├── stats/ # Player stats components (Summary, Charts, History, Navbar)
│ │ │ └── presenter/ # Presenter page components
│ │ ├── stores/ # Pinia state stores
│ │ │ ├── auth.js
│ │ │ ├── ui.js
│ │ │ ├── player.js
│ │ │ ├── question.js
│ │ │ ├── quiz.js
│ │ │ └── room.js
│ │ ├── composables/ # Vue composables
│ │ │ ├── useApi.js # Axios wrapper (w/ CSRF)
│ │ │ ├── useAuth.js # Authentication composable
│ │ │ ├── useLocalStorage.js # LocalStorage wrapper
│ │ │ ├── useSocket.js # Socket.IO integration (w/ PlayerID)
│ │ │ ├── useSoloGame.js # Solo play state management
│ │ │ ├── useTheme.js # Theme management
│ │ │ └── useWakeLock.js # Screen wake lock
│ │ ├── assets/ # Static assets (CSS, images)
│ │ └── main.css # Global styles
│ ├── init/ # Database initialization SQL scripts
│ │ ├── 01-tables.sql # PostgreSQL schema
│ │ ├── 02-migrate_timestamps.sql
│ │ ├── ... # Additional migrations (03-08)
│ │ ├── 09-question-tags.sql # Question Bank & tags
│ │ ├── 10-duplicate-detection.sql # Text hash for duplicates
│ │ ├── 11-ignored-duplicate-pairs.sql # Ignored pairs
│ │ ├── 12-auto-mode-solo-play.sql # Auto-mode & solo play
│ │ ├── 13-fix-solo-guest-participants.sql # Guest participant fix
│ │ ├── 14-show-results-setting.sql # Show results toggle
│ │ ├── 15-server-url-setting.sql # Server URL setting
│ │ ├── 16-trusted-devices.sql # 2FA trusted device tokens
│ │ └── 17-cleanup-display-ghost-users.sql # Prevents Display connections creating ghost users
│ ├── testing/ # Automated testing suite
│ │ ├── README.md # Testing suite overview
│ │ ├── TESTING.md # Complete testing guide
│ │ ├── test-runner.js
│ │ └── stress-test.config.js
│ ├── server.js # Main server application (Express + Socket.IO)
│ ├── db-init.js # Database initialization orchestrator
│ ├── vite.config.js # Vite build configuration
│ ├── index.html # HTML entry point
│ ├── Dockerfile # Docker container definition
│ └── package.json # Dependencies
├── test.bat # Windows test runner wrapper
├── test.sh # Linux/Mac test runner wrapper
├── docker-compose.yml # Docker orchestration configuration
├── .env.example # Environment variables template
├── LICENSE # PolyForm Noncommercial License
├── CONTRIBUTING.md # Contribution guidelines
├── TODO.md # Active development tasks
├── ROADMAP.md # Completed feature history & future plans
└── README.md # This file
Environment variables can be set in multiple ways (listed by precedence, highest to lowest):
- Docker Desktop UI - Set directly in the container configuration (highest priority)
.envfile - Place in the root directory alongsidedocker-compose.yml- Default values - Built into
docker-compose.yml(lowest priority)
| Variable | Description | Default | Required |
|---|---|---|---|
APP_PORT |
Port number for the server | 3000 |
No |
DATABASE_URL |
PostgreSQL connection string | postgres://trivia:trivia@db:5432/trivia |
Yes (auto-configured in Docker) |
ADMIN_PASSWORD |
Password to access admin panel | - | Yes |
HOST_IP |
Server IP address for network access | Auto-detected | No |
SERVER_URL |
Server URL for QR codes (can also be set in Admin > Settings) | Auto-detected | No |
SESSION_TIMEOUT |
Session expiration time (ms) | 3600000 (1 hour) |
No |
NODE_ENV |
Environment mode (development or production) |
production |
No |
DEBUG_MODE |
Enable comprehensive debug logging (server-side) | false |
No |
TZ |
Timezone for timestamps | America/New_York |
No |
APP_NAME |
Application name | TriviaForge |
No |
SOCKET_RATE_WINDOW_MS |
Socket.IO rate limit window (ms) | 60000 (1 min) |
No |
SOCKET_JOIN_LIMIT |
Max join attempts per IP per window | 50 |
No |
SOCKET_ANSWER_LIMIT |
Max answer submissions per IP per window | 300 |
No |
- For Docker Desktop users: Variables set in the UI will override
.envfile values - For Docker Compose CLI users: Create a
.envfile from.env.exampleand configure there ADMIN_PASSWORDmust be set before first run for admin login to workSERVER_URLcan be set in your.envfile OR configured in the Admin > Settings tab. The Admin UI setting takes priority over the environment variable
- Download a formatted Excel template with color-coded sections
- Support for 2-10 answer choices per question
- Automatic validation of quiz structure
- Preserves question formatting and special characters
- Dual-ID Architecture (v4.0.0): PlayerID (persistent across sessions) + RoomSessionID (per-room tracking)
- Automatic session state saving to PostgreSQL database
- In-memory session tracking with Maps for O(1) lookups
- Player answer history preservation with comprehensive logging
- Reconnection support with full state restoration (answers, progress, reconnection count)
- Timestamp tracking for created and resumed sessions (timezone-aware)
- Status indicators (In Progress, Interrupted, Completed)
- Session analytics with participant performance views
- Debug logging modes:
[SESSION DEBUG],[ROOM SESSION],[JOIN DEBUG],[ANSWER DEBUG]
- Persistent Player Identity (v4.0.0): UUID-based PlayerID stored in localStorage for seamless reconnection
- Guest accounts created automatically on first join
- Optional registration for persistent accounts
- Password-protected registered player accounts
- Session tokens with configurable timeout (default 1 hour)
- Admin password reset functionality
- Account type management (guest/registered/admin)
- Recent rooms tracking with active session filtering
- Cross-origin support with CORS and CSRF protection for mobile devices
- Server-side validation prevents answer manipulation
- Answer locking after submission (persists across disconnects)
- Prevents re-answering after reveal
- Tamper-proof answer tracking
- Mobile-first interface for players
- Desktop-optimized admin and presenter views
- Adaptive text sizing with viewport scaling
- Touch-friendly controls
This project is licensed under the PolyForm Noncommercial License 1.0.0.
Key points:
- ✅ Free for personal use, research, and educational purposes
- ✅ Open source and available for modification
- ✅ Can be used by nonprofits and educational institutions
- ❌ Cannot be used for commercial purposes or profit-making activities
See the LICENSE file for full details.
We welcome contributions from the community! Please read our CONTRIBUTING.md guide before submitting pull requests.
Quick guidelines:
- By contributing, you agree your contributions will be under the same noncommercial license
- Follow the existing code style
- Test your changes thoroughly
- Write clear commit messages
- Update documentation as needed
- Issues: Report bugs via GitHub Issues
- Discussions: Ask questions and share ideas in GitHub Discussions
See ROADMAP.md for the full completed-feature history and planned future work.
Built with love for educators, event organizers, and trivia enthusiasts.
This project was developed with assistance from AI tools, including:
- Claude Code - for code generation, debugging, and feature implementation
- Anthropic's Claude - for architecture design and problem-solving
While AI tools were instrumental in the development process, all code has been reviewed, tested, and validated for functionality and security. The project architecture, feature decisions, and final implementation remain the responsibility of the human developers.
TriviaForge - Where Knowledge Meets Fun 🎮






















