World Cup Voting App
A real-time voting platform built with a MERN stack architecture that allows users to vote for match outcomes and participate through a live comment system.
The project focuses on state consistency, API design, and user interaction constraints, while keeping the UI simple and responsive.
📸 UI Preview
🧠 Concept
The application simulates a live voting environment during a football tournament, where users can:
- Vote for a winning team
- View total votes instantly
- Leave comments
- Browse comments with pagination
It includes client-side protections to prevent abuse and ensures backend consistency with atomic updates.
⚙️ Tech Stack
- Frontend: React, React Bootstrap, React Paginate
- Backend: Node.js, Express
- Database: MongoDB (Mongoose)
- State Management: useReducer (custom logic)
- Notifications: React Toastify
🚀 Key Features
🗳️ Voting System
- Users can vote for teams (France / Argentina)
- Voting is rate-limited (1 vote per hour) using localStorage
- Backend uses atomic updates (
$inc) to ensure consistency
💬 Comment System
- Users can submit comments with username
- Rate-limited to 1 comment per 2 minutes
- New comments are inserted instantly without full reload
📊 Live Vote Counts
- Aggregated vote counts stored in MongoDB
- Loaded via
/api/win - Updated after each vote without refreshing the page
📄 Pagination
- Comments are paginated client-side
- Efficient rendering for large datasets
🧩 Backend Design
The backend exposes simple REST endpoints:
GET /api/win→ fetch vote countsPOST /api/win/add/:team→ increment voteGET /api/users→ fetch commentsPOST /api/users/add→ add comment
Vote updates are handled atomically using MongoDB increment operations to avoid conflicts.
⚠️ Challenges & Fixes
❌ Repeated API Calls
Calling async functions inside JSX caused repeated requests.
Fix:
Moved all API logic into useEffect.
❌ State Mutation Bug
State was mutated directly instead of using the reducer.
Fix:
Replaced with proper dispatch-based updates.
❌ Vote Updates Not Refreshing
Votes did not reflect immediately after clicking.
Fix:
Re-fetch /api/win after each vote and separate reducer actions.
💡 What This Project Shows
- Full-stack data flow from UI to database
- Handling real-time-like updates without sockets
- Preventing abuse with client-side rate limiting
- Safe backend updates using MongoDB
- Managing complex UI state with
useReducer