Teemo started with a simple frustration: when you want to learn something new, the internet hands you a pile of tutorials with no order. What you actually want is a syllabus — units, lessons, checkpoints — and that's exactly the kind of structured thing LLMs are good at generating.
Here's what building it taught me.
Structured outputs beat clever prompts
My first version asked the model to "create a course about X" and parsed whatever came back. It worked in demos and failed everywhere else. The fix was boring and effective: define a strict schema for the course (units → lessons → objectives → quiz items), ask the model to fill the schema, and validate before anything touches the UI.
The lesson generalizes: treat the LLM as an unreliable API, not an oracle. Validate its output like you'd validate user input.
The hard part is never the AI
Maybe 15% of Teemo's code touches an LLM. The rest is the same engineering as any product: auth, persistence, loading states, error recovery, and the unglamorous work of making a multi-step generation flow feel fast when the underlying calls take twenty seconds.
Streaming helped more than anything — showing the course outline materialize section by section makes the same latency feel completely different.
Cost is a design constraint
Generating a full course is many model calls. Early on, I regenerated everything when a user tweaked one lesson. Caching intermediate results and regenerating only the changed subtree cut costs by an order of magnitude. Token budgets belong in the design doc, not the postmortem.
What's next
Adaptive difficulty — using quiz results to decide whether the next lesson should remediate or accelerate. That's the part that overlaps with my research interests: evaluation is everything.
The code is on GitHub if you want to poke around.