Self-hosted open source CBT backend built with Go, Gin, PostgreSQL, REST, and WebSockets.
- Students and teachers can sign up and log in.
- Teachers can create exam rooms with objective/theory questions.
- Teachers can start, close, list, and inspect their rooms.
- Students can join rooms by room code, fetch exam questions, and submit answers.
- Objective answers are graded automatically and stored in
results. - Students only see their results when the teacher enables
show_results_to_students. - Room sockets are closed when a teacher closes a room or when the duration expires.
Create a .env file:
POSTGRES_URI=postgres://user:password@localhost:5432/opencbt?sslmode=disable
JWT_SECRET=replace-this-secret
JWT_TTL_HOURS=24
PORT=8080Run the schema:
psql "$POSTGRES_URI" -f src/schema/query.sqlStart the API:
go run .Auth:
POST /api/auth/signupPOST /api/auth/login
Teacher routes require Authorization: Bearer <token> from a teacher account:
POST /api/teacher/roomsGET /api/teacher/roomsGET /api/teacher/rooms/:room_idPOST /api/teacher/rooms/:room_id/startPOST /api/teacher/rooms/:room_id/close
Student routes require Authorization: Bearer <token> from a student account:
POST /api/student/rooms/joinGET /api/student/rooms/:room_id/examPOST /api/student/rooms/:room_id/submitGET /api/student/results
WebSocket:
GET /ws/rooms/:room_id?token=<jwt>
{
"title": "Biology Mock Exam",
"description": "First term practice",
"duration_minutes": 45,
"show_results_to_students": true,
"pass_mark_percentage": 50,
"questions": [
{
"text": "What is the powerhouse of the cell?",
"type": "objective",
"points": 1,
"options": [
{ "text": "Nucleus", "is_correct": false },
{ "text": "Mitochondria", "is_correct": true },
{ "text": "Ribosome", "is_correct": false }
]
}
]
}