← Back to Projects

At a Glance

ClassMaker.ai AI Scheduling Agent demo
01

Problem

Building weekly block schedules for after-school programs is a combinatorial constraint problem — and coordinators are solving it manually in spreadsheets. Every student has a pickup time, grade, and activity preferences. Every class has a capacity limit, grade range, and fixed time blocks. The scheduler has to satisfy all of those constraints simultaneously across dozens of students and classes, and then field individual requests like "move Maya out of Monday art" after the fact. That last part — ad-hoc refinement — is where spreadsheets completely break down.

The real question is whether a large language model can serve as the scheduling engine: not just generate text about scheduling, but reason through constraints and produce a valid, structured schedule as output — and then accept natural-language corrections and revise it. That's an agentic task, and it requires a different kind of prompt design than question-answering.


02

Solution

ClassMaker.ai is a full-stack Next.js application that uses Groq's Llama 3.3 as a constraint-aware scheduling agent. Coordinators enter students and classes — manually or via CSV — and the AI generates a complete weekly class schedule within seconds, respecting capacity limits, grade ranges, fixed time slots, and individual pickup times. A built-in chat interface lets them refine the schedule afterward in plain English, with the model re-applying constraints on each revision.

The key design decision was treating schedule generation as a structured output problem rather than a conversation. The system prompt defines the constraint space and output format precisely; the model's job is to produce valid JSON that the frontend can render directly into a color-coded weekly grid — no post-processing layer required. Chat refinement works the same way: the existing schedule is fed back as context, the user's instruction is appended, and the model returns an updated JSON schedule.

The hardest engineering challenge wasn't the AI — it was prompt design. Getting Llama 3.3 to honor all constraints simultaneously, return valid JSON without preamble, and correctly re-apply constraints during chat refinement required careful iteration on the system prompt and output schema.

03

Tech Stack

The combination of a fast inference API, a structured output prompt, and a stateful chat interface is what makes the system feel agentic rather than just generative.


04

Deep Dive

AI agents don't have to be complex orchestration pipelines. The simplest definition of an agent is a model that takes actions — in this case, producing a structured, constraint-satisfying schedule rather than free-form text. ClassMaker.ai is a single-model agentic system: one well-designed prompt turns Llama 3.3 into a scheduling engine that can generate and revise weekly block schedules on demand.

This project began at an event in Irvine, CA (April 25, 2026) — my introduction to the Zero to Agent international build week, where developers around the world ship real AI agents from scratch. ClassMaker.ai was built and deployed as part of that global hackathon — a full-stack Next.js app powered by Groq's Llama 3.3, live on Vercel.

Zero to Agent wasn't just a name — it was the constraint. Zero lines of code at the start, a production URL by the end. The only way to ship a complete AI application under hackathon pressure is to make every technology choice with speed of execution in mind.

Why This Project?

After-school scheduling is a real operations problem. I've worked in educational settings long enough to know that coordinators waste significant time every week building and patching student schedules in spreadsheets. It's a textbook constraint satisfaction problem — exactly the kind of structured reasoning task that a capable LLM with a well-designed prompt can take over entirely.

I also wanted to demonstrate the difference between a generative AI feature (an LLM answering a question) and an agentic AI system (an LLM taking structured, consequential actions as its primary output). ClassMaker.ai is the latter. The model's output isn't text to be read — it's a schedule to be rendered, used, and revised. That distinction matters in production AI applications, and it was the central engineering challenge here.


What You'll Learn from This


Key Takeaways


Architecture Overview

ClassMaker.ai follows a clean full-stack architecture with Next.js handling both the UI and the server-side AI integration. The client never touches the Groq API directly — all model calls go through Next.js API routes, which keeps the API key server-side and allows server-side validation of inputs before they reach the model.

Browser (React / Next.js Client Components)
   ↓ Student + class data as JSON (manual or CSV import)
Next.js API Route (Server-Side)
   ↓ Constructs constraint-aware system prompt + user message
Groq API — Llama 3.3-70b-versatile
   ↑ Returns structured JSON schedule
Next.js API Route → React Client
   ↓ Renders color-coded weekly grid per student
Chat Refinement Loop
   ↓ User plain-English instruction + current schedule → revised JSON
ComponentRoleWhy This Choice
Next.js App RouterFull-stack frameworkServer components + API routes in one codebase; no separate backend needed
TypeScriptType safetyEnforces data contracts between AI output schema and frontend rendering logic
Groq (Llama 3.3)AI scheduling engineIndustry-leading inference speed; Llama 3.3-70b follows structured output prompts reliably
Tailwind CSSStylingRapid UI development; color-coded grid built with utility classes, no custom CSS
VercelDeploymentZero-config CI/CD for Next.js; production URL in minutes, env vars in dashboard

How It Was Built

Step 1

Define the Data Model in TypeScript

Before writing any AI integration, I defined TypeScript interfaces for the three core data structures: Student, Class, and ScheduleEntry. These interfaces served as the contract between user input, the AI prompt, and the frontend renderer — if the model returned a schedule that didn't match the ScheduleEntry shape, TypeScript would surface the mismatch before it became a runtime error in the grid component.

interface Student {
  id: string;
  name: string;
  grade: number;
  pickupTime: string;
  preferences: string[];
  goals: string;
}

