Back to Curriculum
Week 10Portfolio Project #2

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."

Prompt EngineeringBloom's TaxonomyNext.jsOpenAI APIAssessment Design
Lesson Guide

Weekly Roadmap

A structured path from understanding AI-based assessment design to shipping a complete quiz generator application.

Day 1

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
Day 2

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
Day 3

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
Day 4

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
Day 5

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
Project Brief

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

Content input: Paste text, enter a topic, or upload a document
Quiz configuration: Select difficulty (1-5), question count (5-20), and types (MCQ, T/F, short answer)
AI generation: Use OpenAI API to generate questions aligned with Bloom's Taxonomy
Interactive quiz: Students answer questions one at a time with progress tracking
Instant scoring: Show correct/incorrect with AI-generated explanations
Quiz history: Save generated quizzes to PostgreSQL for reuse
Results dashboard: Show scores, time taken, and areas for improvement
Share/export: Generate shareable links or export as PDF

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

CriteriaWeightExcellent (A)Good (B)Needs Work (C)
AI & Prompt Quality30%Questions are pedagogically sound, well-calibrated by difficulty, aligned with Bloom's levelsQuestions are reasonable but inconsistent in difficulty or pedagogical alignmentQuestions are generic, poorly calibrated, or frequently incorrect
Full-Stack Implementation25%Clean API design, proper data flow, database integration, error handling throughoutWorking API, some data persistence, basic error handlingAPI works but fragile, no database, poor error handling
User Experience20%Polished, intuitive flow, excellent loading states, mobile responsiveClean UI, working flow, basic responsivenessConfusing flow, no loading states, desktop-only
Code Quality15%TypeScript, clean components, consistent patterns, well-documentedReadable code, reasonable structure, some documentationMessy code, large files, no documentation
Demo & Presentation10%Clear 3-min demo, explains design decisions, shows real usageWorking demo, covers main featuresDemo has issues, doesn't explain reasoning

Daily Milestones

MondayPrompt templates finalized, API schema designed, project scaffolded
TuesdayQuiz generation API route working, returns valid JSON quiz data
WednesdayBackend complete with database storage, all API routes functional
ThursdayFrontend UI complete: input form, quiz view, and results dashboard
FridayDeployed to Vercel, demo video recorded, peer code review complete

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
Starter Code

Key Implementation Snippets

lib/prompts/quiz-generator.ts
// 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"
    }
  ]
}`;
}
app/api/quiz/generate/route.ts
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 }
    );
  }
}