React Express PostgreSQL Socket.IO Claude AI License
Enterprise-grade technical interview platform powered by AI.
Real-time collaborative coding, AI-scored mock interviews, and 250+ curated problems β all in one place.
π Live Demo
Features Β· Quick Start Β· API Reference Β· Architecture Β· Dataset
- Features
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- API Reference
- Socket.IO Events
- User Roles
- Database Schema
- Scripts
- License
- AI Mock Interviews β Conversational AI interviewer powered by Claude evaluates answers and returns scored feedback with grades, strengths, and improvement suggestions
- Invite-Only Live Rooms β Interviewers create private sessions and invite candidates by username; only invited users can see and join their session
- Real-Time Collaboration β Shared Monaco editor powered by Yjs/CRDT with live cursors, language switching, and instant in-browser code execution
- 250+ Curated Problems β NeetCode 250 synced from LeetCode with difficulty filters, tag search, and pagination
- Performance Analytics β Visual charts tracking AI interview scores over time by topic and grade
- User Profile Management β Dedicated profile page where users can view their account info, change their password, and permanently delete their account
- Role-Based Access Control β Distinct permission flows for Candidates, Interviewers, and Admins
- Secure Authentication β JWT + httpOnly cookies, email verification, and password reset via email link
| Technology | Purpose |
|---|---|
| React 19 + Vite | UI framework and build tooling |
| React Router v7 | Client-side routing |
| Tailwind CSS v4 | Utility-first styling with custom design tokens |
| Monaco Editor | Code editor (same engine as VS Code) |
| Yjs + y-websocket | CRDT-based real-time collaborative editing |
| Socket.IO Client | Live room events (join, chat, code sync, problem selection) |
| Axios | HTTP client with JWT interceptors |
| React Hook Form | Form state management |
| Technology | Purpose |
|---|---|
| Express 5 | HTTP server and REST API |
| Prisma 7 + PostgreSQL | ORM and relational database |
| Socket.IO | WebSocket server for live rooms |
| y-websocket | Yjs WebSocket provider for collaborative editing |
| Anthropic SDK (Claude) | AI interview evaluation and feedback |
| bcrypt + JWT | Password hashing and stateless authentication |
| Zod | Request validation schemas |
| Redis (ioredis) | Caching layer for problems and pending registrations |
| Nodemailer + Brevo | Transactional email (verification, password reset) |
| Jest + Supertest | Unit and integration testing |
ai-interview-platform/
βββ backend/
β βββ config/
β β βββ config.js # Environment variables
β β βββ database.js # Prisma client
β β βββ redis.js # Redis connection
β βββ controllers/
β β βββ authController.js # Register, login, password, profile
β β βββ sessionController.js
β β βββ problemController.js
β β βββ aiController.js
β β βββ performanceController.js
β βββ middleware/
β β βββ auth.js # JWT verify + role-based access
β β βββ validate.js # Zod request validation
β β βββ errorHandler.js
β β βββ asyncHandler.js
β β βββ rateLimit.js
β βββ prisma/
β β βββ schema.prisma # Database models
β β βββ migrations/
β βββ routes/
β β βββ index.js
β β βββ authRoutes.js
β β βββ sessionRoutes.js
β β βββ problemRoutes.js
β β βββ aiRoutes.js
β β βββ performanceRoutes.js
β βββ services/
β β βββ aiService.js # Claude API integration
β β βββ emailService.js # Verification + reset emails
β β βββ cacheService.js # Redis helpers
β βββ sockets/
β β βββ roomHandler.js # Socket.IO room event listeners
β βββ utils/
β β βββ jwt.js
β β βββ validators.js # Zod schemas
β β βββ apiResponse.js # Standardized response format
β βββ index.js # Server entry point
β
βββ frontend/
βββ src/
βββ api/
β βββ axios.js # Axios instance with auth interceptors
βββ components/
β βββ ProtectedRoute.jsx
β βββ SessionCard.jsx
β βββ SessionList.jsx
β βββ PerformanceChart.jsx
βββ context/
β βββ AuthContext.jsx # Global auth state
βββ pages/
βββ Home.jsx
βββ Login.jsx
βββ Registar.jsx
βββ VerifyEmail.jsx
βββ ForgotPassword.jsx
βββ ResetPassword.jsx
βββ Dashboard.jsx
βββ Profile.jsx
βββ LiveInterviewRoom.jsx
- Node.js 18+
- PostgreSQL
- Redis
- An Anthropic API key
- A Brevo (Sendinblue) account for transactional email
git clone https://github.com/your-username/levelup-io.git
cd levelup-io/ai-interview-platform# Backend cd backend && npm install # Frontend cd ../frontend && npm install
Create a .env file inside the backend/ directory (see Environment Variables below).
cd backend
npx prisma migrate deploy
npx prisma generateOpen three terminal tabs:
# Terminal 1 β REST API + Socket.IO (port 3000) cd backend && npm run dev # Terminal 2 β Yjs WebSocket server for collaborative editing (port 3001) cd backend && npx y-websocket-server # Terminal 3 β Vite frontend dev server (port 5173) cd frontend && npm run dev
Create backend/.env with the following keys:
# Database DATABASE_URL=postgresql://user:password@localhost:5432/levelup # Server PORT=3000 NODE_ENV=development # Auth JWT_SECRET=your_long_random_secret_here JWT_EXPIRES_IN=7d COOKIE_MAX_AGE=604800000 # Anthropic (Claude AI) ANTHROPIC_API_KEY=sk-ant-... # Redis REDIS_URL=redis://localhost:6379 # Email (Brevo / Sendinblue) BREVO_API_KEY=your_brevo_api_key EMAIL_FROM=no-reply@yourdomain.com # Frontend origin (for CORS + email links) FRONTEND_URL=http://localhost:5173
Never commit your
.envfile. It is already listed in.gitignore.
All endpoints are prefixed with /api/v1. Authenticated routes require a valid JWT either via Authorization: Bearer <token> header or the token httpOnly cookie set at login.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/register |
β | Register β sends email verification link |
GET |
/auth/verify-email?token= |
β | Verify email and activate account |
POST |
/auth/resend-verification |
β | Resend verification email |
POST |
/auth/login |
β | Login, returns JWT + sets httpOnly cookie |
POST |
/auth/logout |
β | Clear auth cookie |
GET |
/auth/me |
β | Get current authenticated user |
POST |
/auth/forgot-password |
β | Send password reset link to email |
POST |
/auth/reset-password |
β | Reset password using token from email |
PUT |
/auth/change-password |
β | Change password (requires current password) |
DELETE |
/auth/delete-account |
β | Permanently delete account (requires password) |
| Method | Endpoint | Role | Description |
|---|---|---|---|
GET |
/sessions |
Any | List sessions (candidates see invitations only) |
GET |
/sessions/:id |
Any | Get session by ID (access-controlled) |
POST |
/sessions |
Interviewer / Admin | Create session and invite candidate by username |
PUT |
/sessions/:id |
Interviewer / Admin | Update session status |
DELETE |
/sessions/:id |
Admin | Delete session |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/problems |
β | List problems (filters: difficulty, search, page, limit) |
GET |
/problems/:id |
β | Get problem with test cases and starter code |
POST |
/problems/:id/run |
β | Run code against test cases (JavaScript sandbox) |
POST |
/problems/sync |
β | Sync NeetCode 250 from LeetCode into the database |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/ai/evaluate |
β | Submit answer for AI evaluation and scoring |
GET |
/ai/history |
β | Get past AI evaluation history |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/performance |
β | Get aggregate performance stats by topic and grade |
The live room connects to http://localhost:3000 with a JWT passed in auth.token.
| Event | Direction | Description |
|---|---|---|
join-room |
Client β Server | Join a room (access checked against DB) |
room-state |
Server β Client | Full room state sent on successful join |
room-error |
Server β Client | Emitted when the user is not invited |
user-joined |
Server β Room | Broadcast when a participant joins |
user-left |
Server β Room | Broadcast on disconnect |
code-change |
Bidirectional | Real-time code sync (fallback to Yjs) |
language-change |
Bidirectional | Language switch sync across participants |
chat-message |
Bidirectional | Chat messages (last 100 kept in memory) |
chat-typing |
Client β Room | Typing indicator broadcast |
select-problem |
Client β Server | Interviewer selects a problem for the session |
problem-selected |
Server β Room | Broadcasts selected problem to all participants |
| Role | Capabilities |
|---|---|
CANDIDATE |
AI mock interviews Β· Problem practice Β· View own invitations Β· Join invited rooms |
INTERVIEWER |
Everything above + Create sessions Β· Invite candidates by username Β· Select problems in room |
ADMIN |
Everything above + Delete sessions Β· View all sessions |
User
id, name, email (unique), username (unique), password, role
resetToken?, resetTokenExpiry?
createdAt, updatedAt
β hostedSessions[], attendedSessions[], evaluations[]
InterviewSession
id, title, role, level, status, scheduledAt
interviewerId β User
candidateId β User
AIEvaluation
id, userId, question, answer, role, level, topic
score, grade, strengths[], improvements[], idealAnswer
createdAt
Problem
id, title, slug (unique), difficulty
description, examples (JSON), constraints[], testCases (JSON)
starterCode (JSON), tags[]
npm run dev # Start with nodemon (hot reload) npm start # Production start npm test # Run Jest test suite npm run test:watch # Jest in watch mode
npm run dev # Vite dev server npm run build # Production build npm run preview # Preview production build locally npm run lint # ESLint
MIT