Case study · Personal project · Built solo

JobBuddy

An AI interviewer you practise with on a live video call

JobBuddy puts you on a live video call with Meera, an AI HR interviewer who reacts while you talk. After the call, her scorecard shows what you said and what to say instead. Retry the question and see the improvement. I designed it and built it alone, directing AI agents that wrote the code and generated her motion.

Role
Sole owner, end to end
Time
Solo build, ~6 hours
Built with
Paper, Rive CLI, ElevenLabs Agents, Gemini, Claude Code, Next.js
Try it

The problem

You can tell an answer went badly. You can't tell what to fix, or how.

It's for anyone a week or two out from a real interview, who has been practising answers in their head or in a chat window.

Telling your story clearly under pressure is a skill, separate from doing the job well, and it improves with practice. I've seen how people prepare, and done it myself: polish answers with AI chat, then rehearse them alone. Nothing stops you mid ramble, and nothing tells you what to fix.

Getting better takes four steps: notice an answer went badly, name what was wrong, hear what a better one sounds like, and try it again for real. Alone, the first is a vague feeling and the rest are guesswork. JobBuddy covers each one. Meera reacts while you talk, the scorecard names the pattern, "you said" sits next to "try this", and you retry the question on a call.

I also wanted to see how far I could take a product alone, with AI writing the code.

JobBuddy app — home screen and scorecard

Why a call, not a chat. The hard part of an interview isn't knowing the answer. It's giving a good one on the spot, while someone watches you on a video call. In a chat you can pause, think and edit before you send. Rambling, fillers and answers with no result only show up when you speak. And a chat reacts only after you finish. A call can react while you talk: a nod when an answer lands, a look when you drift, a cut in when you run long.

My bet: practice works when it feels like the real thing and tells you exactly what to fix.

What it does

Every call ends with better answers than you walked in with.

JobBuddy is one loop: take a call, read the scorecard, retry your weakest answer. The new answer is scored next to the old one, so you know you improved instead of hoping you did.

Five screens: the setup sheet, the call, the scorecard, the retry result, and Home with the streak, each with a caption.

The call ends. Now you find out what to fix, and how.

You hang up, and within 20 seconds the scorecard is ready.

Not a list of flaws. One pattern to work on, with proof, like "2 of 3 answers ended before the result". Then your two or three weakest moments: what you said, next to how to say it better, built only from your own facts and judged against your level. A missing number stays a blank for you to fill. It's never invented.

The call's score stays as it was. A retry is scored on its own, next to it. So when it says "+2 on structure", you really got better.

The scorecard and the retry result, annotated. One pattern, with proof: 2 of 3 answers stopped before the outcome. What you said, next to try this. A blank for your number, never invented. Retry this answer leads to the retry result, where the biggest gain is shown by skill: +2, structure, 2 to 4.
Under the hood Judged against your level

Each answer is scored 1 to 5 on five skills: clarity (can it be followed on first listen), structure (situation, action, result, in that order), evidence (specifics, with a number or outcome), relevance (does it answer the question asked) and delivery (pace, filler, hedging). The bar moves with your level. Junior: what you did and learned. Mid: what you owned and the outcome. Senior and above: scope, decisions, influence and tradeoffs. A 3 is a passable answer at your level. Technical correctness is never graded.

Skill135
ClarityHard to follow what happenedFollowable with effortClear on first listen
StructureNo situation, action or resultTwo of the threeAll three, in order, result last
EvidenceNo specificsSome specifics, no numbersSpecific, with a number or concrete outcome
RelevanceAnswers a different questionMostly on the questionDirectly answers it, nothing extra
DeliveryHeavy filler, hedging or ramblingSome filler, or one long stretchSteady pace, little filler, no hedging

Designed for, not yet measured

Not launched, so nothing is measured yet. The first number I'd watch is how many calls reach the scorecard. Drop before it, and nothing else matters. Then how many people retry their weakest answer, because finishing shows effort and retrying shows they're getting better.

A streak counts daily practice. There is no XP, because XP rewards time spent, not getting better. You only need the streak for a short while, from the day you start preparing to the day of the interview. In that window, practising a little every day matters more than anything else. The streak keeps you doing it, so by the time the real one comes, you have said your answers out loud many times.

First change I'd make: the nudge to practise today lives in History. It belongs on Home, where it can pull someone back.

