Spaces:
Sleeping
Sleeping
AI InterviewMentor β Architecture Overview
System Architecture
Browser (React SPA)
β
βΌ
HF Spaces Docker Container (port 7860)
βββ FastAPI (Python 3.11)
β βββ /api/auth/* β Custom JWT auth (jose + bcrypt)
β βββ /api/batches/* β Batch/class management
β βββ /api/topics/* β Topic CRUD + unlock control
β βββ /api/upload β CSV question bank ingestion
β βββ /api/sessions/* β Session detail + reports
β βββ /api/instructor/* β Dashboard + student analytics
β βββ /api/student/* β Student dashboard
β βββ /interview/* β LangGraph interview engine
β βββ / (catch-all) β React static files (Vite build)
β
βββ LangGraph Engine
β βββ ask_question β Picks next question from bank
β βββ evaluate_answer β Scores: strong | shallow | wrong
β βββ counter_question β Probing follow-up for shallow answers
β βββ summarize β Compresses conversation every 4 turns
β βββ generate_report β Final scored feedback JSON
β
βββ External Services
βββ NeonDB (PostgreSQL)
β βββ public schema β App data (users, batches, topics, questions, sessions)
β βββ checkpointer β LangGraph state (auto-managed)
βββ OpenRouter API β MiniMax 2.7 model
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite + TypeScript + Tailwind CSS v3 (dark theme only) |
| Backend | FastAPI (Python 3.11) |
| AI Orchestration | LangGraph (state machine with checkpointing) |
| Database | NeonDB (PostgreSQL) β app data + LangGraph checkpoints |
| AI Gateway | OpenRouter β MiniMax 2.7 |
| Auth | Custom JWT (jose + bcrypt) β no third-party auth |
| Deployment | Single Docker container on Hugging Face Spaces (port 7860) |
Key Design Decisions
- Single container deployment β React static build served by FastAPI, no split deployment
- Same-origin API calls β No CORS needed, browser hits FastAPI directly
- Two DB schemas β
publicfor app data,checkpointerfor LangGraph state - Token budget control β Summarize every 4 turns, ~700 token ceiling per LLM call
- session_id = thread_id β Natural scoping between DB sessions and LangGraph state
- CSV-to-DB question ingestion β No file storage needed (no S3/R2)
- Custom JWT only β Supabase/Firebase explicitly banned (hackathon rules)
Database Schema
Tables
- users β id, full_name, email, password_hash, role (student|instructor), batch_id
- refresh_tokens β id, user_id, token_hash, expires_at
- batches β id, name, instructor_id, class_code (auto-generated)
- topics β id, batch_id, name, is_unlocked, order_index
- questions β id, topic_id, question_text, difficulty (easy|medium|hard)
- interview_sessions β id, student_id, topic_id, status, score, feedback (JSONB)
Relationships
instructor (user) β creates batches β has topics β has questions
student (user) β joins batch via class_code β takes interview_sessions on topics
Auth Flow
- Access token: HS256 JWT, 15min expiry, sent in
Authorization: Bearerheader - Refresh token: 7-day expiry, bcrypt-hashed in DB, sent as httpOnly cookie
- Route protection:
get_current_userdependency extracts JWT βrequire_instructor/require_studentrole guards
LangGraph Interview Flow
START β ask_question β [wait for student answer] β evaluate_answer
β
ββββββββββββββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
counter_question ask_question generate_report β END
β (or summarize
βΌ every 4 turns)
evaluate_answer
- 8 turns max or question bank exhausted β generate_report
- Counter-questions fire once per shallow answer (no double-countering)
- Summarize node compresses messages every 4 turns to keep token usage flat
Frontend Architecture
- Routing: React Router with
ProtectedRoutewrapper - State: Zustand stores β
authStore(JWT + user),interviewStore(session state) - API layer: Single
apiFetchwrapper with auto-refresh on 401 - Pages: Login, Signup, StudentDashboard, Interview, Report, InstructorDashboard, Upload, StudentDetail
Scope Boundary (Not In V1)
Voice input, email notifications, leaderboard, certificates, question bank editor UI, light theme, multi-instructor batches.