Academic-Ballot is a resilient real-time classroom polling platform built on the MERN stack, designed for seamless teacherβstudent interaction. It features synchronized server-authoritative timers, secure single-vote enforcement, late-join recovery, and persistent state management to ensure reliability even after refresh or reconnection. Teachers can create polls and monitor live analytics, while students participate instantly, making academic decision-making interactive, scalable, and dependable.
- β¨ Key Features
- π οΈ Technology Stack
- ποΈ System Architecture
- π Project Structure
- π Getting Started
- βοΈ Environment Configuration
- π‘ REST API Endpoints
- π Real-Time Socket Events
- π₯οΈ Application Screens
- π Security & Data Integrity
- π License
- Create Polls - Create multiple-choice questions with customizable duration (30s, 45s, 60s, 90s)
- Mark Correct Answers - Set the correct answer when creating a poll
- Live Results - View real-time vote counts and percentage distributions
- Reveal Answers - Optionally reveal the correct answer to all participants
- Participant Management - View list of all connected students
- Kick Participants - Remove disruptive students from the session
- Poll History - Access complete history of all past polls
- In-App Chat - Communicate with students during sessions
- Join Sessions - Simple name-based registration to join a poll session
- Real-Time Voting - Submit votes instantly with real-time feedback
- Live Timer - See countdown timer for each poll
- Answer Reveal - View correct answers when revealed by teacher
- In-App Chat - Communicate with the class during sessions
- Real-Time Updates - WebSocket-powered instant updates
- Responsive Design - Works on desktop and mobile devices
- Auto Reconnection - Handles network interruptions gracefully
- Kick Prevention - Prevents previously kicked students from rejoining π οΈ Tech
The frontend of Academic-Ballot is built using a modern, performance-driven ecosystem designed for scalability, real-time responsiveness, and clean UI architecture.
- React 18 β A powerful component-based library for building dynamic and interactive user interfaces
- Vite β A fast, next-generation build tool ensuring optimized development and production performance
- Tailwind CSS β A utility-first CSS framework for crafting clean, consistent, and modern designs
- React Router β Declarative routing for smooth navigation across multiple application views
- Socket.io Client β Enables real-time, bidirectional communication between client and server
- Axios β A promise-based HTTP client for structured and secure API interactions
The backend of Academic-Ballot is engineered for reliability, scalability, and real-time performance, forming the core of the systemβs resilient architecture.
- Node.js β A high-performance runtime environment powering the server-side logic
- Express.js β A minimalist and flexible web framework for building structured REST APIs
- Socket.io β Enables real-time, event-driven communication with synchronized state updates
- MongoDB β A scalable NoSQL database ensuring persistent and reliable data storage
- Mongoose β An elegant ODM for schema modeling, validation, and data integrity management
Academic-Ballot is deployed on a modern cloud platform to ensure high availability, scalability, and seamless performance in production.
- Vercel β Hosts both frontend and backend services with optimized build pipelines, automatic deployments, and global edge distribution for fast and reliable access
academic-ballot/
βββ LICENSE # MIT License
βββ README.md # Project Documentation
βββ version.json # Version Information
βββ client/ # Frontend Application
β βββ public/ # Static Assets
β βββ src/
β β βββ api/ # API Configuration
β β β βββ index.js # Axios Instance & API URL
β β βββ components/ # Reusable UI Components
β β β βββ ChatPopup.jsx # Chat Interface
β β β βββ Layout.jsx # Main Layout
β β β βββ ParticipantsModal.jsx # Participants Management
β β β βββ ParticipantsPopup.jsx # Participants Quick View
β β β βββ PollCard.jsx # Poll Display Component
β β βββ hooks/ # Custom React Hooks
β β β βββ usePollTimer.js # Countdown Timer
β β β βββ useSocket.js # Socket Connection
β β βββ pages/ # Page Components
β β β βββ Home.jsx # Landing Page
β β β βββ PollHistory.jsx # Past Polls History
β β β βββ RoleSelection.jsx # Teacher/Student Selection
β β β βββ Student.jsx # Student Entry Page
β β β βββ StudentDashboard.jsx # Student Main Interface
β β β βββ StudentOnboarding.jsx # Student Registration
β β β βββ Teacher.jsx # Teacher Entry Page
β β β βββ TeacherDashboard.jsx # Teacher Main Interface
β β βββ App.jsx # Root Component
β β βββ index.css # Global Styles
β β βββ main.jsx # Entry Point
β βββ package.json # Frontend Dependencies
β βββ tailwind.config.js # Tailwind Configuration
β βββ vite.config.js # Vite Configuration
β βββ vercel.json # Vercel Deployment Config
β
βββ server/ # Backend Application
βββ config/
β βββ db.js # MongoDB Connection
βββ controllers/
β βββ poll.controller.js # Request Handlers
βββ models/
β βββ participant.model.js # Participant Schema
β βββ poll.model.js # Poll Schema
β βββ vote.moel.js # Vote Schema
βββ routes/
β βββ poll.routes.js # API Routes
βββ services/
β βββ poll.service.js # Business Logic
βββ sockets/
β βββ poll.socket.js # Socket Event Handlers
βββ package.json # Backend Dependencies
βββ server.js # Server Entry Point
βββ vercel.json # Vercel Deployment Config
Ensure you have the following installed:
- Node.js (v14 or higher)
- npm or pnpm
- MongoDB (local or Atlas)
-
Clone the Repository
git clone https://github.com/UjjwalSaini07/Academic-Ballot.git
cd Academic-Ballot -
Install Backend Dependencies
cd serverpnpm install
-
Install Frontend Dependencies
cd ../clientpnpm install
-
Start MongoDB (if using local instance)
mongod
-
Start Backend Server
cd serverpnpm dev
- Server runs on http://localhost:5000
-
Start Frontend Development Server
cd clientpnpm dev
- Client runs on http://localhost:3000
-
Build Frontend
cd client pnpm run build -
Start Production Server
cd server pnpm start
- Create a
.envfile in theserver/directory:
# Server Configuration
PORT=5000
NODE_ENV=development
# MongoDB Connection
# Option 1: Local MongoDB
MONGODB_URI=mongodb://localhost:27017/academic-ballot
# Option 2: MongoDB Atlas
MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/academic-ballot
# Frontend API URL (for CORS)
CLIENT_URL=http://localhost:3000- Create a
.envfile in theclient/directory:
# Development (use this when running server locally with npm run dev)
# VITE_API_URL=http://localhost:5000
# Production (use this when deploying to Vercel)
VITE_API_URL=https://academic-ballot-backend.vercel.app http://localhost:5000/api
| Method | Endpoint | Description |
|---|---|---|
GET |
/poll/active |
Get currently active poll |
GET |
/poll/history |
Get all completed polls |
GET |
/poll/participants |
Get all active participants |
GET |
/poll/check-kicked |
Check if student is kicked |
POST |
/poll |
Create a new poll |
POST |
/poll/vote |
Submit a vote |
POST |
/poll/kick |
Kick a participant |
POST |
/poll/register |
Register a student |
PUT |
/poll/:id/complete |
Complete a poll |
PUT |
/poll/:id/reveal |
Reveal the answer |
| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Server health status |
GET |
/api |
API information & endpoints |
| Event | Payload | Description |
|---|---|---|
join |
{ name: string } |
Join as participant |
create_poll |
{ question, options[], duration, correctOption } |
Create new poll |
vote |
{ pollId, studentName, optionIndex } |
Submit vote |
kick |
{ socketId } |
Kick participant |
chat_message |
{ message } |
Send chat message |
| Event | Payload | Description |
|---|---|---|
poll_created |
{ poll object } |
New poll created |
poll_ended |
{ poll object } |
Poll completed |
vote_update |
{ poll object } |
Vote count updated |
answer_revealed |
{ poll object } |
Answer revealed |
participants |
[{ id, name }] |
Participants list updated |
kicked |
- | Current user was kicked |
chat_message |
{ message } |
New chat message |
error_message |
{ error } |
Error occurred |
βββββββββββββββββββ
β Home Page β β Role Selection
ββββββββββ¬βββββββββ
β
ββββββ΄βββββ
β β
βΌ βΌ
βββββββββ ββββββββββ
βTeacherβ β Studentβ
βββββ¬ββββ βββββ¬βββββ
β β
βΌ βΌ
βββββββββββββ ββββββββββββββββββββββ
β Teacher β β Student β
β Dashboard β β Onboarding β
βββββββββββββ βββββββββββ¬βββββββββββ
β
βΌ
ββββββββββββββ
β Student β
β Dashboard β
ββββββββββββββ
| Page | Route | Description |
|---|---|---|
| Role Selection | / |
Choose Teacher or Student role |
| Teacher Dashboard | /teacher |
Create & manage polls, view results |
| Student Onboarding | /student |
Enter name to join |
| Student Dashboard | /student/dashboard |
View polls, submit votes |
| Poll History | /history |
View past poll results |
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Client ββββββΆβ Server ββββββΆβ MongoDB β
β (React) βββββββ (Express) βββββββ (Database) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β β
β β
βΌ βΌ
βββββββββββββββ βββββββββββββββ
β Socket.io ββββββΆβ Socket.io β
β (Client) β β (Server) β
βββββββββββββββ βββββββββββββββ
{
question: String, // Poll question
options: [String], // Answer options
duration: Number, // Duration in seconds
startTime: Number, // Poll start timestamp
status: String, // 'active' or 'completed'
correctOption: Number, // Index of correct answer (-1 if not set)
showAnswer: Boolean, // Whether answer is revealed
results: [{ // Vote counts per option
optionIndex: Number,
votes: Number
}],
createdAt: Date,
updatedAt: Date
}{
name: String, // Student name
socketId: String, // Socket connection ID
isActive: Boolean, // Currently connected
isKicked: Boolean, // Has been kicked
createdAt: Date,
updatedAt: Date
}{
pollId: ObjectId, // Reference to Poll
studentName: String, // Student's name
optionIndex: Number, // Selected option
createdAt: Date
}This project is licensed under the MIT License - see the LICENSE file for details.
Ujjwal Saini
- Email: ujjwalsaini0007+ballot@gmail.com
- Portfolio: https://www.ujjwalsaini.dev/
- GitHub: https://github.com/UjjwalSaini07
Made with β€οΈ by Ujjwal Saini