The riskiest question first

  1. Voice first. Could a voice agent run an interview, fire reactions and time lip sync? Tested in a bare call screen, so it was a call from day one.
  2. Then an orb. Was the call and scorecard loop worth having? A simple orb was enough to find out.
  3. Meera last. She was the most expensive part, and her expressions came from what the settled flows needed.

How Meera behaves

Meet Meera. She's a tough interviewer, and she's on your side.

Meera had to feel like a real interviewer, not a chatbot that waits for you to finish. That came down to rules about when she reacts, when she speaks, and what she never does.

Meera at four moments of a long answer: listening, glancing down at 75 seconds, checking her watch at 105, cutting in at 120. A timeline below.
  • Cutting in. The voice platform can't interrupt mid word, so the app watches the answer and cuts in at your next breath after 120 s. Nothing fires in the first 20 s, and she cuts in once per answer, at most.
  • Judging, not coaching. "So how did that turn out?" She asks for the result and steers you back once. Coaching waits for the scorecard, so the call stays real.
  • Silence. Early calls asked "Are you still there?" Now a pause means thinking. She says "Take your time", leans in, then repeats the question in fewer words.
  • Fair by design. She never asks about age, family, religion, health, nationality or salary history. A CV gap is asked about once, neutrally, and never flagged.
  • Warmth with limits. Never "great question". She looks impressed at most twice a call, and only for a clear result or a sharp insight.
Under the hood How Meera thinks
  • Two layers. The app runs the timed rules, because the voice platform can't interrupt mid word. Meera judges the rest at the end of each turn, like a story with no result.
  • Filler and hedge bursts. 6 or more fillers, or 3 or more hedges, in one answer raise a brow, once.
  • Her tools in the app. react fires one of her reactions. flag notes a moment for the scorecard and plays her writing mood. setPhase moves the call from opening to interview to done. nextQuestion moves "Question 2 of 3", and the app ignores it if she hasn't asked a new one.

How it was made: her personality is a system prompt I wrote with Claude. Her live reactions are app rules I specced and Claude Code built.

Built to be trusted

Practising for an interview is personal. The app treats it that way.

Nothing leaves your phone

No account, and calls are never recorded. Your CV, transcripts and scores stay on your phone.

System diagram: your phone holds the rig, live rules and local storage. Your voice goes to the voice agent; her voice, letter timing and tool calls come back. After the call, the transcript goes to the scorecard and the scorecard comes back.

01 · Failure states

Nothing gets stuck

Every way a call can go wrong has a planned way out.

The scorecard takes over 130 s
A clear retry, never a spinnerTry again after some time.
Meera forgets to hang up
The app hangs up for her3 s after her voice stops.
The time limit runs out
She's told to close60 s later, the app ends the call.
The connection drops
Reconnect, same questionSorry, we lost you. Where were we…
You hang up early
Saved as incomplete, with a way backWant to jump back in where we stopped?

02 · Cost

Call time is spent on the interview

Every minute on a call costs voice credits. So anything that can happen off the call does.

Under the hood What happens before, during and after the call
Before the callSetup
  • Role and level
  • Length: 5, 10 or 20 min
  • CV and job post
No voice credits
On the callOnly the interview
  • A short opening
  • Questions and follow ups
  • Her closing line
2 min left no new questionsTime up she closes+60 s the app hangs up
Voice credits
After the callScorecard
  • Built from the transcript
  • Saved on your phone
No voice credits

03 · Accessibility

Accessible by design

Motion follows your phone's settings. Meera stays expressive but stops moving around.

Contrast is a rule in the tokens, not a final check. The one primary action is pink with dark text, never white. White on pink measured 3.37:1 in my first direction, so the rule went into the system.

Under the hood What changes with reduced motion
Motion onReduced motion
Expressions and blinksOnOn
Breathing, bounce and liftOnOff
Body dip on arm posesOnOff
Ringing screenPulsing ringsA crossfade
Score gaugeCounts upShows the score at once

Rules made her act like an interviewer. She still had to feel like one.

Making her feel present

She had to feel like someone on the other end of a call.

How it was made: her concepts were designed in Paper. Her rig and every motion were generated as code with the Rive CLI from her vector parts. No keyframes were drawn by hand.

She felt flat, so I measured it

She looked lifeless while talking, and measuring showed why: only her mouth moved. So I redrew her as Concept v2, with long hair, a clipboard, arm poses and a talking loop.

