A small research prototype that runs a 5–10 minute conversational voice interview with real language learners to discover the problems people face learning German or Italian.
The interview is driven by an AI interviewer (Gemini, with Groq as an automatic fallback), spoken and answered by voice, with a text fallback always available. Completed interviews produce a structured research summary you can review in a protected admin dashboard.
- Next.js 16 (App Router) + TypeScript + Tailwind CSS v4
- Supabase (PostgreSQL) — interviews & transcripts
- Gemini API (primary) — interviewer LLM, speech-to-text, text-to-speech
- Groq API (automatic fallback) — keeps the interview running if Gemini fails
- Deploy target: Vercel
-
Install dependencies:
npm install
-
Create your
.env.localfrom the template:cp .env.local.example .env.local
Set the values:
Variable Where to get it GEMINI_API_KEYGoogle AI Studio (aistudio.google.com) GROQ_API_KEYconsole.groq.com (optional, but recommended for fallback) SUPABASE_URLSupabase project → Settings → API SUPABASE_SERVICE_ROLE_KEYSupabase project → Settings → API (service_role, server-only) ADMIN_PASSWORDAnything you choose; gates /admin -
Set up the database. Run the SQL in
supabase/schema.sqlin your Supabase SQL editor. -
Run locally:
npm run dev
Open http://localhost:3000.
/— landing page. Add?lang=deor?lang=itfor the language variant (defaults to German). No account needed for participants./interview— the voice interview itself./admin— password-protected research dashboard (interviews, transcripts, AI summaries)./api/...— server routes; see below.
- Participant consents and starts the interview.
- The AI interviewer asks one question at a time (spoken + on screen).
- The participant answers by holding/pressing the microphone (or typing).
- Audio is transcribed server-side, then:
- the transcript is saved,
- the interviewer model decides the next question (or a follow-up),
- the next question is spoken via TTS.
- Repeats until the interviewer ends or ~10 minutes elapse, then a research summary is generated from the full transcript (never from the last answer alone) and saved.
Provider fallback: every AI call (LLM, STT, TTS) tries Gemini first, and on failure retries Groq automatically. The provider that served the call is stored on the message/interview so it is visible in the admin dashboard.
| Route | Purpose |
|---|---|
POST /api/interview |
Create an interview record (in_progress) |
POST /api/interview/ask |
Participant answer in → interviewer's next question out |
POST /api/interview/finish |
Generate + save the research summary, mark completed |
POST /api/stt |
Transcribe an audio blob (multipart) |
POST /api/tts |
Synthesize speech from text → audio |
POST /api/admin/login |
Issue the /admin session cookie |
GET /api/admin/interviews |
Snow interviews + stats (admin only) |
GET /api/admin/interviews/:id |
Interview + transcript + summary (admin only) |
Everything tunable lives in src/lib/:
constants.ts— model IDs for all providers, voices, timeouts, question caps.languages.ts— the German/Italian variants (landing copy, target-language name).interviewer.ts/summary.ts— interviewer & summary prompts.
Push the repo to GitHub and import it into Vercel, then set the same environment variables
(GEMINI_API_KEY, GROQ_API_KEY, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY,
ADMIN_PASSWORD) in the Vercel project settings.