Inspiration

Studying from a topic or a document and then testing yourself on it are usually two separate steps — open a book, then go find or write a quiz somewhere else. We wanted to collapse that into one step: drop in a topic, or your own notes, and get a quiz back in seconds.

What it does

QuizAI generates multiple-choice quizzes two ways:

  • By topic — type anything ("Python Programming," "World History") and pick a difficulty and question count.
  • From a document — upload a .txt/.md/.csv/.html/.json file and the AI reads it and writes questions based on its actual content.

You then take the quiz with a progress bar and a question jump-pad, submit it, and get a scored results page — a circular progress ring, a breakdown of correct/wrong/ skipped, and a per-question review showing your answer next to the correct one. Results are saved to MongoDB so they persist across sessions.

How we built it

  • Frontend: React + Vite, styled with Tailwind CSS, with a small Context API store to share quiz state (current quiz, answers, results) across pages without prop-drilling. Dark mode is a manual toggle (not just OS preference) persisted in localStorage.
  • Backend: Express + MongoDB (Mongoose), with two Mongoose models — Quiz and Result — and REST endpoints for generating, fetching, and scoring quizzes.
  • AI: Google's Gemini API does the actual question generation. We prompt it for strict JSON output (responseMimeType: "application/json") and validate every question server-side — exactly one correct answer must be present among the options — before anything touches the database, so a malformed AI response never corrupts a saved quiz.

Challenges we ran into

  • Getting reliable structured output from the model. Free-text "give me a quiz" prompts occasionally drifted format. Forcing JSON mode and writing a validation layer that filters out any malformed question (rather than trusting the AI blindly) fixed this.
  • MongoDB Atlas IP whitelisting. Classic "works on my machine" trap — the backend would silently die on connectDB() failure, which made early debugging confusing because every route looked broken, not just the database-backed ones.
  • Vite environment variables are build-time, not runtime. Changing VITE_API_URL after a production build requires a full rebuild — restarting the server alone does nothing, since there's no server, just static files.
  • CORS between separately deployed frontend/backend. CLIENT_URL has to exactly match the production frontend's origin, not localhost, or every API call gets silently blocked by the browser.

What's next

Question types beyond multiple-choice (true/false, fill-in-the-blank), a leaderboard for shared quizzes, exporting a quiz to PDF, and richer document support (PDF/DOCX uploads instead of plain text).

Built With

Share this project:

Updates

Submission history