Bar chart: idle 1.80%, talking on the first rig 2.0%, talking on Concept v2 5.92% of pixels changing per frame.
Meera writing on her clipboard, the pen moving behind the board.
Writing. When she notes something for the scorecard, her pen moves behind the clipboard, so you see your answer being noted.
Meera saying 'and how you approach design leaders'. Her mouth changes shape with each sound, and the mouth shape name updates under her face.
Speaking. One line from a real call, played with its real letter timing. Each sound picks one of nine mouth shapes. Rendered from the rig, so there's no sound.

21 states, one face

Seven moods she holds and 14 reactions she plays, all built from her 12 expressions. The rig is generated and compiled in the terminal, and every tile below is rendered from that file.

$ node rive/rig/make-rig.js && rive rive --publish=local
rive  published rive/meera.riv (93479 bytes, 2243ms, 0 errors, 0 warnings)
21 short loops rendered from the rig. Moods: idle, intake, listening, skeptical, writing, talking and thinking. Reactions: nod, smile, brow raise, glance down, one second, check watch, sit up, lean in, expectant, think, impressed, laugh, reassure and surprised.
Under the hood How the rig is built Meera smiling, with her seven face controls labelled: brows, upper lids, lower lids, blush, head tilt, pupils and mouth. The app sets values on InterviewVM: mood, viseme, mouthOpen, lipSync, reducedMotion and 14 triggers. The rig runs nine layers at once: mood, talking motion, reactions, posture, blink, eye darts, mouth, viseme, and breathing with hair follow through.
  • Expressions as controls. Brows, both lids, pupils, mouth, tilt and blush each move on their own, so every face is a set of numbers and the rig blends between them.
  • Generated, not drawn. A script turns her vector parts and a file of expression values into the whole rig. The Rive CLI compiles it.
  • One frame swaps. Eyes, mouths, visemes and arm poses cut on a single frame, so two half transparent parts never overlap.
  • Guards in the build. It refuses a rotation stored the long way round, and any part animated by two layers at once.

A call should ring

"Connecting…" felt like loading, not calling someone. Now it rings, and her picture grows into the video tile when she answers. She appears in 0.8 s, down from 2.9 s.

Three steps. 1, Ringing: her round picture with lavender rings, Ringing…, and End call. 2, She answers: her picture grows into the video tile in 300 ms. 3, On the call: the live rig takes over and she says hi.

Next: how I built her and the app, and how I checked the work.

How I built it alone with AI

How I checked the work.

Who did what Me, Claude and Claude Code

I wrote the PRD, made every product and design decision, designed the screens and the character, and tested every version on my phone. Claude Code wrote and tested the code. Claude helped me explore options and draft specs.

I reviewed every step: the spec before anything was built, the build once it came back, and the proof that it worked. Nothing counted as done on a report alone.

Build quality checks

3xmore movement while she talks. Measured, then tuned by eye.
15 → 2mouth freezes mid sentence, traced through call logs.
12expressions from one set of face controls.
16–20 sfor the scorecard. It used to hang.
The proof loop: I decide. Claude drafts the spec and I review it. The agents build and I review what changed. Proof comes back and I check it. Then I review it on my phone, in a real call. A failed review goes back to the spec.
Meera's warm smile, rendered from the Rive rig.The rig
The reference pose for the warm smile.The reference
The difference between the two, almost entirely grey.The difference
What proof looked like. Every state of the rig is rendered beside its reference. Grey means the pixels match. Across all 33 states, they differ by 0.09% at most.
Under the hood Everything that counted as proof
  • Contact sheets. Every state of the rig beside its reference pose, with differing pixels in red.
  • Frame captures at 60 fps. Every expression switch, so a one frame glitch can't hide.
  • Motion measurements. How much of her moves per frame, idle and talking.
  • Real call logs. When something broke on a call, the fix started from the log, not a guess.

Where my call overruled the AI

Three times, the AI's answer looked done and wasn't. What it proposed, and what I decided.

Before: a bun and a purple circle behind her head.After: long warm brown hair with a soft glow.

A profile picture, not a person

The AIA bun and a purple circle, to stand out on the dark screen. The bun bobbed with every nod.

My callLong warm brown hair with a soft glow.

2 more The other two calls

...

Tell me about a time a stakeholder pushed back…

The "..." on the question card

The AIBlamed a timing race.

My callWait for the call log. I had talked over her, and her cut off turn came through as "...". Empty lines are dropped now.

Before: a notepad low at her left and the pen up at her shoulder.After: she writes on a clipboard tilted toward her, the pen behind the board.

Writing that looked staged

The AIThe pen shook in the air, then sat on the page.

My callA clipboard tilted toward her, with the pen working behind the board.

Fixes became rules. When a bug had a clear cause, the build learned to refuse it. By the end, 120+ unit tests and 3 end to end suites all passed.

What real calls caught that tests didn't

Every test passed, and four bugs still showed up only on real calls. Each fix started from the cause in the call log, not the symptom.

The same spoken line on the real rig, run through the old and the new lip sync rules. Before: her mouth sticks on one shape for most of a word. After: it keeps changing with the letters. Played at three quarter speed.

Her mouth stopped while you could still hear her

WhyShort sounds were merged away, so whole words collapsed into one shape.

The fixSounds grouped so no word collapses, a cap on how long one shape holds, and a guard for stalled timing. The freezes left are both real pauses in her speech.

Under the hood How the lip sync works Lip sync pipeline in six steps, with the three fixes highlighted, and the nine visemes: rest, closed, teeth, open, wide, round, pucker, fv and lth.
  • Letter timing. Her voice arrives in chunks, each with the timing of every letter as it starts to play.
  • Letters to mouth shapes. Simple spelling rules pick one of nine visemes: p, b and m close the lips, o rounds them, e and i widen them.
  • Readable timing. Quick letters are grouped so each shape shows for at least 60 ms, and each shape lands about 40 ms early, when the sound reaches you.
  • A fallback. If letter timing goes missing, or one shape would hold past 250 ms, her mouth follows her voice volume instead.
3 more The other three bugs
BeforeHer smile closing, before: two mouths fade through each other in grey.AfterAfter: the mouth cuts cleanly in one frame.

Grey flashes when her face changed

WhyTwo half transparent parts overlapped.

The fixEvery swap cuts in one frame.

What you read

[calm] Tell me about a time…

What you read now

Tell me about a time…

Stage directions in the question you were reading

WhyThe voice model writes tone cues like "[calm]" into its text, and the app showed them as they came.

The fixThe app strips every cue before you see it, and expressive mode is off.

Before: as she looks up from her clipboard, her right upper lid spins a full turn. After: the same move, and the lid settles cleanly. Played at half speed.

An eyelid spun as she looked up from her clipboard

WhyAn angle was saved the long way round.

The fixThe build now refuses rotations like that.

What I cut

Most of the work was deciding what not to ship.

Three character directions: the blob, the stylised human (chosen) and the hybrid.
Cut the blob and the hybrid, because an interviewer you can read is easier to practise with.
Concept v2, what shipped: six of her 12 expressions. Listening, warm smile, interested, skeptical, thinking and laughing.
Cut Concept v1, because she barely moved while talking. v2 was redrawn for the video tile.
A raised pen next to a raised finger, and three other cuts: setup by voice, lip sync from volume, and a timed closing line.
Cut the raised pen, because it read as writing, not as "one second". A raised finger says it at a glance.

Left out of v1, on purpose

  • Accounts and cloud storage. Practice is personal, so it all stays on the phone.
  • Grading technical correctness. Meera judges how you answer, not whether you're right about your field. An AI can't judge every field reliably, and one wrong verdict would break trust in the whole scorecard.
  • Camera analysis. A real privacy cost, for little gain over voice.
  • More interviewers. One done well beats several done thinly.
  • Sharing and payments. Not until the core loop is proven.

What I learned

What I'd take into the next product.

The hardest design work was behaviour, not screens.

When she cuts in. How long she waits in a silence. That she says "take your time", never "are you still there?". What she never asks about. None of that shows up in a mockup, and all of it decides whether the call feels real.

Numbers find the problem. Eyes judge the fix.

I couldn't say why she felt flat until I measured her. While talking, only her mouth moved. That told me where she was dead, not how lively to make her, because more motion isn't more life. Past a point it reads as jitter. The right amount was a judgement I made by watching her, not a number I hit.

The AI sounds just as sure when it's wrong.

The code came fast, and so did confident answers. Some were right, some weren't, and they read the same. My job moved to knowing what to check before anything shipped.

If I took it further.

I'd test it with other people and measure how many calls reach the scorecard.