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:
- Type questions one by one into a form โ slow, error-prone, exhausting
- CSV upload only available on expensive paid plans
- Free plans with severe feature limitations
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:
- Wrap all cells in double quotes
- The Explanation column is optional โ existing CSVs without it still work
- You can generate questions with AI and export directly to this format
- Yoruba-language CSVs should be saved with UTF-8-BOM encoding
-- 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.
- Create a free project at supabase.com
- Go to SQL Editor โ New Query and run the schema above
- Go to Authentication โ Providers โ Email โ Enable email sign-in โ Disable "Confirm email" for development
- Go to Settings โ API and copy your:
- Project URL (e.g.
https://xxxxxx.supabase.co) - anon public key (starts with
eyJ...)
- Project URL (e.g.
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';- Fork this repository
- Go to Settings โ Pages โ Source: Deploy from branch โ Branch: main โ Save
- Your live URLs will be:
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.
- The Supabase anon key is designed for browser use โ it is safe in frontend code
- Row Level Security ensures teachers can only access their own exams and results
- Never put your Supabase
service_rolekey in any frontend file - Students do not need accounts โ they access exams by unique link only
- Tab-switching detection auto-submits the exam after 2 violations
| 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."
- ๐ง buildingmyictcareer@gmail.com
- ๐ผ linkedin.com/in/adewalesamsonadeagbo
- ๐ github.com/cssadewale
This project is open. If you are a Nigerian educator, developer, or anyone who sees value in free EdTech tools โ contributions are welcome.
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-idea - Commit your changes
- Open a Pull Request with a clear description of what changed and why
Before contributing, please read the project values:
- Free first โ no feature should require a paid service
- Mobile-friendly โ many Nigerian students use phones, not laptops
- Simple โ the code should be readable by someone learning, not just experts
- Backward compatible โ new CSV columns must remain optional
MIT License โ free to use, modify, and distribute. Attribution appreciated but not required.
If this saved you time, give it a โญ on GitHub. If it helped a student, that's enough.