Intervia is a full-stack AI mock interview platform for practicing role-based interviews. Users can create an account, choose a work field, select a role and difficulty, answer AI-generated questions, receive AI feedback and scores, and review their interview history over time.
The app is built as a practical job-prep tool and a portfolio project that demonstrates authentication, frontend state management, backend APIs, PostgreSQL persistence, and AI integration in one product.
- User signup, login, logout, and protected routes
- Forgot-password flow with email verification and direct password reset
- JWT authentication stored in an HTTP-only cookie
- Field, role, and difficulty selection
- AI-generated interview sessions with 10 questions
- Text answer input
- Browser speech-to-text answer input where supported
- Per-answer AI feedback and score
- Interview completion with total score out of 100
- Active, abandoned, resumed, and completed interview states
- Interview history page
- Interview review page with answered and unanswered questions
- Profile page with user details, total interviews, average score, and latest session
- Redux Toolkit state management for interviews and app data
- Supabase/PostgreSQL-compatible database access
- Vercel SPA rewrite config for the frontend
- React
- Vite
- Tailwind CSS
- React Router
- Redux Toolkit
- React Redux
- Axios
- React Markdown
- Node.js
- Express
- PostgreSQL with
pg - JWT
- Cookie Parser
- CORS
- Groq SDK
- Groq API
- Current model:
llama-3.3-70b-versatile - Installed but not currently wired in the active AI service: OpenAI SDK and Google GenAI SDK
- PostgreSQL
- Supabase compatible
ai-interview-app/
|-- client/ # React Vite frontend
| |-- public/
| |-- vercel.json # SPA routing rewrites
| `-- src/
| |-- app/ # Redux store
| |-- assets/
| |-- components/
| |-- context/ # Auth context
| |-- features/ # Redux slices
| |-- lib/ # API helpers, constants, icons, utilities
| |-- pages/ # App pages
| `-- routes/ # Protected/public/shared layouts
|-- server/ # Node + Express backend
| |-- controllers/
| |-- lib/
| |-- middlewares/
| |-- queries/
| |-- routes/
| |-- services/
| |-- connection.js
| `-- index.js
`-- README.md| Route | Description |
|---|---|
/auth/login |
Login page |
/auth/register |
Registration page |
/auth/forgot-password |
Verify email and reset password |
/ |
Home dashboard and interview starter |
/interview |
Active interview session |
/history |
Interview history |
/review/:interviewId |
Detailed interview review |
/profile |
User profile and stats |
| Method | Route | Description |
|---|---|---|
| POST | /auth/register |
Create a new user and set auth cookie |
| POST | /auth/login |
Log in and set auth cookie |
| POST | /auth/logout |
Clear auth cookie |
| POST | /auth/forgot-password |
Verify that an email belongs to an existing user |
| POST | /auth/reset-password |
Update the password for a verified email |
| GET | /me |
Return the authenticated user |
All interview routes are protected by verifyUser.
| Method | Route | Description |
|---|---|---|
| GET | /interview/all |
Get all interviews for the logged-in user |
| POST | /interview/start |
Create an interview and generate questions |
| GET | /interview/:interviewId |
Get interview details and questions |
| PUT | /interview/answer/:questionId |
Submit an answer and get AI feedback |
| PUT | /interview/submit/:interviewId |
Mark interview as completed with final score |
| PUT | /interview/abandon/:interviewId |
Mark interview as abandoned |
| PUT | /interview/resume/:interviewId |
Resume an incomplete interview |
- The user signs up or logs in.
- The frontend checks the session with
/me. - The user selects a field, role, and difficulty.
- The backend creates an interview record.
- Groq generates 10 role-specific interview questions.
- Questions are saved in PostgreSQL.
- The user answers questions with text or browser speech recognition.
- Each submitted answer is evaluated by Groq.
- The backend stores the answer, feedback, score, and answered timestamp.
- When the interview is finished, the frontend totals the scores and submits the final interview score.
- The user can view past sessions, resume incomplete interviews, and review completed interviews.
- The user opens
/auth/forgot-password. - The user enters their email address.
- The frontend calls
/auth/forgot-passwordto verify that the email exists. - After verification, the user enters and confirms a new password.
- The frontend calls
/auth/reset-password. - The backend hashes the new password with the configured
HASH_SALT. - The UI shows a password reset success modal with a link back to sign in.
This is currently a direct in-app reset flow. Email delivery and one-time reset tokens are good next improvements for production use.
- Node.js
- npm
- PostgreSQL database or Supabase project
- Groq API key
git clone <your-repo-url>
cd ai-interview-appcd server
npm installCreate a .env file inside server/:
PORT=8000
DATABASE_URL=your_postgresql_connection_string
JWT_SECRET=your_jwt_secret
HASH_SALT=your_password_hash_salt
GROQ_API_KEY=your_groq_api_key
CLIENT_URL=http://localhost:5173
NODE_ENV=developmentCLIENT_URL is used by CORS. For production, set it to your deployed frontend URL.
The app expects users, interviews, and interview_questions tables.
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE interviews (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role TEXT NOT NULL,
difficulty TEXT NOT NULL,
work_field TEXT,
score INTEGER,
status TEXT NOT NULL DEFAULT 'active',
started_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
CREATE TABLE interview_questions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
interview_id UUID NOT NULL REFERENCES interviews(id) ON DELETE CASCADE,
question TEXT NOT NULL,
question_order INTEGER NOT NULL,
answer TEXT,
feedback TEXT,
evaluation_score INTEGER,
answered_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);npm startThe API runs on:
http://localhost:8000The backend also has a dev script:
npm run devThat script uses nodemon, so make sure nodemon is available if you use it.
Open a new terminal:
cd client
npm installCreate a .env file inside client/:
VITE_API_URL=http://localhost:8000/Keep the trailing slash because frontend API helpers append route paths directly.
npm run devThe app runs on:
http://localhost:5173cd server
npm start # Start backend with node
npm run dev # Start backend with nodemon if availablecd client
npm run dev # Start Vite dev server
npm run build # Build frontend for production
npm run preview # Preview production build
npm run lint # Run ESLint{
"name": "Priyanshu",
"email": "priyanshu@example.com",
"password": "password123"
}{
"work_field": "Software Engineering",
"role": "Frontend Engineer",
"difficulty": "Medium"
}{
"question": "What is the virtual DOM in React?",
"answer": "The virtual DOM is React's in-memory representation of the UI..."
}{
"score": 82
}{
"email": "priyanshu@example.com"
}{
"email": "priyanshu@example.com",
"password": "newPassword123",
"confirmPassword": "newPassword123"
}Intervia currently includes role presets for:
- Software Engineering
- Data and AI
- Design
- Product
- Marketing
- Sales
- HR and Recruiting
- Finance and Accounting
- Operations
- Cybersecurity
- Cloud and Infrastructure
- Support
- Education
- Healthcare
- Legal
- The frontend includes
client/vercel.jsonso client-side routes work correctly on Vercel. - The backend must allow the deployed frontend URL through
CLIENT_URL. - In production, cookies use
sameSite: "none"andsecure: true, so the backend must be served over HTTPS. - Configure production environment variables separately for the client and server.
- Add formal database migrations
- Add stronger password hashing with bcrypt or Argon2
- Replace direct password reset with tokenized email reset links
- Add richer AI session summaries with strengths and weak areas
- Add charts for progress over time
- Add automated tests for auth, interview routes, and AI response parsing
- Add better retry handling for invalid AI JSON responses
- Built a real AI-powered interview practice app from scratch
- Combined frontend, backend, auth, database, and AI workflows
- Used Groq to generate questions and evaluate answers dynamically
- Designed persistent interview sessions with resume and review flows
- Added speech input for a more realistic mock interview experience
- Built a project that is useful during job hunting and easy to demo in interviews
This project is currently for learning and portfolio use.
