- Overview
- Features
- Tech Stack
- Project Structure
- Requirements
- Installation
- Usage Guide
- API Reference
- Database Schema
- Security
- Roadmap
- Author
A real-time interactive competition platform that allows agents to register participants and generate unique QR codes, while the admin monitors everything live from a fully-featured dashboard. Admin controls settings โโโบ Agent registers participants โโโบ Participant scans QR โโโบ Challenge begins
โโโโโโโโโโโโโ login + register โโโโโโโโโโโโโโโโโโโโ โ Agent โ โโโโโโโโโโโโโโโโโโโบ โ Registration UI โ โโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โ generates QR โผ โโโโโโโโโโโโโ scans QR code โโโโโโโโโโโโโโโโโโโโ โParticipantโ โโโโโโโโโโโโโโโโโโโบ โ Challenge Page โ โโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โ sends result โผ โโโโโโโโโโโโโ real-time update โโโโโโโโโโโโโโโโโโโโ โ Admin โ โโโโโโโโโโโโโโโโโโโ โ MySQL Database โ โโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
| Feature | Description |
|---|---|
| ๐ Auth System | Separate accounts for admin and agents |
| ๐ฑ Unique QR Codes | Every participant gets a personal QR code |
| โฑ๏ธ Interactive Timer | Circular animated stopwatch in seconds |
| ๐ Prize System | First prize + two secondary prizes with configurable probability weights |
| ๐ Live Dashboard | Stats that refresh every 5 seconds |
| ๐ข Company Branding | Upload logo + custom welcome message |
| ๐ก๏ธ QR Protection | Each QR code can only be used once |
| ๐๏ธ Result Management | Delete individual results or clear all records |
| ๐๏ธ MySQL Database | Persistent data with relational integrity |
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite 8 |
| Backend | Node.js 20 (HTTP) |
| Database | MySQL 8.0 |
| QR Code | qrcode.react |
| Routing | React Router DOM |
| Styling | CSS Variables + Custom Design System |
competition-app/ โ โโโ ๐ src/ # Frontend source code โ โโโ ๐ main.jsx # Entry point โ โโโ ๐ App.jsx # Router & routes โ โโโ ๐ index.css # Global styles & design tokens โ โ โ โโโ ๐ pages/ โ โ โโโ ๐ AgentPage.jsx # Agent login + QR generation โ โ โโโ ๐ ChallengePage.jsx # Participant challenge screen โ โ โโโ ๐ AdminLogin.jsx # Admin login โ โ โโโ ๐ AdminDashboard.jsx # Full admin control panel โ โ โ โโโ ๐ components/ โ โ โโโ ๐ ProtectedRoute.jsx # Route guard for admin pages โ โ โ โโโ ๐ utils/ โ โโโ ๐ api.js # Server communication functions โ โโโ ๐ server/ โ โโโ ๐ index.cjs # Node.js HTTP server + MySQL queries โ โโโ ๐ uploads/ # Uploaded logo images โ โโโ ๐ dist/ # Production build output โโโ ๐ .env.example # Environment variables template โโโ ๐ .gitignore โโโ ๐ CHANGELOG.md โโโ ๐ CONTRIBUTING.md โโโ ๐ LICENSE โโโ ๐ README.md โโโ ๐ SECURITY.md โโโ ๐ package.json โโโ ๐ vite.config.js
| Requirement | Version |
|---|---|
| Node.js | >= 20.x |
| npm | >= 10.x |
| MySQL | >= 8.0 |
| Browser | Chrome / Firefox / Safari |
git clone https://github.com/mortada313s/competition-app.git
cd competition-appnpm installsudo mysqlCREATE DATABASE competition_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'competition_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON competition_db.* TO 'competition_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;Then create the tables:
sudo mysql competition_db < server/schema.sqlcp .env.example .env
# Edit .env with your database credentialsnpm run buildnode server/index.cjsAccessing from other devices on the same network: Find your IP with
hostname -I, then openhttp://YOUR_IP:4000
| URL | Description |
|---|---|
/admin |
Admin login page |
/admin/dashboard |
Full control panel |
Default credentials: Username: admin Password: admin1234
โ ๏ธ Change your password immediately after first login from the Account tab.
Admin capabilities:
- Create agents and assign secret codes
- Configure challenge timers (Challenge 1 & 2)
- Set prizes and probability weights for secondary prizes
- Upload company logo and write a custom welcome message
- Monitor all results in real time
- Delete individual results or clear the entire log
- Update admin username and password
| URL | Description |
|---|---|
/agent |
Agent login page |
Workflow:
- Agent opens
/agenton their device - Enters their name and secret code assigned by the admin
- Registers a participant (name + password)
- A QR code is generated โ the participant scans it to start the challenge
- Scans the QR code with their phone camera
- Taps Start Challenge โ the timer begins
- Taps Stop at the target time
- Win on Challenge 1 โ Prize 1 is awarded
- Lose on Challenge 1 โ Moves to Challenge 2
- Win on Challenge 2 โ Random prize (Prize A or B based on admin-set weights)
- Lose on Challenge 2 โ No prize, game over
- Each QR code is valid for one use only
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/admin/login |
Admin login |
POST |
/api/admin/update |
Update admin credentials |
POST |
/api/agent/login |
Agent login |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/db |
Fetch all data |
GET |
/api/check/:token |
Check if QR token has been used |
POST |
/api/participant |
Register a new participant |
POST |
/api/result |
Save a challenge result |
POST |
/api/config |
Save competition settings |
POST |
/api/agents |
Update agents list |
POST |
/api/branding |
Update company branding |
DELETE |
/api/results/:id |
Delete a specific result by ID |
DELETE |
/api/results/all |
Delete all results |
-- Admin account
CREATE TABLE admin (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Agents (representatives)
CREATE TABLE agents (
id VARCHAR(100) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
code VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Participants registered by agents
CREATE TABLE participants (
token VARCHAR(100) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
agent_id VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL
);
-- Competition results
CREATE TABLE results (
id INT PRIMARY KEY AUTO_INCREMENT,
participant_token VARCHAR(100) NOT NULL,
participant_name VARCHAR(100) NOT NULL,
prize VARCHAR(255),
challenge INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (participant_token) REFERENCES participants(token) ON DELETE CASCADE
);
-- Competition configuration
CREATE TABLE config (
id INT PRIMARY KEY DEFAULT 1,
target1 DECIMAL(5,1) DEFAULT 7.0,
target2 DECIMAL(5,1) DEFAULT 4.0,
max1 INT DEFAULT 10,
max2 INT DEFAULT 10,
prize1 VARCHAR(255),
prize_a VARCHAR(255),
prize_b VARCHAR(255),
prize_a_weight INT DEFAULT 70
);
-- Company branding
CREATE TABLE branding (
id INT PRIMARY KEY DEFAULT 1,
company_name VARCHAR(255),
welcome TEXT,
logo_url VARCHAR(500)
);| Aspect | Current | Recommended for Production |
|---|---|---|
| Admin auth | Plain text in MySQL | bcrypt hashing |
| Agent auth | Plain text code | bcrypt hash |
| Database | MySQL (local) | MySQL with SSL |
| HTTPS | โ | โ Required |
| Rate Limiting | โ | โ Required |
| Input Validation | Basic | Full server-side validation |
- Password hashing with bcrypt
- JWT session management
- Deploy to the internet (Railway / Render / VPS)
- Mobile app (React Native / Expo)
- Real-time updates via WebSocket
- Export results to Excel / PDF
- Multi-competition support
- Analytics charts in dashboard
Mortada Mohammed Abdulabbas
- GitHub: @mortada313s
- Location: Iraq ๐ฎ๐ถ
MIT License ยฉ 2026 Mortada Mohammed Abdulabbas