AI-Powered Quiz Generator
Build a production-quality tool that takes any learning material (text, PDF, or URL) and generates pedagogically-sound quizzes using LLM APIs. This is your second portfolio piece — and the one that will make hiring managers say "tell me more."
Weekly Roadmap
A structured path from understanding AI-based assessment design to shipping a complete quiz generator application.
AI Assessment Design & Pedagogy
Learning Objectives
- Understand Bloom's Taxonomy and how it maps to question types
- Learn the difference between recall, comprehension, application, and analysis questions
- Study how effective educational assessments are designed
- Explore how LLMs can generate questions at each cognitive level
- Identify common pitfalls in AI-generated questions (ambiguity, bias, difficulty)
Activities
- ▸Workshop: Map question types to Bloom's levels with real examples
- ▸Exercise: Write prompt templates for each cognitive level
- ▸Discussion: When should AI generate assessments vs. teachers?
- ▸Reading: Research papers on automated question generation
Prompt Engineering for Quiz Generation
Learning Objectives
- Craft system prompts that produce well-structured quiz questions
- Use few-shot prompting to control output format (JSON schema)
- Implement difficulty calibration through prompt parameters
- Handle edge cases: too-easy, too-hard, ambiguous, or biased outputs
- Build a prompt template library for different question formats
Activities
- ▸Lab: Build and iterate on quiz generation prompts in a Jupyter notebook
- ▸Exercise: Create MCQ, true/false, short-answer, and essay prompts
- ▸Pair work: Test each other's prompts and find failure modes
- ▸Mini-project: Build a prompt evaluation framework
Building the Backend API
Learning Objectives
- Design a REST API for the quiz generator (endpoints, schemas)
- Build Next.js API routes that accept content and return quizzes
- Implement input processing (text extraction, chunking for long content)
- Add request validation and error handling
- Store generated quizzes in PostgreSQL
Activities
- ▸Workshop: Design the API schema together as a class
- ▸Lab: Implement /api/generate-quiz endpoint step by step
- ▸Exercise: Add support for different content input types
- ▸Testing: Write integration tests for your API routes
Building the Frontend UI
Learning Objectives
- Design a user-friendly quiz generation interface
- Build an interactive quiz-taking experience with scoring
- Implement a results dashboard with analytics
- Add export functionality (PDF, share link)
- Polish the UI with animations and loading states
Activities
- ▸Workshop: Wireframe the quiz generator UX flow together
- ▸Lab: Build the content input form with drag-and-drop support
- ▸Exercise: Create the interactive quiz-taking component
- ▸Polish: Add Tailwind animations and micro-interactions
Integration, Testing & Demo
Learning Objectives
- Connect frontend to backend for end-to-end quiz flow
- Deploy the complete application to Vercel
- Write a comprehensive README with architecture diagram
- Record a 3-minute demo video for your portfolio
- Conduct peer code reviews and gather feedback
Activities
- ▸Final integration sprint: Connect all pieces together
- ▸QA session: Test with real educational content from various subjects
- ▸Demo prep: Practice your 3-minute project presentation
- ▸Demo Day: Present your quiz generator to the cohort and guest evaluators
Portfolio Project: QuizForge
A full-stack AI application that generates educational quizzes from any source material.
Overview
Build "QuizForge" — an AI-powered quiz generation platform. Teachers paste in their lesson content (or provide a topic), select parameters (difficulty level, number of questions, question types), and the tool generates a pedagogically-sound quiz. Students can then take the quiz interactively and receive instant scoring with explanations. All quizzes are saved for future use and analytics.
Core Features
Technical Architecture
┌─────────────────────────────────────────────────────┐ │ FRONTEND (Next.js) │ │ ┌─────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ Content │ │ Quiz │ │ Results │ │ │ │ Input │→ │ Taking │→ │ Dashboard │ │ │ │ Form │ │ View │ │ + Analytics │ │ │ └─────────┘ └──────────┘ └──────────────────┘ │ │ │ ↑ │ ├─────────┼────────────────────────────┼──────────────┤ │ ↓ API ROUTES │ │ │ ┌─────────────┐ ┌─────────────────────────┐ │ │ │ POST │ │ GET │ │ │ │ /api/quiz/ │ │ /api/quiz/[id]/results │ │ │ │ generate │ │ │ │ │ └──────┬──────┘ └────────────┬────────────┘ │ ├─────────┼──────────────────────┼────────────────────┤ │ ↓ BACKEND ↑ │ │ ┌─────────────┐ ┌───────────────────┐ │ │ │ OpenAI │ │ PostgreSQL │ │ │ │ API │ │ Database │ │ │ └─────────────┘ └───────────────────┘ │ └─────────────────────────────────────────────────────┘
Grading Rubric
| Criteria | Weight | Excellent (A) | Good (B) | Needs Work (C) |
|---|---|---|---|---|
| AI & Prompt Quality | 30% | Questions are pedagogically sound, well-calibrated by difficulty, aligned with Bloom's levels | Questions are reasonable but inconsistent in difficulty or pedagogical alignment | Questions are generic, poorly calibrated, or frequently incorrect |
| Full-Stack Implementation | 25% | Clean API design, proper data flow, database integration, error handling throughout | Working API, some data persistence, basic error handling | API works but fragile, no database, poor error handling |
| User Experience | 20% | Polished, intuitive flow, excellent loading states, mobile responsive | Clean UI, working flow, basic responsiveness | Confusing flow, no loading states, desktop-only |
| Code Quality | 15% | TypeScript, clean components, consistent patterns, well-documented | Readable code, reasonable structure, some documentation | Messy code, large files, no documentation |
| Demo & Presentation | 10% | Clear 3-min demo, explains design decisions, shows real usage | Working demo, covers main features | Demo has issues, doesn't explain reasoning |
Daily Milestones
Stretch Goals
- ★Support PDF/document upload with text extraction (e.g., pdf-parse library)
- ★Add quiz analytics: track which questions students get wrong most often
- ★Implement adaptive difficulty — if a student scores high, generate harder questions
- ★Add collaborative features — teachers can share quiz templates with each other
- ★Build a quiz bank — save and categorize quizzes by subject and grade level
Key Implementation Snippets
// Quiz generation prompt template with Bloom's Taxonomy
export function buildQuizPrompt(params: {
content: string;
numQuestions: number;
difficulty: 1 | 2 | 3 | 4 | 5;
questionTypes: ("mcq" | "true_false" | "short_answer")[];
}) {
const bloomLevel = {
1: "Remember — recall facts and basic concepts",
2: "Understand — explain ideas or concepts",
3: "Apply — use information in new situations",
4: "Analyze — draw connections among ideas",
5: "Evaluate — justify a stand or decision",
}[params.difficulty];
return `You are an expert educational assessment designer.
Generate ${params.numQuestions} quiz questions from the
provided content.
BLOOM'S TAXONOMY LEVEL: ${bloomLevel}
QUESTION TYPES: ${params.questionTypes.join(", ")}
RULES:
- Each question must be directly supported by the content
- MCQs must have exactly 4 options with 1 correct answer
- Include a brief explanation for the correct answer
- Vary question difficulty within the specified Bloom's level
- Avoid ambiguous or trick questions
CONTENT:
${params.content}
Respond in this exact JSON format:
{
"questions": [
{
"type": "mcq",
"question": "...",
"options": ["A) ...", "B) ...", "C) ...", "D) ..."],
"correct_answer": "A",
"explanation": "...",
"bloom_level": "Remember"
}
]
}`;
}import { NextRequest, NextResponse } from "next/server";
import { buildQuizPrompt } from "@/lib/prompts/quiz-generator";
export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { content, numQuestions, difficulty, questionTypes } = body;
// Validate inputs
if (!content || content.length < 50) {
return NextResponse.json(
{ error: "Content must be at least 50 characters" },
{ status: 400 }
);
}
// Build prompt and call OpenAI
const prompt = buildQuizPrompt({
content,
numQuestions: numQuestions || 5,
difficulty: difficulty || 3,
questionTypes: questionTypes || ["mcq"],
});
const response = await fetch(
"https://api.openai.com/v1/chat/completions",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: "gpt-4o",
messages: [{ role: "user", content: prompt }],
temperature: 0.7,
response_format: { type: "json_object" },
}),
}
);
const data = await response.json();
const quiz = JSON.parse(
data.choices[0].message.content
);
return NextResponse.json(quiz);
} catch (error) {
console.error("Quiz generation error:", error);
return NextResponse.json(
{ error: "Failed to generate quiz" },
{ status: 500 }
);
}
}