interface Class {
  id: string;
  name: string;
  day: string;
  blockStart: number;
  blockEnd: number;
  gradeMin: number;
  gradeMax: number;
  capacity: number;
  type: string;
}

interface ScheduleEntry {
  studentId: string;
  studentName: string;
  assignments: { day: string; block: number; className: string }[];
}

Step 2

Design the Constraint-Aware Scheduling Prompt

The system prompt is the most important engineering artifact in the project. It defines the constraint space the model must satisfy, specifies the exact JSON output schema, and explicitly prohibits preamble or commentary around the JSON. Without those last two instructions, Llama 3.3 will sometimes wrap its output in markdown code fences or add an explanation sentence — both of which break JSON parsing.

Constraints enforced through the prompt: class capacity limits, grade range eligibility, fixed time block assignments, and per-student pickup time cutoffs (a student with a 4:30pm pickup cannot be scheduled into a block that ends at 5pm). Each constraint was described explicitly in the system prompt with an example of the edge case it was meant to prevent.

const systemPrompt = `You are a school scheduling agent. Given a list of students
and available classes, generate a weekly block schedule that:
- Respects each class's capacity limit (never exceed it)
- Only assigns students within the class's grade range
- Never schedules a student into a block that ends after their pickup time
- Assigns each student to at most one class per time block per day

Return ONLY a valid JSON array matching this exact schema — no markdown,
no explanation, no preamble:
[{ "studentId": "...", "studentName": "...", "assignments":
   [{ "day": "Monday", "block": 1, "className": "Art" }] }]`;

Step 3

Wire the Next.js API Route to Groq

The /api/schedule route receives the students and classes payload from the client, constructs the full prompt, and calls the Groq SDK. Keeping this logic in an API route rather than a client-side function means the GROQ_API_KEY never leaves the server — it's set in Vercel's environment variables and accessed only from the server context.

import Groq from 'groq-sdk';

const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });

export async function POST(req: Request) {
  const { students, classes } = await req.json();

  const completion = await groq.chat.completions.create({
    model:       'llama-3.3-70b-versatile',
    temperature: 0.2,
    messages: [
      { role: 'system',  content: systemPrompt },
      { role: 'user',    content: buildUserMessage(students, classes) },
    ],
  });

  const raw      = completion.choices[0].message.content ?? '';
  const schedule = JSON.parse(raw);
  return Response.json({ schedule });
}

Temperature was set to 0.2 — low enough to produce deterministic, constraint-consistent schedules without stripping the model of the flexibility to find creative assignments when the constraint space is tight.

Step 4

Implement Chat-Based Schedule Refinement

The chat interface accepts plain-English instructions like "move Maya out of Monday art and into something after 3pm" and returns a revised schedule. The implementation passes the full current schedule as part of the user message alongside the refinement instruction — the model receives complete context and returns a new, constraint-satisfying JSON schedule.

This stateful context passing is what makes refinement work correctly. Without feeding the existing schedule back, the model would treat every chat message as a fresh generation request. With it, the model understands which slots are already occupied and can make targeted, minimal edits rather than regenerating the entire schedule from scratch.

Step 5

Build the Weekly Grid Visualization & Deploy

The schedule JSON is rendered as a color-coded weekly grid — one row per student, one column per time block per day. Tailwind's grid utilities handled layout; each class type was assigned a distinct color class so coordinators can scan the full schedule visually rather than reading row by row.

Deployment to Vercel was a single command. The GROQ_API_KEY was added to Vercel's environment variable settings; the Next.js build pipeline handled the rest. The production URL was live within minutes of the first successful build.


What I Built & What I Learned


What I Learned & Why It Matters to Employers

ClassMaker.ai demonstrates the full cycle of agentic AI development: problem scoping, data modeling, prompt engineering for structured output, full-stack integration with a production LLM API, and zero-friction deployment. I didn't just connect an LLM to a frontend — I designed a system prompt that turns a general-purpose model into a domain-specific scheduling agent, handled the edge cases where the model needed to be corrected, and shipped a working application to a real URL within a single day. That combination — rapid agentic development with production deployment — is exactly what teams building AI-native products need.

Conclusion & Reflections

The most important lesson from ClassMaker.ai wasn't about scheduling or LLMs — it was about what "production-ready" means for an agentic AI application. It means the model's output is reliable enough to be consumed programmatically, not just read by a human. It means API keys never leave the server. It means the chat refinement loop maintains state correctly across turns. And it means the application is live at a real URL, not running on localhost.

Groq + Next.js + Vercel is a remarkably productive stack for this kind of work. The tooling decisions removed nearly all infrastructure overhead, which meant almost the entire day went into the actual product — the prompt design, the constraint model, the UI, and the refinement flow. For anyone building AI-native applications, that ratio is hard to beat.

FeatureStatus
Student entry (manual + CSV import)COMPLETED ✓
Class entry with constraint validationCOMPLETED ✓
AI schedule generation via Groq (Llama 3.3)COMPLETED ✓
Constraint enforcement (capacity, grade, pickup time)COMPLETED ✓
Chat-based schedule refinementCOMPLETED ✓
Color-coded weekly grid visualizationCOMPLETED ✓
Production deployment on VercelCOMPLETED ✓

Want to Try the App?

The live app is deployed on Vercel.