recruitvoca_ew5VqP5O.mp4
RecruitVoca is a real-time, WebRTC-powered AI voice recruitment platform designed to conduct interactive, human-centric technical interviews. Unlike standard text-based assessments, it termination-handles WebRTC peer connections on our own server, utilizing a LiveKit SFU (Selective Forwarding Unit) and a Python Agent worker to orchestrate an STT ➔ LLM ➔ TTS voice loop using high-performance, free-tier services.
Browser (livekit-client = WebRTC) ──join room──► LiveKit Server (Docker SFU)
▲ mic track / ◄ agent audio track ▲ media ▼
│ Python LiveKit Agent Worker
Next.js App (TypeScript) • Silero VAD (voice activity detection)
• POST /pre-interview • Groq Whisper (STT)
• GET /livekit-token • Mistral Large (LLM)
• POST /finish (Mistral evaluation) • Groq Orpheus (TTS)
• GET /result/[id] │
▼
Neon Postgres ◄────── Writes Transcript / Messages
Below is the workflow sequence diagram detailing the step-by-step interview process from candidate login to automated scoring.
The hero page introduces RecruitVoca with a bento-grid feature showcase, including Smart Voice Agents, Intent Analysis, GitHub-Powered Context, and Full Transcript Replay.
Candidates enter their GitHub profile URL. The AI scrapes their public repos and uses them to craft personalized, context-aware interview questions.
The real-time interview room powered by LiveKit WebRTC. The animated shader-based aura visualizer reacts to the AI agent's speaking state. The right panel shows a live transcript of the conversation.
After the interview ends, Mistral AI evaluates the full transcript. A pulsing loading screen is shown while the scoring pipeline runs.
The completed results page shows the overall score, three category breakdowns (Technical Depth, Communication, Problem Solving), qualitative feedback, and the full conversation transcript.
The history page lists all past interviews with status badges (Completed / In Progress / Not Started), score rings, and quick links to view results or resume an ongoing session.
- Frontend & API: Next.js 16 (App Router, Tailwind CSS, TypeScript)
- Authentication: NextAuth.js (Google OAuth)
- Database: Neon Serverless Postgres + Drizzle ORM
- WebRTC Server: LiveKit (Dockerized OSS SFU)
- Real-time Pipeline: Python
livekit-agents- VAD / Turn Detection: Silero VAD
- STT: Groq (
whisper-large-v3-turbo) - LLM: Mistral AI (
mistral-large-latest) - TTS: Groq (
canopylabs/orpheus-v1-english, voiceautumn)
├── agent/ # Python LiveKit agent worker (STT -> LLM -> TTS pipeline)
│ ├── pyproject.toml # Dependency management via uv
│ ├── worker.py # Core agent listener and session loop
│ └── README.md # Agent-specific startup instructions
├── app/ # Next.js App Router directory
│ ├── (talent)/ # Candidate interview, onboarding & results pages
│ ├── api/ # LiveKit JWT generation, pre-interview setup, and finishing hooks
│ ├── sign-in/ # Custom authentication pages
│ └── globals.css # Global tailwind configurations & color tokens
├── components/ # Reusable UI component library (navbar, footer, button, icons)
├── lib/ # Shared TypeScript logic and DB integrations
│ ├── ai/ # Mistral client & system interviewer prompts
│ ├── auth/ # Middleware authentication helpers
│ ├── db/ # Drizzle schemas, index, and relations
│ ├── scraper/ # GitHub profile scaper for tailoring interview questions
│ ├── livekit.ts # Room creation & token signing SDK wrapper
│ └── utils.ts # Classnames merging and tailwind utilities
├── docker-compose.yml # LiveKit SFU orchestration file
├── livekit.yaml # LiveKit development environment configuration
└── proxy.ts # Next.js middleware file (auth-guarded routes)
Before running the application, make sure you have the following installed:
- Docker & Docker Compose
- Bun (or Node.js 18+)
- Python 3.10+ with
uv(recommended Python package manager)
Create a .env.local file in the root directory:
# Google OAuth (NextAuth)
AUTH_GOOGLE_ID=your_google_client_id
AUTH_GOOGLE_SECRET=your_google_client_secret
AUTH_SECRET=your_random_auth_secret
AUTH_URL=http://localhost:3000
# LiveKit SFU (defaults for docker-compose)
LIVEKIT_URL=ws://localhost:7880
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=devsecret___min32chars
NEXT_PUBLIC_LIVEKIT_URL=ws://localhost:7880
# Neon Database
DATABASE_URL=postgres://user:password@host/dbname?sslmode=require
# External APIs
GROQ_API_KEY=gsk_...
MISTRAL_API_KEY=...
GITHUB_TOKEN=ghp_... # Optional, to prevent GitHub API rate-limitingOrchestrate the local WebRTC media server via Docker:
bun run livekit
# or: docker compose upEnsure the Neon Database schema is updated:
bun run db:pushInstall Python dependencies and start the agent worker which listens for incoming WebRTC room events:
# From the root directory:
bun run agent
# Or manually:
# cd agent && uv sync && uv run python worker.py devStart the client application in a separate terminal:
bun run devOpen http://localhost:3000 to view the application.
The following scripts are defined in package.json:
npm run dev- Launch Next.js development servernpm run build- Build the production application bundlenpm run lint- Run ESLint rulesnpm run livekit- Launch the Docker container running the LiveKit servernpm run db:push- Synchronize Drizzle schema updates to your DBnpm run db:studio- Inspect tables using Drizzle Studio GUInpm run agent- Initialize the python-agent voice worker usinguv







