Create effective, ADHD-friendly lesson plans for AI/ML learning. Use when designing new lessons or adapting curriculum.
Load context strategically to preserve context window. Don't load everything upfront.
READ IMMEDIATELY:
1. .claude/skills/interactive-widgets/references/component-catalog.md (~200 lines)
2. src/lib/exercises.ts (~60 lines) — check existing slugs
| When... | Load... |
|---|---|
| Planning which lesson to build | docs/curriculum.md — find the specific section |
| Need widget patterns | .claude/skills/interactive-widgets/SKILL.md |
| Need lesson structure reference | ONE recent lesson (e.g., src/components/lessons/module-1-1/GradientDescentLesson.tsx) |
| Building a widget | Relevant widget file from src/components/widgets/ |
These are in this skill file already:
These patterns apply to building effective lessons for any subject. Follow these when creating new lesson components.
The Problem: A lesson that tries to cover too much becomes overwhelming and hard to learn from.
The Solution: Split large topics into multiple focused lessons, each with ONE core objective.
Example: A lesson on "Transformers" trying to cover:
Should be split into focused lessons:
attention-mechanism — Just the core attention concept with visualizationself-attention — Multi-head self-attention with codetransformer-architecture — How the pieces fit togetherRule of thumb: If a lesson has more than 3-4 major sections, consider splitting it.
The Problem: Lessons that only use text and math formulas fail to engage multiple learning pathways. This leads to shallow understanding that doesn't stick.
The Principle: Every core concept should be presented through 2-3 different modalities:
| Modality | Examples | Engages |
|---|---|---|
| Verbal | Text explanations, analogies | Language processing, narrative memory |
| Symbolic | Math formulas, code | Abstract reasoning, precision |
| Visual | Diagrams, animations, graphs | Spatial reasoning, pattern recognition |
| Kinesthetic | Sliders, draggable points, manipulation | Motor memory, active learning |
The Check: For each major concept in a lesson, ask:
Example - Teaching "What is a Neuron":
y = w₁x₁ + w₂x₂ + b with text explanationy = w₁x₁ + w₂x₂ + b (symbolic)Why it matters: Different people learn through different channels. More importantly, concepts encoded through multiple modalities are more durable and transferable. When a learner can see it, manipulate it, AND read the formula, the understanding is deeper.
Rule of thumb: If a section only has text and math, it needs a visual or interactive element. Math alone is not enough.
Consider what concepts could be enhanced with interactive visualization or exploration. See the interactive-widgets skill for:
Quick check: For each lesson section, ask:
CRITICAL: Always use the Row component from @/components/layout/Row.
Never create manual flex layouts in lessons. The Row component automatically injects an empty aside placeholder when no aside is provided, which prevents content from expanding full-width.
import { Row } from '@/components/layout/Row'
// ✅ CORRECT - Always use Row
<Row>
<Row.Content>
<Card ... />
</Row.Content>
<Row.Aside>
<TipBlock>...</TipBlock>
</Row.Aside>
</Row>
// ✅ CORRECT - Conditional aside (Row auto-injects empty placeholder)
<Row>
<Row.Content>
<Card ... />
</Row.Content>
{isExpanded && (
<Row.Aside>
<TipBlock>...</TipBlock>
</Row.Aside>
)}
</Row>
// ❌ WRONG - Manual flex layout (causes width issues!)
<div className="flex flex-col lg:flex-row gap-8 lg:gap-32 items-start">
<div className="w-full lg:w-[900px] flex-shrink-0">
<Card ... />
</div>
</div>
Why this matters: When the aside is conditionally rendered and you use manual flex, the content expands full-width when the aside is hidden. Row prevents this by always maintaining the 2-column structure.
Use lesson blocks from @/components/lessons for visual consistency.
For Asides (sidebar blocks):
| Block | Purpose | Color |
|---|---|---|
TipBlock | Helpful hints, "Use for" | Sky blue |
InsightBlock | Key concepts, "Why it works" | Violet |
TryThisBlock | Interactive prompts, variations | Emerald |
WarningBlock | Common mistakes | Rose |
ConceptBlock | Theory explanations | Neutral |
For Main Content (gradient cards):
| Block | Purpose | When to Use |
|---|---|---|
GradientCard | Single categorized card | Feature highlights, categorized info |
ComparisonRow | Two side-by-side cards | A vs B comparisons |
PhaseCard | Numbered sequential card | Multi-step processes, timeline phases |
See interactive-widgets skill → references/component-catalog.md for full component reference.
Use CodeBlock from @/components/common/CodeBlock for syntax-highlighted code in lessons.
import { CodeBlock } from '@/components/common/CodeBlock'
<CodeBlock
code={`def forward(self, x):
return self.linear(x)`}
language="python"
filename="model.py" // Optional - shows in header
/>
Features:
Styling notes (from ventures):
rgb(156 163 175 / 0.5) for dark, rgb(107 114 128 / 0.5) for lighttext-xs for appropriate code sizetransparent (inherits from container)oneDark / oneLight themes from react-syntax-highlighterHydration safety: The component handles SSR by defaulting to dark theme until mounted, avoiding hydration mismatches.
Reusable clipboard copy button from @/components/common/ClipboardCopy.
import { ClipboardCopy } from '@/components/common/ClipboardCopy'
<ClipboardCopy text="content to copy" />
<ClipboardCopy text={code} className="h-7 w-7" />
<ClipboardCopy text={url} label="Copy URL" />
Props:
text — Content to copy (required)variant — Button variant: 'ghost' (default), 'default', 'outline'size — Button size: 'icon' (default), 'sm', 'default', 'lg'label — Optional text label (shows "Copied!" on success)className — Additional classesUses useTimeout hook for the 2-second "copied" state reset.
For lessons with formulas, use KaTeX:
import 'katex/dist/katex.min.css'
import { InlineMath, BlockMath } from 'react-katex'
// Inline math in paragraph
<p>The loss is <InlineMath math="\hat{y} = wx + b" /> where...</p>
// Block math (centered, standalone)
<BlockMath math="L = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2" />
// Emphasized formula box
<div className="py-4 px-6 bg-muted/50 rounded-lg">
<BlockMath math="\theta_{new} = \theta_{old} - \alpha \nabla L" />
</div>
Pattern for explaining formulas:
<div className="py-4">
<BlockMath math="L = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2" />
</div>
<p className="text-muted-foreground">Let's break this down:</p>
<ul className="list-disc list-inside text-muted-foreground space-y-2 ml-4">
<li><InlineMath math="y_i - \hat{y}_i" /> — the residual for point i</li>
<li><InlineMath math="(\cdot)^2" /> — square it (makes positive)</li>
<li><InlineMath math="\sum" /> — sum over all points</li>
<li><InlineMath math="\frac{1}{n}" /> — divide by count</li>
</ul>
Lessons should include curated external references — especially foundational papers and key resources that deepen understanding beyond what the lesson covers.
Why this matters: Many AI/ML concepts trace back to seminal papers. Linking to these gives the learner a path from "I get the intuition" to "I can read the original source." It also builds the habit of engaging with primary sources, which is essential for staying current in a fast-moving field.
What to include:
| Type | When | Example |
|---|---|---|
| Foundational papers | The concept has a canonical paper | "Attention Is All You Need" for transformers |
| Clear explanations | A blog post or video explains it better than you can in a sidebar | Karpathy's "Let's build GPT" |
| Implementation references | Official docs or tutorials for hands-on follow-up | PyTorch docs for nn.MultiheadAttention |
| Deep dives | For the learner who wants to go further | Survey papers, advanced tutorials |
How to include them:
References go in a dedicated section near the end of the lesson — after the SummaryBlock, before the NextStepBlock. Use the shared ReferencesBlock component from @/components/lessons.
import { ReferencesBlock } from '@/components/lessons'
<Row>
<Row.Content>
<ReferencesBlock
references={[
{
title: 'Attention Is All You Need',
authors: 'Vaswani et al., 2017',
url: 'https://arxiv.org/abs/1706.03762',
note: 'The paper that started it all. Read sections 3.1-3.2 for the attention mechanism — skip the experiments for now.',
},
{
title: 'The Illustrated Transformer',
authors: 'Jay Alammar',
url: 'https://jalammar.github.io/illustrated-transformer/',
note: 'Best visual walkthrough of the architecture. Great complement to this lesson.',
},
]}
/>
</Row.Content>
<Row.Aside>
<TipBlock title="Reading Order">
Start with the Illustrated Transformer, then skim the original paper.
Don't try to understand everything on the first read.
</TipBlock>
</Row.Aside>
</Row>
Props:
references — Array of { title, authors, url, note? }. The note field is for reading guidance (what to focus on, what to skip).title — Optional override, defaults to "References & Further Reading"ADHD-friendly reference principles:
note — Tell them what to read and what to skip (e.g., "Read sections 3.1-3.2, skip the experiments")Every lesson exports an Exercise object for the lesson registry:
import { Exercise } from '@/lib/exercises'
export const myLessonExercise: Exercise = {
slug: 'my-lesson', // URL slug
title: 'Lesson Title',
description: 'One-line description.',
category: 'Fundamentals', // Module name
duration: '20 min',
constraints: [ // ADHD scope boundaries
'Focus on intuition first',
'No code yet — just concepts',
],
steps: [ // Learning objectives
'Understand concept A',
'See why B matters',
],
skills: ['skill-tag-1'],
prerequisites: ['previous-lesson-slug'],
}
Register in src/lib/exercises.ts by importing and adding to exercises record.
Wrap interactive widgets in ExercisePanel for consistent styling + fullscreen:
import { ExercisePanel } from '@/components/widgets/ExercisePanel'
<Row>
<Row.Content>
<ExercisePanel title="Try Fitting a Line">
<LinearFitExplorer
initialSlope={0.3}
initialIntercept={-0.5}
showResiduals={true}
/>
</ExercisePanel>
</Row.Content>
<Row.Aside>
<TryThisBlock title="Experiment">
<ul className="space-y-2 text-sm">
<li>• Drag the intercept point up and down</li>
<li>• Try to minimize the MSE</li>
</ul>
</TryThisBlock>
</Row.Aside>
</Row>
At the end of a module's final lesson, celebrate completion with ModuleCompleteBlock:
import { ModuleCompleteBlock } from '@/components/lessons'
<Row>
<Row.Content>
<ModuleCompleteBlock
module="1.1"
title="The Learning Problem"
achievements={[
'ML as function approximation',
'Generalization vs memorization',
'Loss functions (MSE)',
]}
nextModule="1.2"
nextTitle="From Linear to Neural"
/>
</Row.Content>
</Row>
Props:
module — Module number (e.g., "1.1")title — Module title (e.g., "The Learning Problem")achievements — Array of concepts/skills learnednextModule — Next module numbernextTitle — Next module titleFor hands-on exercises, link to Colab notebooks stored in the /notebooks/ directory.
Notebook naming: {module}-{lesson}-{topic}.ipynb (e.g., 1-1-6-linear-regression.ipynb)
Colab link format:
import { ExternalLink } from 'lucide-react'
<div className="rounded-lg border-2 border-primary/50 bg-primary/5 p-6">
<div className="space-y-4">
<p className="text-muted-foreground">
Now write the code yourself in a Jupyter notebook.
</p>
<a
href="https://colab.research.google.com/github/brennancheung/CourseAI/blob/main/notebooks/1-1-6-linear-regression.ipynb"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-primary text-primary-foreground font-medium text-sm hover:bg-primary/90 transition-colors"
>
<ExternalLink className="w-4 h-4" />
Open in Google Colab
</a>
<p className="text-xs text-muted-foreground">
The notebook includes exercises: try different learning rates, add more noise...
</p>
</div>
</div>
Best practice: Use the in-app interactive widgets (like TrainingLoopExplorer) for visualization, and link to Colab for the "implement it yourself" exercises. The widget shows what happens; the notebook lets them write the code.
Colab workflow:
.ipynb file in /notebooks/ directoryStandard text patterns used in lessons:
// Paragraph text
<p className="text-muted-foreground">
Regular explanation text goes here.
</p>
// Text with emphasis
<p className="text-muted-foreground">
We need a way to <strong>measure</strong> how good a fit is — a
single number that tells us how wrong our predictions are.
</p>
// Bulleted list
<ul className="list-disc list-inside text-muted-foreground space-y-1 ml-4">
<li>First point</li>
<li>Second point with <strong>emphasis</strong></li>
</ul>
// Numbered list
<ol className="list-decimal list-inside text-muted-foreground space-y-1 ml-4">
<li>First step</li>
<li>Second step</li>
</ol>
// Spaced content sections
<div className="space-y-4">
<p className="text-muted-foreground">First paragraph...</p>
<p className="text-muted-foreground">Second paragraph...</p>
</div>
// Side-by-side concepts
<div className="grid gap-4 md:grid-cols-2">
<ConceptBlock title="Option A">...</ConceptBlock>
<ConceptBlock title="Option B">...</ConceptBlock>
</div>
Standard section structure with header + content + aside:
<Row>
<Row.Content>
<SectionHeader
title="The Core Insight"
subtitle="What does a machine actually 'learn'?"
/>
<div className="space-y-4">
<p className="text-muted-foreground">
First paragraph of explanation...
</p>
<p className="text-muted-foreground">
More precisely: <strong>key concept here</strong>.
</p>
</div>
</Row.Content>
<Row.Aside>
<InsightBlock title="Key Point">
The "aha moment" for this section goes in the aside.
</InsightBlock>
</Row.Aside>
</Row>
Section with comparison:
<Row>
<Row.Content>
<SectionHeader title="Two Approaches" subtitle="..." />
<ComparisonRow
left={{
title: 'Approach A',
color: 'amber',
items: ['Point 1', 'Point 2'],
}}
right={{
title: 'Approach B',
color: 'emerald',
items: ['Point 1', 'Point 2'],
}}
/>
</Row.Content>
<Row.Aside>
<TipBlock>When to use which...</TipBlock>
</Row.Aside>
</Row>
For lessons with multiple items to explore (concepts, techniques, models), use expandable cards wrapped in Row:
import { Row } from '@/components/layout/Row'
function ConceptRow({ concept, isExpanded, onToggle }) {
return (
<Row>
<Row.Content>
<ConceptCard
concept={concept}
isExpanded={isExpanded}
onToggle={onToggle}
/>
</Row.Content>
{isExpanded && (
<Row.Aside>
<TipBlock title="Key Insight">...</TipBlock>
<WarningBlock title="Common Misconceptions">...</WarningBlock>
</Row.Aside>
)}
</Row>
)
}
Key points:
Before creating a lesson, understand current state:
Learner baseline:
Identify the learning edge:
Every lesson needs ONE clear outcome:
Good objectives:
Bad objectives:
The test: Can you say "After this lesson, I can ___" with a specific, observable skill?
This is critical for ADHD. Explicitly close doors:
NOT optimizing for speed
NOT worrying about deployment
NOT covering all variations
Just focusing on: [the one thing]
Constraints liberate. Every "not" removes a decision.
The order of content in a lesson matters. Motivation drives learning.
The hook is critical. It comes right after context and before explanation. Its job is to increase motivation before teaching begins.
Types of hooks:
| Hook Type | Example |
|---|---|
| Demo | Interactive visualization showing the concept in action |
| Before/After | "Here's what GPT-2 outputs vs GPT-4 — what changed?" |
| Question | "Why can transformers understand context that RNNs can't?" |
| Challenge preview | "By the end, you'll implement this from scratch" |
| Real-world impact | "This technique enabled ChatGPT to exist" |
Hook principles:
Before finalizing any lesson, verify: