Inspiration

Most study apps make it easy to feel productive without actually remembering anything. Re-reading notes feels like learning, but research on retrieval practice says the real gains come from pulling information out of your head, not putting it back in. I wanted a study session that forces that retrieval, keeps you honest about what you actually know, and is fun enough that you come back for the next session. I use the pomodoro learning style for studying, and I wanted to turn it into a web app!

So I turned a study session into a fantasy campaign. Your notes become the world, each pomodoro is a chapter, and anything you get wrong comes back to haunt you as a villain.

What it does

Quest-Mode Study turns your notes into a story-driven study session:

  1. Notes in. Paste notes, upload a PDF, or just type a topic.
  2. A campaign appears. Gemini builds a short fantasy campaign with one chapter per pomodoro, based on how long you want to study.
  3. Focus. Each chapter runs a pomodoro timer with optional brown noise. The screen shows only the chapter's story beat and the concepts to master. There are no summaries, so the review that follows is real retrieval practice.
  4. Break choice. When the timer ends, choose a fun break or a review break.
  5. Review break, two modes:
    • Quiz: a Guide character asks three questions from your notes and reacts to each answer.
    • Teach-back: a confused apprentice confidently states a wrong claim taken from your notes, and you have to correct it. Explaining something to someone else is one of the best ways to learn it.
  6. Results cited to your notes. Each answer is graded correct, partial, missed, or wrong, next to the exact quote from your notes that supports the right answer.
  7. Villains. Anything you missed or got wrong comes back as a villain in the next chapter, so your weak spots keep returning until you've dealt with them.

A demo mode shrinks pomodoros to 20 seconds and breaks to 15 seconds so the whole loop can be shown live.

  • An eval that measures the citation pass rate across several sets of notes.

How I built it

  • Frontend: React, TypeScript, Vite and Tailwind. Brown noise is generated in the browser with the Web Audio API.
  • Backend: Python and Flask, with all API keys kept server-side.
  • Database: Tiger Data (PostgreSQL) stores campaigns, chapters, villains and every graded attempt. Reloading the page reads from the database and never calls the model again.
  • AI: Google Gemini with structured JSON output for three jobs: generating the campaign, playing the characters during review, and grading the transcript.
  • Grounding: a plain-Python citation check is the core of the app. No quote reaches the database or the screen unless it appears word for word in the student's notes (after normalizing case, whitespace and curly quotes). Generated concepts whose quotes fail the check are dropped, and grading results with unverified quotes are flagged and the quote is hidden.
  • Design for voice: review conversations are recorded as a plain transcript, and grading only ever sees that transcript. That means a voice review (through ElevenLabs) can be added without touching the grader. (Still to-do).
  • Process: I used test-driven development throughout, with Gemini faked in tests so they never spend API quota.

Challenges I ran into

  • Keeping the model honest. LLMs love to paraphrase, and a paraphrased "quote" is worse than no quote. I solved it with a deterministic check instead of trusting the model, and the app regenerates a chapter if too much of it fails the check.
  • Grading that silently returned nothing. In my first real test, the results screen said no concepts were covered. Debugging the raw model output showed Gemini returning "Concept: explanation" instead of the concept's name, so every result was discarded. I fixed it by constraining the JSON schema with an enum of valid names.
  • Questions that didn't match concepts. The citation check could drop a concept but keep a quiz question about it, so a wrong answer never became a villain. I changed quiz grading to grade per question, citing each question's own verified quote.
  • The planted wrong claim. In teach-back, the apprentice must repeat only the planted claim from the campaign and never invent new misinformation, or the student could end up learning something false. The claim and its correction come from stored data, and the model only reacts.
  • Environment issues. HTTPS interception from antivirus software broke API calls, and my Node version forced me to pin an older Vite.

Accomplishments that I'm proud of

  • The full loop works end to end: notes, campaign, focus timer, review, cited results, and villains in the next chapter.
  • Every quote shown to the student is verified against their own notes by code, not by the model.
  • A clean separation between how a review happens (text now, voice later) and how it's graded.

What I learned

  • Retrieval practice and teaching others (the "protégé effect") are strong study techniques, and they're easy to build into a game loop.
  • With LLMs, the most reliable fixes are structural (schemas, enums, deterministic checks), not longer prompts.
  • Logging and inspecting raw model output is the fastest way to find out why an AI feature "just doesn't work."

What's next

  • Voice review with an ElevenLabs agent, so you can talk to the apprentice. The architecture is ready, and it's waiting on API access.
  • A progress chart across sessions using the time-series attempts data.
Share this project:

Updates

Submission history