Interview Cracker — building an AI interviewer

I Build It With AI Championship · Bengaluru · 5 September 2026

3rd place among 15+ teams · Competed solo against teams of up to three

Product

Interview Cracker

Role

Solo Product Owner

The brief

The problem statement was revealed at 9:50 AM. Four hours to build, deploy publicly, and defend it in a five-minute pitch.

Freshers and job switchers prepare by reading interview questions instead of answering them out loud. So the first time they speak under pressure is in the real interview. Every role asks for something different, and the job description already says what.

Build a platform where someone pastes a JD and then goes through a real interview round with an interviewer on screen.

The organisers named four things they would look for: questions that visibly come from the pasted JD; an interviewer you can see and hear who asks and reacts; one question at a time with no skipping, no going back, no preview; and a result at the end that says what was weak and why, based on what the candidate actually said — explicitly not a score out of ten.

That brief is unusually prescriptive. The shape of the product was decided for everyone in the room. Fifteen teams were going to build the same skeleton. Whatever differentiation existed had to come from the insight and the execution, not the feature list.

The user, and the moment

It’s 11 PM. Priya has an interview in three days. She has the JD open in one tab and a list of top-50 interview questions in the other. She has read forty of them and nodded along to every answer. She has not said a single one out loud.

Three days later, the first question is about something specific in that JD. She knows the answer in her head. It comes out as ninety seconds of vague rambling with no example. The rejection arrives with no reason. She goes back to reading question lists.

The underlying problem is that the feedback loop is broken at both ends. Preparation is silent and generic, so she never hears herself. Rejection carries no explanation, so nobody tells her what was weak. Reading is not practising, and a generic question list ignores the one document that says exactly what this job wants.

The decision that shaped everything else

With roughly two and a half hours of real build time, I could build one thing well or four things badly.

I decided the product was the debrief. Not the avatar, not the voice, not the question generation — those were table stakes every team would attempt. The differentiating bet was the last screen: feedback that quotes the candidate’s own sentence back and names the specific failure, because that is where the brief was most explicit and where laziness would be most visible.

Everything else was scoped to serve that screen.

What I cut, and why:

  • Video avatars. The brief asked for an interviewer who reacts, not a face that renders. Video generation adds a third API, several seconds of latency per line, and per-second billing — all on the one moment that must not stall on stage. An illustrated SVG with three states plus browser speech satisfies “see and hear” at zero integration risk.
  • A database. Nothing in the demo needed to survive a refresh. Persistence would have cost schema work and access-policy debugging for zero visible value.
  • Authentication. A login wall in front of a demo was disallowed, and auth is a classic time sink.
  • Local model deployment. Open-weights models earned extra credit, and I used one — but hosted. A model running on my laptop cannot serve a public URL on mobile data, which was a submission requirement. I chose a working public demo over the extra marks and said so.

Every one of these is logged in a public DECISIONS.md with the trade-off named. That file became my Q&A preparation.

How the AI was designed

Three calls, each with a purpose-built system prompt and a strict JSON contract.

1. Questions. Reads the JD, returns five questions plus an interviewer persona — a name, title and manner inferred from the company’s tone. Each question carries the verbatim JD phrase it came from, rendered on screen in red. That label is the difference between claiming the questions are role-specific and proving it. Paste a product JD and you meet Arjun Mehta, Senior Product Lead; paste a frontend JD and you meet Maya Patel, Senior Frontend Lead.

2. Reaction. After every answer, the model receives the JD, the entire conversation so far, and the current answer. Sending the full history each turn costs a few hundred tokens and buys something a single-turn design cannot: the interviewer notices when you contradict yourself, revise a claim, or dodge. It removed the need for a separate follow-up engine.

This call also returns an advance boolean. The model decides whether to move on or stay. If the candidate says “I didn’t understand the question,” the interviewer rephrases and waits on the same question. If the candidate declines — “I don’t know, sorry” — it responds with grace and moves on. A forced advance on the second attempt prevents an infinite loop.

That mechanism came from testing. My first version advanced on every input, and it felt like a form that talks. The second version stayed when someone was lost but responded to “I don’t know” as if they’d misunderstood, which felt worse — a bot pretending to be kind. Passing the attempt count into the prompt and distinguishing confused from declining fixed it.

