Every field in course.yml (course metadata) and lesson Markdown frontmatter. Fields marked * are required.
Place this file at the root of your repository. All other paths are relative to it.
| Field | Type | Default | Description |
|---|---|---|---|
title* | string | — | Course title shown on the course page and marketplace. |
slug* | string | — | URL-safe identifier. Must be unique per creator. Used in /courses/<slug>. |
description | string | — | Short description shown in search results and the course card. |
price_cents | integer | 0 | Price in cents (USD). 0 = free. E.g. 2900 = $29.00. |
currency | string | usd | ISO 4217 currency code. Currently usd, eur, gbp supported. |
repo_url | string | — | GitHub repository URL. Used for version tracking and re-imports. |
lessons_dir | string | lessons/ | Directory containing lesson Markdown files, relative to repo root. |
quizzes_dir | string | quizzes/ | Directory containing quiz YAML files, relative to repo root. |
cover_image | string | — | URL or relative path to course cover image (1200×630 recommended). |
tags | string[] | — | Searchable tags displayed on the course card and marketplace. |
affiliate_pct | integer | 0 | Affiliate commission percentage (0–80). Affiliates receive this % of each sale they refer. |
pricing_model | string | one_time | one_time or subscription (subscription requires Stripe subscription config). |
title: "TypeScript Deep Dive"
slug: "typescript-deep-dive"
description: "Master TypeScript from fundamentals to advanced patterns."
price_cents: 2900
currency: "usd"
repo_url: "https://github.com/you/typescript-deep-dive"
lessons_dir: "lessons/"
cover_image: "https://example.com/cover.png"
tags: ["typescript", "javascript", "programming"]
affiliate_pct: 20Each Markdown lesson file must begin with YAML frontmatter between --- delimiters.
| Field | Type | Default | Description |
|---|---|---|---|
title* | string | — | Lesson title shown in the sidebar and lesson header. |
slug* | string | — | URL-safe identifier. Inferred from filename if omitted. |
order* | integer | — | Sort order in the course sidebar. Start from 1. |
access | string | paid | free = public preview (no enrollment required). paid = gated. |
description | string | — | Short summary shown in the sidebar tooltip and lesson header. |
estimated_minutes | integer | — | Estimated reading/watching time shown on the lesson header. |
sandbox_url | string | — | StackBlitz, CodeSandbox, or CodePen embed URL. Gated for paid lessons. |
quiz_slug | string | — | Slug of a quiz YAML file in quizzes_dir to attach to this lesson. |
---
title: "Generics in TypeScript"
slug: "generics"
order: 5
access: paid
description: "Use generics to write reusable, type-safe code."
estimated_minutes: 20
sandbox_url: "https://stackblitz.com/edit/ts-generics-demo?embed=1"
quiz_slug: "generics-quiz"
---
# Generics in TypeScript
Generics allow you to write functions and classes that work with
multiple types while maintaining type safety...Quiz files live in quizzes/ and define auto-graded questions. They can be hand-authored or generated via teachrepo quiz generate.
id: "generics-quiz"
title: "Generics Quiz"
pass_threshold: 70
questions:
- type: multiple_choice
prompt: "What is the primary purpose of generics?"
choices:
- "To make code run faster"
- "To write reusable, type-safe code"
- "To avoid null checks"
- "To enable async/await"
answer: 1
explanation: "Generics let you write functions and classes that work with multiple types."
points: 1
- type: true_false
prompt: "Generic constraints restrict which types can be used."
answer: true
explanation: "The 'extends' keyword adds constraints to generic type parameters."
points: 1