Rohini's JAM Academy LMS
Design & Architecture Document v1.0

Contents
  1. System Overview
  2. Architecture
  3. Design System
  4. Data Model
  5. API Surface
  6. Key Flows
  7. Third-Party Integrations

1. System Overview

An Edmingle-style Learning Management System for IIT-JAM coaching with three roles — Student, Teacher, Admin — built to scale into a multi-academy SaaS. Features: course catalog with video/PDF curriculum & progress tracking, batches/cohorts, payment checkout (Stripe/Razorpay placeholders in demo mode), live class scheduling (batch-scoped, Zoom-ready), timed auto-graded mock tests with review & leaderboards, assignments with file submissions and grading, announcements, in-app + email (Resend) notifications, completion certificates, teacher analytics and an admin panel.

2. Architecture

Browser (React SPA, port 3000)
   │  HTTPS — all API calls prefixed /api → routed by K8s ingress to :8001
   ▼
FastAPI backend (uvicorn, 0.0.0.0:8001)
   ├── routers/*  (feature-modular API)
   ├── auth_utils (bcrypt + JWT Bearer/cookie, role guards)
   ├── notify.py  (in-app notifications + Resend email, fire-and-forget)
   ├── zoom_service.py (Server-to-Server OAuth, token cache)
   └── uploads/   (file storage on disk, served via /api/files/{id})
   ▼
MongoDB (motor async driver; DB name from env DB_NAME)
LayerTechnologyNotes
FrontendReact 19 (CRA + craco), Tailwind CSS, shadcn/ui, lucide-react, recharts, axios, sonner, dayjsSPA with react-router; token in localStorage jam_token
BackendFastAPI + uvicorn (hot reload), Pydantic v2, PyJWT, bcrypt, httpx, resendAll routes under /api; supervisor-managed
DatabaseMongoDB via motorUUID string _ids (JSON-safe, no ObjectId leakage)

3. Design System

TokenValue
StyleSwiss / International Typographic — high-contrast light theme, sharp corners (no border radius), 1px zinc borders, generous whitespace
PrimaryKlein Blue #1D4ED8 (actions, links, active nav)
AccentSignal Red #E63946 / red-600 (live badges, alerts, destructive)
Neutralszinc-50 … zinc-950 (backgrounds, borders, text)
Headings fontCabinet Grotesk (fontshare) — class font-heading
Body fontIBM Plex Sans (Google Fonts)
BrandingAcademy name configurable: REACT_APP_ACADEMY_NAME (frontend) / ACADEMY_NAME (backend) → src/lib/config.js & notify.py

4. Data Model (MongoDB collections)

CollectionKey fields
users_id(uuid), name, email(unique idx), password_hash(bcrypt), role(student|teacher|admin), created_at
courses_id, title, subject, description, thumbnail, price, duration, published, teacher_id, teacher_name, sections:[{id,title,lessons:[{id,title,type(video|pdf),url,duration}]}]
enrollments_id, course_id, student_id, batch_id?, completed_lessons:[lessonId], payment_id?, enrolled_at — unique idx (course_id,student_id)
batches_id, course_id, teacher_id, name, start_date, schedule, capacity
tests_id, title, subject, duration_min, published, course_id?, course_name?, total_marks, teacher_id, questions:[{id,text,options[4],correct_index,marks}]
test_attempts_id, test_id, student_id, answers{qid:optionIdx}, score, total, correct_count, question_count, submitted_at — unique idx (test_id,student_id)
assignments_id, title, subject, description, due_date, max_marks, course_id?, course_name?, teacher_id
submissions_id, assignment_id, student_id, student_name, content, link, file_url, file_name, grade, feedback, submitted_at
live_classes_id, title, subject, description, start_time(ISO), duration_min, meeting_link, course_id?, batch_id?, course_name?, batch_name?, zoom_meeting_id?, teacher_id
announcements_id, title, body, teacher_id, teacher_name, created_at
payments_id, student_id, course_id, course_title, batch_id?, amount, currency, method(stripe|razorpay), gateway(demo|…), status(pending|paid|failed), created_at, paid_at
notifications_id, user_id, title, body, link, read, created_at — idx (user_id, created_at desc)
certificates_id, cert_no(JAM-XXXXXXXX), student_id, student_name, course_id, course_title, subject, teacher_name, issued_at
password_reset_tokens_id(token), user_id, expires_at(TTL idx), used
files_id(uuid), filename, ext, content_type, size, uploader_id

5. API Surface (all prefixed /api)

DomainEndpoints
AuthPOST /auth/register · /auth/login · /auth/logout · GET /auth/me · POST /auth/forgot-password · /auth/reset-password
CoursesGET/POST /courses · GET/PUT/DELETE /courses/{id} · POST …/sections · …/sections/{sid}/lessons · …/enroll · …/lessons/{lid}/complete · GET /courses/{id}/students · /teacher/courses · /student/enrollments
BatchesGET/POST /courses/{id}/batches · DELETE /batches/{id} · GET /batches/{id}/students
TestsGET/POST /tests · GET/PUT/DELETE /tests/{id} · POST /tests/{id}/attempt · GET …/attempts · …/review · …/leaderboard · /student/attempts
AssignmentsGET/POST /assignments · DELETE /assignments/{id} · POST …/submit · GET …/submissions · PUT /submissions/{id}/grade
Live classesGET/POST /live-classes · DELETE /live-classes/{id} · GET /zoom/config
PaymentsGET /payments/config · POST /payments/checkout · /payments/{id}/confirm · GET /student/payments
FilesPOST /files/upload (multipart, 25MB, ext whitelist) · GET /files/{id}
NotificationsGET /notifications · POST /notifications/read-all
CertificatesGET /courses/{id}/certificate · /student/certificates
DashboardsGET /dashboard/student · /dashboard/teacher · /dashboard/teacher/analytics
AdminGET /admin/stats · /admin/users?q=&role= · PUT /admin/users/{id}/role · DELETE /admin/users/{id} · GET /admin/payments

6. Key Flows

Authentication

Register/login → bcrypt verify → JWT (HS256, 7-day exp, claims sub/email/role) returned in body and httpOnly cookie. Frontend stores token in localStorage and sends Authorization: Bearer via axios interceptor. get_current_user checks header then cookie; require_role(*roles) guards endpoints. Password reset: single-use token (secrets.token_urlsafe) with 1h TTL, emailed as link.

Enrollment & payment (demo mode)

EnrollModal → GET payments/config (demo when gateway keys empty) → POST /payments/checkout (creates pending payment, validates batch capacity) → POST /payments/{id}/confirm → marks paid + creates enrollment + notifies student (email) and teacher. Free courses enroll directly. When real keys are added, confirm returns 501 until gateway verification is implemented.

Progress & certificates

Marking a lesson complete does $addToSet completed_lessons; progress = completed/total lessons. At 100%, GET /courses/{id}/certificate issues (or returns) a certificate with unique cert_no.

Test lifecycle

Teacher publishes MCQs (optionally course-linked). Students see tests that are global or belong to enrolled courses; correct_index is stripped from student payloads. Attempt is auto-graded server-side, one per student (unique index). Review returns answers + correct indexes; leaderboard ranks by score desc, time asc, computes percentile.

Batch-scoped visibility

student_class_query() builds $or: global classes, OR classes of enrolled courses where batch is null or matches the student's enrollment batch. Reused by live-class list and student dashboard.

Notifications

notify(user_ids, title, body, link, email_subject?) inserts db.notifications docs and fire-and-forgets Resend emails (branded HTML template). Bell component polls every 30s.

7. Third-Party Integrations

ServiceStatusConfig (backend/.env)
Resend (email)ACTIVE — testing mode (delivers only to account owner until domain verified at resend.com/domains)RESEND_API_KEY, SENDER_EMAIL
Stripe / RazorpayPLACEHOLDER — demo checkout simulates successSTRIPE_API_KEY, RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET
Zoom (Server-to-Server OAuth)WIRED — awaiting credentials; auto-create meeting checkbox disabled until setZOOM_ACCOUNT_ID, ZOOM_CLIENT_ID, ZOOM_CLIENT_SECRET

© 2026 Rohini's JAM Academy · Design & Architecture v1.0