3. Debrief. Over the full transcript: for each answer, the JD requirement it tested, a verbatim quote from the candidate, a named failure — no example given, example with no outcome, vague ownership, missed the requirement — and a rewrite built only from facts the candidate themselves supplied. The prompt forbids inventing achievements. If an answer was too thin to quote, it says so rather than fabricating one.

Why a model and not templates: a template can swap a job title into a fixed question list, which is exactly the failure the brief warned against. It cannot read a JD and ask about that company’s roadmap by name, and it cannot quote your own sentence back and tell you why it was weak.

Designing for the failure case

Every AI call sits behind a never-fail path: invalid JSON triggers one retry with a stricter instruction, a hung request is killed at 25 seconds, and anything still failing returns a pre-written response marked as a fallback — with a visible amber badge reading “Demo response — live AI unavailable.”

This was not defensive over-engineering. It fired twice on the day.

12:25 PM. Question generation returned fallback on the live URL. The model ID I had chosen had been retired from the provider’s catalog that week — a 404. I checked the live model list, switched to openai/gpt-oss-120b, one line changed.

12:40 PM. The interviewer’s reaction was identical every time: the fallback string. The cause was subtler — the model spends tokens reasoning before it writes an answer, and my 100-token cap on that call was entirely consumed before any content was generated. Empty content, failed parse, fallback fired. Raising the cap and setting reasoning effort to low resolved it.

In both cases the app kept working for the user while I diagnosed the failure. The reliability design is why two live failures cost me minutes instead of the demo.

The related decision: I built the entire flow with hardcoded questions and a hardcoded debrief first, published it, and then swapped in live calls one at a time. That guaranteed a deployed working product early — and produced the fallback content as a by-product rather than an afterthought.

 

Where it fell short

The organisers released detailed test cases an hour before pitching, after the build was already frozen. I scored my own product against them line by line. Three gaps came out of that, and none of them could be fixed — the build was locked.

No probing follow-ups. The interviewer reacts to what you said, but doesn’t push back. Their test case is explicit: a candidate says “I think I’m quite good at collaboration,” and a real interviewer asks for a specific example. Mine acknowledges and moves on. This is the most important gap, and it’s close — the stay-on-question mechanism already exists; extending it from confused to vague is a prompt change.

Questions don’t adapt to a stated gap. If a candidate says they’ve never used Kubernetes, the interviewer notes it and the debrief flags it against the JD — but the remaining questions were generated at the start and don’t regenerate around what he can actually show. I pre-generated deliberately: one call at the start means the round cannot stall mid-interview. That was the right call for a live demo and the wrong one for a real user.

No resume upload. JD only. I prioritised the interview feeling real over a second input.

I also noticed, and didn’t fix, that two questions occasionally cite the same JD line. I found it shortly before submission and chose not to touch a working generation call.

What I'd measure

No users, no data — four hours. If this ran for real, the instrumentation I’d start with:

  • Completion rate — how many people who paste a JD finish all five questions. The likeliest drop-off is question one, where the pressure is real for the first time.
  • Voice vs typed split — the entire premise is answering out loud. If most people type, the product isn’t solving the problem it claims to.
  • Second-attempt rate — the honest signal of whether the debrief was useful. Someone who comes back to try again found it worth acting on.
  • Debrief-to-change — do the answers in a second attempt actually address the priorities the first debrief named?

What this was worth

Third place among 15+ teams, competing solo against teams of up to three. The judged parameters were usefulness, creativity, craft, and how well you defend your decisions. The Q&A ran to the stack — the model, the edge cases, the debrief, the usefulness — and having written the decisions down while building meant answering those took no thinking.

Three things I'd take into any product role from this:

Reliability is a product decision, not an engineering afterthought. The fallback path was the reason two live failures were invisible to users.

Honesty about gaps is a positioning strategy. Knowing where you fall short is worth more than hiding it. The test cases arrived after the build was frozen and gave me a precise map of what a real version of this needs — which is why the gaps are written up here rather than quietly left out.

And the thing worth building is usually the last screen, not the first. Everyone was going to build a JD parser and an avatar. The debrief was where the user’s actual problem lived.


Built solo in four hours with Lovable, Claude, an open-weights model served via Groq, and the browser’s own speech APIs. No database, no authentication, nothing persists. The face is illustrated, not generated video. The README states exactly what is real and what is not.