A free, open-source live polling tool for instructors. Students join from any device with a browser; no app install, no account, no login required. Results appear in real time. All data stays in your own Firebase project.
- Create multiple-choice polls on the fly or prepare them in advance as poll sets
- Control when students see results and whether the correct answer (if any) is revealed
- Step through a poll set sequentially at your own pace
- View poll history and attendance, grouped by poll set and session
- CSV export of poll results (per-poll and per-session)
- Delete individual polls from history
- Password-protected teacher and history access
- Join with just a name — no account needed
- See results and correct answer when the instructor chooses to reveal them
- Works on phone, tablet, laptop, or desktop
- Create polls in a plain text format and paste them in bulk
- Or build polls one at a time using the form interface
- Set default duration and display policies for the whole set, with per-poll overrides
- Edit sets in form view (one poll at a time) or text view (all at once)
- Individual polls are separated by
---. - The first prompt line begins with
Q:. - A blank line is required to separate the prompt from the block of answers. (This allows multi-line prompts.)
- The correct answer is marked with a
*prefix. - Each answer has a letter followed by
.. - Per-poll overrides go before the
Q:line.
| Key | Values | Default |
|---|---|---|
duration |
seconds, e.g. 30, 90 |
poll set default |
results |
submit, manual, never |
poll set default |
correct |
results, manual, never |
poll set default |
| Value | Meaning |
|---|---|
submit |
Students see results after they submit their answer |
manual |
Instructor reveals results with a toggle on the dashboard |
never |
Results never shown to students |
results |
Correct answer shown at the same moment as results |
Q: What is photosynthesis?
* A. Converts sunlight into energy
B. Breaks down glucose
C. Absorbs water through roots
D. Releases CO2
---
duration: 90
correct: manual
Q: Which organelle contains chlorophyll?
A. Mitochondria
* B. Chloroplast
C. Nucleus
D. Vacuole
ClassPoll uses Firebase Realtime Database as its backend; there's no server for you to maintain. Each instructor deploys their own instance with their own Firebase project, so student data stays private.
Click Fork at the top right of this page. Clone your fork:
git clone https://github.com/YOUR_USERNAME/classroom-polling.git
cd classroom-polling
git remote add upstream https://github.com/MetroCS/classroom-polling.git
npm install- Go to console.firebase.google.com
- Click Add project → name it (e.g.
classroom-polling) → disable Analytics → Create project
- In the Firebase Console left sidebar: Build → Realtime Database
- Click Create Database → choose your region
- If prompted for security rules, choose locked mode — you will set them in Step 7
If the setup dialog does not show an Enable button, use the Firebase CLI:
npm install -g firebase-tools
firebase login
firebase init database- Firebase Console → Build → Authentication → Get started
- Under Sign-in providers → Anonymous → toggle ON → Save
- Firebase Console → gear icon ⚙ → Project settings
- Under Your apps → click </> → register a web app
- Copy the
firebaseConfigvalues shown
Copy the example file and fill in your values:
cp .env.example .env.localEdit .env.local with your Firebase config values and a teacher password of your choice:
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
VITE_FIREBASE_DATABASE_URL=https://your_project-default-rtdb.firebaseio.com
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_project.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
VITE_TEACHER_PASSWORD=your_password_here
Never commit .env.local to git. It is already listed in .gitignore.
- Firebase Console → Realtime Database → Rules tab
- Replace everything with the contents of
firebase-rules.json - Click Publish
npm run devOpen http://localhost:5173/classroom-polling/. Open two browser tabs — one as teacher, one as student — to verify everything works.
If your GitHub repository is named something other than classroom-polling,
update vite.config.js:
export default defineConfig({
plugins: [react()],
base: '/your-repo-name/',
})git add .
git commit -m "Initial setup"
git push origin main
npm run build
git add dist -f
git commit -m "Deploy"
git subtree push --prefix dist origin gh-pagesThen in GitHub → your repo → Settings → Pages:
- Source: Deploy from a branch
- Branch: gh-pages → / (root) → Save
Your app will be live at:
https://YOUR_USERNAME.github.io/classroom-polling/
For subsequent deployments:
npm run build
git add dist -f
git commit -m "Update deployment"
git subtree push --prefix dist origin gh-pages
git push origin maingit fetch upstream
git merge upstream/main- Open the app → I'm the Teacher → enter your password
- Click New Poll → enter question and options → click Start Poll
- Share your app URL with students — they click I'm a Student, enter their name, and wait
- Students see the poll instantly; results update live on your dashboard
- For standalone polls, click Close Poll when done. When running a poll set, click End Poll to stop accepting answers while staying in the set, then *Next Poll to advance
- Click Poll Sets → + New Set
- Enter a name, set defaults, paste your polls in plain text → Preview → Save Set
- Open the set → click Launch
- Step through polls with Next Poll; use End Poll to pause between polls
- Click Finish Set when done
- Click History → enter teacher password
- Polls tab: past polls grouped by set, expandable with per-option results
- Attendance tab: students who joined, grouped by date
| File | What to change |
|---|---|
.env.local |
Teacher password, Firebase config |
firebase-rules.json |
Database security rules |
vite.config.js |
Repository name for GitHub Pages base path |
src/index.css |
Colors, fonts, visual design |
classroom-polling/
├── src/
│ ├── firebase.js Firebase initialization (config from .env.local)
│ ├── utils/
│ │ ├── firebaseOps.js All database read/write operations
│ │ └── pollParser.js Plain text poll format parser
│ │ └── csvExport.js CSV export utilities
│ ├── pages/
│ │ ├── RoleSelector.jsx Landing page
│ │ ├── TeacherPage.jsx Teacher dashboard
│ │ ├── StudentPage.jsx Student poll experience
│ │ ├── PollHistory.jsx History and attendance
│ │ ├── PollSets.jsx Poll set list and creation
│ │ └── PollSetDetail.jsx Poll set editing and launch
│ ├── App.jsx
│ ├── main.jsx
│ └── index.css
├── .env.example Template — copy to .env.local and fill in values
├── firebase-rules.json Paste into Firebase Console Rules tab
├── vite.config.js
└── package.json
The Firebase Spark (free) plan is sufficient for typical classroom use:
| Resource | Free limit | Typical usage |
|---|---|---|
| Simultaneous connections | 100 | Fine for one class |
| Storage | 1 GB | Years of poll data |
| Downloads/month | 10 GB | ~500,000 page loads |
- Teacher password is a single shared secret; not suitable for multiple instructors sharing one instance
- Code formatting in questions is plain text only (markdown support planned)
- Student names are self-reported and not authenticated
- Code block rendering in questions and options
- Student self-paced mode for poll sets
Contributions welcome — see CONTRIBUTING.md.
Copyright (C) 2026 Dr. Jody Paul
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See LICENSE for the full license text.