Built by a tutor who got tired of typing exam questions one by one.
| Portal | Link |
|---|---|
| 👨🏫 Teacher / Admin Dashboard | cssadewale.github.io/cbt-system/teacher.html |
| 🎓 Student Exam Portal | cssadewale.github.io/cbt-system/student.html |
I have been a Mathematics, Further Mathematics, Physics and Chemistry tutor for over 10 years. I set CBT exams regularly for my students — for WAEC practice, JAMB drills, terminal assessments, and class tests.
Every CBT platform I found had the same frustrating pattern:
Meanwhile, I was already generating exam questions with AI and exporting them to CSV in seconds. The gap between what I had and what the platforms offered made no sense.
So I built my own. Free. Open source. CSV-first. With every feature I actually needed — and a few the paid platforms don’t even have.
| Feature | Description | |———|————-| | 🔐 Secure auth | Register and sign in with email and password | | 📄 CSV upload | Upload one file — full exam ready in seconds | | ⚙️ Exam configuration | Set subject, duration, question count, and attempt limit per exam | | 🔀 Question randomisation | Questions pulled randomly from your question bank per student | | 👁️ Exam preview | Preview all questions and correct answers before publishing | | 🔗 Instant sharing | Auto-generated shareable exam link — send directly via WhatsApp | | 🔒 Exam control | Lock or unlock exams at any time | | 📊 Results dashboard | View all student submissions with scores, time taken, and attempt number | | 🔍 Search & filter | Search results by student name or class | | ⬇️ CSV export | Download all results as a spreadsheet |
| Feature | Description | |———|————-| | 🔗 Direct link access | No account needed — click the link and start | | ⏱️ Countdown timer | Live timer with minutes and seconds | | 🧭 Question navigator | Jump to any question, see answered/unanswered at a glance | | 🔀 Randomised options | Answer options shuffled per student — makes copying impossible | | 🧮 Scientific calculator | Built-in calculator with sin, cos, tan, log, √, x² — ideal for Maths and Physics | | 📝 Attempt limit enforcement | System checks attempt history before allowing entry | | 🛡️ Anti-cheat measures | Tab-switching detection — exam auto-submits after 2 violations | | 📋 Instant results | Score and full answer review immediately after submission | | 💡 Explanations | Teacher-written explanations shown for wrong answers |
cbt-system/
│
├── teacher.html # Admin portal — authentication, exam creation, results
├── student.html # Student portal — exam engine, calculator, results
│
├── sample/
│ └── further_maths_sample.csv # Sample CSV question file
│
└── README.md
Each exam is powered by a single CSV file. This is the format:
"Question","A","B","C","D","Answer","Explanation"
"Find lim(x→2) (x²-4)/(x-2)","Undefined","4","2","0","B","Factor as (x-2)(x+2). Cancel (x-2) to get x+2. At x=2 this equals 4."
"Differentiate y = x³eˣ","3x²eˣ + x³eˣ","3x²eˣ","3x²eˣ - x³eˣ","x³eˣ","A","Product rule: (x³)'eˣ + x³(eˣ)' = 3x²eˣ + x³eˣ."
| Column | Field | Required |
|---|---|---|
| 1 | Question text | ✅ |
| 2 | Option A | ✅ |
| 3 | Option B | ✅ |
| 4 | Option C | ✅ |
| 5 | Option D | ✅ |
| 6 | Correct answer (A / B / C / D) | ✅ |
| 7 | Explanation for wrong answers | ⬜ Optional |
Notes:
-- Exams table
create table exams (
id uuid default gen_random_uuid() primary key,
teacher_id uuid references auth.users(id) on delete cascade,
subject text not null,
duration integer not null,
attempt_limit integer default 1,
select_count integer default 0,
code text unique not null,
csv_data jsonb not null,
is_open boolean default true,
created_at timestamp with time zone default now()
);
-- Results table
create table results (
id uuid default gen_random_uuid() primary key,
exam_id uuid references exams(id) on delete cascade,
student_name text not null,
student_class text not null,
score integer not null,
total integer not null,
attempt_number integer default 1,
time_taken integer,
created_at timestamp with time zone default now()
);
-- Row Level Security
alter table exams enable row level security;
alter table results enable row level security;
-- Teachers manage their own exams
create policy "teacher_manage_exams"
on exams for all
using (auth.uid() = teacher_id)
with check (auth.uid() = teacher_id);
-- Public can read exams by code (students need this)
create policy "public_read_exams"
on exams for select using (true);
-- Anyone can insert results (students submitting)
create policy "public_insert_results"
on results for insert with check (true);
-- Anyone can read results (for attempt checking)
create policy "public_select_results"
on results for select using (true);
This platform is designed for zero-cost self-hosting. You need a GitHub account and a free Supabase account. Nothing else.
https://xxxxxx.supabase.co)eyJ...)In both teacher.html and student.html, find these two lines near the top of the <script> section and replace with your values:
const SB_URL = 'https://your-project-id.supabase.co';
const SB_KEY = 'your-anon-public-key';
https://yourusername.github.io/cbt-system/teacher.html
https://yourusername.github.io/cbt-system/student.html
Create an exam on the teacher dashboard, copy the generated link, and send it to students via WhatsApp. They click, enter their details, and the exam begins — no account, no app download, no confusion.
service_role key in any frontend file| Layer | Technology | Cost |
|---|---|---|
| Frontend | HTML5, CSS3, Vanilla JavaScript | Free |
| Hosting | GitHub Pages | Free |
| Database | Supabase (PostgreSQL) | Free tier |
| Authentication | Supabase Auth | Free tier |
| Fonts | Google Fonts (Plus Jakarta Sans) | Free |
| Editor | Acode (Android) | Free |
No frameworks. No npm. No build tools. No Node.js. Just two HTML files that work.
Every line of code in this project was written, tested, and deployed from an Android tablet using the Acode editor. No laptop. No PC. No desktop IDE.
This was a deliberate constraint — not a limitation. It proves that the barrier to building real, production-grade software is not hardware. It is clarity of thought and willingness to learn.
Adewale Samson Adeagbo
I am a secondary school tutor with over 10 years of experience teaching Mathematics, Further Mathematics, Physics, and Chemistry at JSS and SSS level — both virtually and in person across Lagos and Ogun State, Nigeria.
I began my data science journey in 2024. I can write and read Python and SQL, handle end-to-end data science projects, work with GitHub, and deploy models on Streamlit. I am comfortable at an intermediate level and growing.
This project was born from a simple frustration: I could not find a free CBT platform that let me upload a CSV. Every tool I found made me type questions one by one, or charged money for the feature I needed. A colleague showed me that AI could guide someone with limited web experience to build real software — and that idea would not leave me alone.
So I built this. From scratch. On a tablet. With AI as my guide and a real problem as my north star.
“Data science taught me that if you can think through a problem clearly, you can find a path to a solution — even in unfamiliar territory.”
This project is open. If you are a Nigerian educator, developer, or anyone who sees value in free EdTech tools — contributions are welcome.
git checkout -b feature/your-ideaBefore contributing, please read the project values:
MIT License — free to use, modify, and distribute. Attribution appreciated but not required.