LearnMD: Format Specification v0.4
Part of the LearnSpec suite. Draft based on v0.3.
Core principle
LearnMD is the educational content format of the LearnSpec suite. It covers instruction, explaining what to know, while QuizMD covers assessment. Together they form a complete teach → assess stack, in portable plain-text files.
A complete course, chapters, lessons, exercises, quizzes, can live in a single valid .learn.md file. The !import directive is a composition tool for reusability, not a prerequisite.
| Principle | Description |
|---|---|
| Markdown-first | A .learn.md file is valid Markdown readable in any editor |
| File-native | All content lives in files, no database required |
| Git-native | Versionable, diffable, and mergeable like code |
| AI-native | Generatable and consumable by LLMs without specific tooling |
| Progressively enriched | Plain text (Level 0) up through special fenced blocks (Level 2) |
| LearnSpec-interoperable | Natively integrates with QuizMD, DiagramMD, MediaMD, and GlossaryMD |
LearnMD inherits the universal frontmatter, directives, and validation rules defined in the Architecture Charter.
Format levels
| Level | Mechanism | Purpose |
|---|---|---|
| 0 | Plain .learn.md, native Markdown | Minimal content, readable everywhere |
| 1 | YAML frontmatter + GFM callouts | Metadata, estimated time, language |
| 2 | Special fenced blocks + directives | Examples, summaries, inline quizzes, imports |
Each level is a strict superset of the previous one. A Level 0 file is valid at Level 1 and 2.
Document architecture
Three-tier hierarchy
document (.learn.md, minimal or no frontmatter)
└── module (## heading)
└── lesson (### heading or file imported via !import)- Structure is strictly linear in v0.4 (no branching).
```quizblocks and!import,!ref,!checkpointdirectives are usable at any level.- Images are referenced via
(recommended) or(direct).
Level 0: Plain Markdown
Basic syntax
| Syntax | Meaning |
|---|---|
# Title | Document title (inferred by the parser if absent from frontmatter) |
## Module title | Main section heading |
### Lesson title | Sub-section heading |
> text | Generic blockquote |
!import ./file.learn.md | Include another lesson file |
!import ./file.quiz.md | Embed an external QuizMD checkpoint |
!ref ./file.diagram.md | Declare a DiagramMD context (enables ```diagram ref:slug resolution) |
!ref ./file.media.md | Declare a MediaMD context (enables media:slug resolution) |
!ref ./file.glossary.md | Declare a GlossaryMD context (enables term highlighting) |
```diagram ref:slug | Render a named diagram from a !ref-ed DiagramMD file |
!checkpoint id:slug | Mark a learner progress checkpoint |
$...$ | Inline LaTeX math formula |
$$...$$ | Block (display) LaTeX math formula |
 | Image via MediaMD with fallback for standard readers |
 | Direct image (URL) |
Minimal example
# Introduction to Python
!ref ./glossary-python.glossary.md
## Module 1: Variables
A **variable** is a named reference to a value in memory.
```python
age = 25
name = "Alice"
```
!checkpoint id:module-1-done label:"Module 1 complete"
## Module 2: Conditions
An `if` statement runs code only when a condition is true.Level 1: YAML frontmatter
A YAML block at the top of the .learn.md file, between two --- lines.
---
title: Python, Variables # optional: inferred from the first # H1 if absent
lang: en # REQUIRED: BCP-47 code (en, fr, en-US, …)
description: "Names, assignment, and basic types in Python, for learners with no prior programming experience."
# optional: short summary for catalogues, previews, and meta tags
estimated_time: 15min # optional: free-form duration string
tags: [python, variables] # optional: list of strings
author: Jane Smith # optional: string or {name, email, url}
spec_version: "0.4" # optional: LearnMD spec version this file targets
created: 2026-05-10 # optional: ISO 8601
updated: 2026-05-10 # optional: ISO 8601
license: CC-BY-4.0 # optional: SPDX identifier or "custom"
---Field reference
| Field | Required | Type | Description |
|---|---|---|---|
title | No | string | Overrides the first # H1. Inferred from H1 if absent. |
lang | Yes | BCP-47 | Language code: en, fr, en-US, etc. |
description | No | string | Short plain-text summary (typically 1–3 sentences), used for catalogues, link previews, and <meta name="description">. Distinct from title and from the body content. |
estimated_time | No | string | Free-form estimated reading/study time: 15min, 1h30, 2h |
tags | No | string[] | Thematic tags |
author | No | string or object | Author name, or {name, email, url} |
spec_version | No | string | LearnMD spec version this file targets (e.g. "0.4") |
created | No | date | Creation date, ISO 8601 |
updated | No | date | Last update date, ISO 8601 |
license | No | string | SPDX identifier (e.g. CC-BY-4.0) or custom |
GFM callouts
Callouts use GitHub Flavored Markdown syntax and are rendered with visual emphasis by compatible players.
Supported everywhere (GitHub, Obsidian, LearnSpec players):
| Syntax | Semantic | Typical use |
|---|---|---|
> [!note] | Note | Supplementary information |
> [!tip] | Tip | Best practice, shortcut, helpful advice |
> [!warning] | Warning | Common pitfall, frequent mistake |
> [!important] | Important | Critical point to remember |
> [!caution] | Caution | Risk of error or data loss |
Extended callouts (degrade gracefully to a blockquote on GitHub):
| Syntax | Semantic | Typical use |
|---|---|---|
> [!summary] | Summary | Key takeaways at the end of a lesson |
> [!example] | Example | Non-code illustrative example |
> [!objectives] | Learning Objectives | What the learner will be able to do, place at top |
Level 2: Special fenced blocks and directives
Composition directives
!import <path>
Includes content from another file at the current position. The file type is detected from the extension:
| Extension | Behaviour |
|---|---|
.learn.md | Lesson content inserted inline (frontmatter ignored) |
.quiz.md | Rendered as an interactive QuizMD checkpoint |
DiagramMD files (.diagram.md) are not consumed via !import, they are leaf catalogues declared with !ref and addressed by slug. See !ref below.
!import ./03-conditions.learn.md
!import ./check-variables.quiz.md- Imports are recursive (an imported file may itself contain
!importdirectives). - Circular imports are silently skipped.
- Local paths or external URLs accepted, see the Architecture Charter.
!ref <path>
Declares a context file without including its content inline. Produces no visible render, it establishes a context the player uses in the background.
| Extension | Behaviour |
|---|---|
.media.md | Enables media:slug reference resolution |
.glossary.md | Enables defined-term highlighting |
!ref ./media-python.media.md
!ref ./glossary-python.glossary.md
!ref https://github.com/example/commons/blob/main/glossaries/en/computing.glossary.mdMultiple !ref directives may coexist in the same document.
!checkpoint id:slug [label:"..."] [type:...] [badge:...]
Marks a named progress point in the lesson.
!checkpoint id:module-1-done label:"Module 1 complete"
!checkpoint id:module-variables-done label:"Variables mastered" badge:./badge-variables.badge.md| Attribute | Required | Default | Description |
|---|---|---|---|
id | Yes | none | Unique identifier within the document |
label | No | "Checkpoint" | Display text shown to the learner |
type | No | milestone | milestone / read / exercise-complete |
badge | No | none | Path to a BadgeMD file awarded when this checkpoint is reached |
Rules:
idvalues must be unique within a document.- When a
!import ./quiz.quiz.mdis present, the quiz itself acts as a natural checkpoint, an additional!checkpointat the same position is redundant.
Checkpoint JSON (parser output)
{
"checkpoints": [
{ "id": "module-1-done", "label": "Module 1 complete", "type": "milestone", "position": 42 },
{ "id": "module-2-done", "label": "Module 2 complete", "type": "milestone", "position": 87 }
]
}Inline quiz checkpoint
Embeds a single question using QuizMD Level 0 syntax directly in the lesson. The QuizMD frontmatter (global configuration, scoring, reveal, feedback_mode) is not applicable inline. All QuizMD Level 0 question types are supported: mcq, multi, open, tf, match, order.
```quiz
? Which operator assigns a value in Python?
- [x] =
- [ ] ==
- [ ] :=
```| Attribute | Default | Description |
|---|---|---|
scored:false | Yes (default) | Practice mode, immediate feedback, no score recorded |
scored:true | none | Scored checkpoint, contributes to lesson score |
Inline quiz vs external file:
| Need | Syntax |
|---|---|
| Single simple question | Inline ```quiz block |
| Multiple questions, advanced scoring, or shared config | !import ./file.quiz.md |
Fenced callout blocks
Level 2 alternatives to GFM callouts. Support richer content (multi-paragraph, nested lists, syntax-highlighted code).
| Language | Icon | Label | Typical use |
|---|---|---|---|
```note | 📝 | Note | Supplementary information |
```tip | 💡 | Tip | Best practice or helpful advice |
```warning | ⚠️ | Warning | Common pitfall, frequent mistake |
```important | ❗ | Important | Critical point to remember |
```caution | 🔴 | Caution | Risk of error or data loss |
```summary | ✅ | Summary | Key takeaways at the end of a lesson |
```example | 🔍 | Example | Illustrative example |
```objectives | 🎯 | Learning Objectives | What the learner will achieve, place at top |
Optional title attribute:
```example title:"Token prediction"
Context: "The capital of France is"
Most likely token: " Paris"
```Optional code language: place before title: to enable syntax highlighting:
```example python title:"Assigning and reassigning a variable"
score = 0
print(score) # → 0
score = 42
print(score) # → 42
```Math support
LearnMD uses LaTeX formulas rendered via KaTeX. Math is auto-detected: no frontmatter flag is required.
| Form | Syntax | Rendering |
|---|---|---|
| Inline | $E = mc^2$ | Embedded in the line of text |
| Block (display) | $$\int_0^\infty e^{-x}\,dx = 1$$ | Centred on its own line |
Diagram support
LearnMD supports all diagram block types defined in the DiagramMD spec. Inline diagrams use DiagramMD Level 0 fenced block syntax with optional Level 2 attributes (caption, width, alt). The DiagramMD frontmatter (Level 1) is not applicable inline.
```mermaid caption:"System architecture" width:80% alt:"Client-API-DB diagram"
flowchart LR
Client --> API --> DB
``````abc play
X:1
T:Main Theme
K:C
|: G2 AB c2 BA | G4 E4 :|
```Supported types, shared attributes (caption, width, alt), and AI authoring recommendations are documented in the DiagramMD spec.
For diagrams reused across multiple lessons, gather them in a .diagram.md catalogue declared via !ref ./file.diagram.md and reference each one inline with:
```diagram ref:auth-flow
```Media references
Images are referenced via two mechanisms.
Via MediaMD (recommended)
Requires a !ref to a MediaMD file at the top of the document. Enables automatic licence and attribution resolution.
!ref ./media-biology.media.md
media:chloroplast: slug resolved via the MediaMD → full-resolution image + licence metadata."https://...": fallback URL, displayed in standard readers without LearnSpec.
Direct (URL)
Syntax reference
| Element | Syntax | Level |
|---|---|---|
| Document title | # Title | 0 |
| Module heading | ## Module title | 0 |
| Lesson heading | ### Lesson title | 0 |
| Generic blockquote | > text | 0 |
| Import lesson | !import ./file.learn.md | 0 |
| Embed quiz | !import ./file.quiz.md | 0 |
| Declare DiagramMD | !ref ./file.diagram.md | 0 |
| Reference a diagram | ```diagram ref:slug | 0 |
| Declare MediaMD | !ref ./file.media.md | 0 |
| Declare GlossaryMD | !ref ./file.glossary.md | 0 |
| Progress checkpoint | !checkpoint id:slug [label:"..."] [type:...] [badge:...] | 0 |
| Inline math | $formula$ | 0 |
| Block math | $$formula$$ | 0 |
| Image via MediaMD |  | 0 |
| Direct image |  | 0 |
| Diagram block | ```{type} [caption:"..."] [width:...] [alt:"..."] | 0 |
| Frontmatter | --- YAML --- | 1 |
| Note callout | > [!note] | 1 |
| Tip callout | > [!tip] | 1 |
| Warning callout | > [!warning] | 1 |
| Important callout | > [!important] | 1 |
| Summary callout | > [!summary] | 1 |
| Example callout | > [!example] | 1 |
| Objectives callout | > [!objectives] | 1 |
| Inline quiz | ```quiz | 2 |
| Scored inline quiz | ```quiz scored:true | 2 |
| Note callout (fenced) | ```note | 2 |
| Summary callout (fenced) | ```summary | 2 |
| Example callout (fenced) | ```example [lang] [title:"..."] | 2 |
| Objectives callout (fenced) | ```objectives | 2 |
Validation
Lenient mode (default)
| Condition | Level |
|---|---|
lang absent from frontmatter | Warning |
Title absent (no H1 and no frontmatter title) | Warning |
| Unclosed fenced block | Error |
Inline quiz block with no ? line | Error |
!checkpoint missing required id attribute | Error |
Duplicate !checkpoint id within a document | Error |
!import pointing to a missing file | Warning |
!ref pointing to a missing file | Warning |
media:slug without a matching !ref MediaMD | Warning |
media:slug without a fallback URL | Warning |
Strict mode (--strict)
| Condition | Level |
|---|---|
lang absent | Error |
| Title absent | Error |
| All lenient-mode errors | Error |
!ref pointing to a missing file | Error |
media:slug without a fallback URL | Error |
Strict mode is recommended for CI pipelines and production publishing. Lenient mode is appropriate during authoring.
Changes from v0.3
| Element | Change |
|---|---|
| Hierarchy | path renamed to document (avoids confusion with TrackMD) |
| Principles | "QuizMD-interoperable" → "LearnSpec-interoperable" |
!ref | New directive, declares DiagramMD, MediaMD and GlossaryMD contexts |
| Diagram reference | New ```diagram ref:slug block, resolves a named diagram from a !ref-ed DiagramMD |
| Images | New media:slug syntax via MediaMD |
| Frontmatter | Added created, updated, license (universal LearnSpec fields) |
| Diagrams | Mermaid and ABC sections simplified, delegate to DiagramMD spec |