TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
Spoken mock interviews for government, campus and private-sector roles, with follow-up questions and feedback based on what you actually said.
EducationTypeScript · JavaScriptGitHub @PrachiYadav-16OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Live site:https://ai-voice-interviewer-lyart.vercel.app
Spoken mock interviews for government and private-sector roles. You talk with an AI interviewer that asks one question at a time, waits while you think and follows up on what you actually said. Afterwards you get rubric-based feedback on each answer.
| Part | Where |
|---|---|
| Interview catalog (tracks, roles, formats, styles) | lib/interview/catalog.ts — add a role or field by adding data here |
| Interviewer instructions and Vapi assistant config | lib/interview/prompt.ts |
| Live call state machine (pure, unit-tested) | lib/interview/session.ts |
| Vapi SDK wiring, mic checks, pause/mute/skip/end | lib/hooks/useVapiInterview.ts |
| Rubrics and the 1–5 scale | lib/interview/rubrics.ts |
| Overall score calculation | lib/interview/scoring.ts |
| Device accounts (PBKDF2-hashed passwords) | lib/auth.ts |
| Browser storage for profiles, sessions and reports | lib/storage.ts |
| Server routes | app/api/parse-document, app/api/plan, app/api/evaluate, app/api/status |
Voice. The browser runs the call with the Vapi Web SDK (@vapi-ai/web 2.7) using a transient assistant built per interview. Turn-taking uses Vapi's smart endpointing for English and transcription endpointing for Hindi, requires two spoken words before the interviewer stops talking, and nudges once after 25 seconds of silence. Pause mutes your mic and the interviewer; skip, repeat and wrap-up send control messages. The call's hard limit is set from the interview length (Vapi's default is 10 minutes).
Feedback. After the call, the transcript is sent to /api/evaluate, which asks an OpenAI-compatible model to rate each answer 1–5 against the rubric for that interview type, with evidence from your words. IntervU computes the overall score itself as the average rating mapped to 0–100, and shows no overall score when fewer than three answers were rated. Feedback covers the words only: tone, pace, confidence and body language are not measured.
Data. With Supabase configured, accounts use Supabase Auth (email confirmation, email password reset) and interviews are stored in two tables protected by Row Level Security, so each user can only read their own rows (supabase/schema.sql). The app is local-first: pages read from a browser cache, and lib/cloud.ts mirrors every change to the database with debounced, retried writes, then fills the cache on sign-in. Without Supabase, everything stays in each browser's localStorage. See /privacy in the app.
Requirements: Node.js 20.9 or later (tested on 22), npm.
git clone https://github.com/PrachiYadav-16/AI-voice-interviewer.git
cd AI-voice-interviewer
npm ci
cp .env.example .env.local # then fill in the values below
npm run dev # http://localhost:3000
| Variable | Needed for | Where to get it |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Accounts and database | Supabase → Project Settings → API Keys (or the project home page) |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Accounts and database | Same page → Publishable key (sb_publishable_...). Never use the secret / service_role key. |
NEXT_PUBLIC_VAPI_PUBLIC_KEY | Live interviews | Vapi dashboard → API Keys → Public key. Restrict it to your domains. Never use the private key here. |
LLM_API_KEY | Feedback reports, personalised question plans | An OpenAI API key, or a key for any OpenAI-compatible provider |
LLM_BASE_URL | Optional | Defaults to https://api.openai.com/v1 |
LLM_MODEL | Optional | Defaults to gpt-4.1-mini; must support JSON response format |
NEXT_PUBLIC_VAPI_LLM_MODEL | Optional | Interviewer model, default gpt-4.1 |
NEXT_PUBLIC_VAPI_VOICE_ID | Optional | ElevenLabs voice ID, default 21m00Tcm4TlvDq8ikWAM |
Without NEXT_PUBLIC_VAPI_PUBLIC_KEY the app runs but interviews can't start (the UI says so). Without LLM_API_KEY interviews run and transcripts are saved, but reports and plans show a "not configured" message. Vapi usage is billed to the Vapi account, including the speech, model and voice providers it calls.
Microphone access needs HTTPS in production (localhost is allowed in development).
supabase/schema.sql, and click Run. This creates the profiles and sessions tables, Row Level Security policies, and the delete_my_account function.http://localhost:3000 while developing) and add http://localhost:3000/** plus your deployed domain with /** to Redirect URLs. Confirmation and password-reset emails link back here..env.local and restart npm run dev.Supabase's built-in email sender is rate-limited and meant for testing. For real users, add your own SMTP provider under Authentication → Emails → SMTP Settings.
With Supabase set, the AI routes (/api/evaluate, /api/plan, /api/parse-document) also require a signed-in user, which stops other people from spending your AI credits.
npm run dev # development server
npm run build # production build
npm start # serve the production build
npm test # unit and API tests (Vitest)
npm run typecheck # TypeScript
npm run lint # ESLint, zero warnings allowed
npm run check # all three
Browser smoke test (optional): npm i -D playwright && npx playwright install chromium, start the app, then node tests/e2e/smoke.mjs. It uses a fake microphone and does not test a real conversation.
Vercel works out of the box:
/api/evaluate may take up to 90 seconds, so use a plan whose function timeout allows that.Any host that runs next start on Node 20.9+ also works.
.doc files and scanned PDFs can't be read; paste the text instead.npm audit reports a moderate advisory in sprintf-js, reached only through mammoth's command-line argument parser, which IntervU never calls. The suggested fix downgrades mammoth to a 2015 release, so it hasn't been applied.LLM_API_KEY) are only read on the server. /api/status exposes booleans, never values.app/page.tsx. It has been removed from the code but remains in git history, so rotate that key in the Vapi dashboard.