Component reference
Every component below is registered in src/theme/MDXComponents.tsx, so it is
available in any .md or .mdx file under docs/ with no import
statement.
Each component exists because the alternative — plain Markdown — produced a recurring defect. The "use it when" line is the rule; the component is the mechanism.
Lesson framing
<LessonMeta>
Use it when: always, immediately after the title, before any prose.
<LessonMeta
duration={35}
level="advanced"
gitVersion="2.38"
prerequisites={[
{label: 'Rebase basics', to: '/history-and-rewriting/rebase-basics'},
{label: 'Anatomy of a commit', to: '/foundations/commit-anatomy'},
]}
/>
The values duplicate frontmatter deliberately: frontmatter is for machines, this
block is for readers. pnpm content:validate is what keeps the two honest.
<Objectives>
Use it when: always, after <LessonMeta>. Three to five observable capabilities.
<Objectives>
- Reorder commits without losing changes
- Squash a series of fixup commits into their target
- Recover from an interactive rebase you started by mistake
</Objectives>
Blank lines around the list are required — MDX needs them to parse the Markdown inside a JSX block.
<Prerequisites>
Use it when: the prerequisite needs a reason, not just a link. Otherwise the
prerequisites prop of <LessonMeta> is enough.
<Prerequisites
items={[
{label: 'The reflog', to: '/history-and-rewriting/reflog', why: 'recovery depends on it'},
]}
/>
<KeyTakeaways>
Use it when: always, as the last section before "next steps".
<KeyTakeaways
points={[
<>Interactive rebase rewrites commits; every rewritten commit gets a new object ID.</>,
<>The todo list is just a file — saving an empty one aborts the rebase.</>,
<>Anything you lose is in the reflog for at least 90 days.</>,
]}
/>
Commands and output
<Terminal>
Use it when: you show commands and their output together.
<Terminal
cwd="~/practice"
branch="feature/login"
commands={['git status --short', 'git add src/auth.js']}
output={`M src/auth.js
?? src/auth.test.js`}
/>
Why not a fenced code block: readers copy blocks whole, and a block containing both prompt and output pastes garbage into a shell. The copy button here yields only the commands.
Set fails when the command is supposed to fail:
<Terminal commands={['git push origin main']} output="! [rejected] main -> main (fetch first)" fails />
<CommandBlock>
Use it when: you are teaching the anatomy of a command rather than running it.
<CommandBlock
command="git push --force-with-lease origin feature/login"
summary="Replace the remote branch, but only if nobody else has pushed since you last fetched."
flags={[
{flag: '--force-with-lease', description: 'Refuse the push if the remote moved unexpectedly.'},
{flag: '--force', description: 'Overwrite unconditionally.', dangerous: true},
]}
warning={<>Never <code>--force</code> a branch other people have based work on.</>}
/>
<VersionNote>
Use it when: a claim is true only from a particular Git release.
<VersionNote since="2.23">
`git switch` and `git restore` split the overloaded responsibilities of
`git checkout`.
</VersionNote>
Version claims are the fastest-staling content in a Git curriculum. Marking them
up means pnpm content:stats can list every one of them for periodic re-checking.
Structure
<Steps> / <Step>
Use it when: a procedure has steps that each contain more than one paragraph.
<Steps>
<Step title="Create the branch">
Content, including code blocks and admonitions.
</Step>
<Step title="Make the change">
More content.
</Step>
</Steps>
An ordered Markdown list is correct for short steps. This component exists for the case where a step contains a code block and the list numbering collapses.
<Checkpoint>
Use it when: the reader's repository must be in a specific state before the next section makes sense.
<Checkpoint
verify="git log --oneline -3"
expect={<>Three commits, with <code>Add login form</code> at the top.</>}
ifNot={<>Run <code>git reflog</code> and reset to the entry before the rebase started.</>}
/>
This is the highest-value component in the library. A learner who silently diverges fails every subsequent step for reasons unrelated to the lesson.
<FileTree>
Use it when: showing directory structure.
<FileTree
root="my-project/"
tree={[
{name: '.git', type: 'directory', note: 'the repository itself'},
{name: 'src', type: 'directory', children: [{name: 'auth.js', highlight: true}]},
{name: 'README.md'},
]}
/>
ASCII box-drawing trees are unreadable on narrow screens and inaccessible to screen readers. Use this instead.
Diagrams
<GitGraph>
Use it when: the diagram needs HEAD markers, faded commits, per-node labels or precise lane control.
<GitGraph
caption="A feature branch rebased onto main"
branches={[{name: 'main'}, {name: 'feature'}]}
commits={[
{id: 'a1', branch: 'main', label: 'a1b2c3d'},
{id: 'a2', branch: 'main', parents: ['a1'], label: 'e4f5g6h'},
{id: 'f1', branch: 'feature', parents: ['a2'], label: 'i7j8k9l', head: true},
]}
/>
caption is required — it is the accessible name, and the component also emits
a text description of the graph for screen readers.
For a quick, unannotated history, Mermaid is enabled site-wide and is less work:
```mermaid
gitGraph
commit
branch feature
commit
checkout main
merge feature
```
Practice
<Exercise>
Use it when: always, at least one per lesson.
<Exercise
id="rebase-reorder"
title="Reorder two commits"
level="advanced"
duration={10}
hints={[
<>Start with <code>git rebase -i HEAD~3</code>.</>,
<>Reordering lines in the todo list reorders the commits.</>,
]}
solution={<>Move the <code>pick</code> line for the second commit above the first, save and exit.</>}
>
Given three commits, swap the order of the most recent two without changing
their messages.
</Exercise>
Hints come before solutions because a reader who reaches the answer from a nudge retains more than one who reads it.
<Quiz>
Use it when: a misconception is worth surfacing. One or two per lesson.
<Quiz
id="rebase-vs-merge"
question="What happens to the original commits after a successful rebase?"
options={[
{
text: 'They are deleted immediately.',
explanation: 'They become unreachable, but remain in the object database and the reflog.',
},
{
text: 'They remain, unreachable, until garbage collection.',
correct: true,
explanation: 'Exactly — which is why `git reflog` can always recover them.',
},
]}
/>
Every option needs an explanation, including the correct one. Explaining why a plausible wrong answer is wrong is usually the real lesson.
Navigation
<CardGrid>
Use it when: on module overview pages and the landing page. Not inside lessons.
<CardGrid
columns={3}
items={[
{badge: '01', title: 'Foundations', description: 'The mental model.', to: '/foundations', level: 'foundational'},
]}
/>
<Term>
Use it when: a Git term is used precisely for the first time in a module.
A <Term id="fast-forward">fast-forward</Term> merge only moves a pointer.
Definitions live in src/data/glossary.ts. An unknown id degrades to plain text
rather than failing the build, but validation reports it.
<Difficulty>
Use it when: rarely on its own — <LessonMeta>, <Exercise> and <CardGrid>
already render it. Standalone use is for comparison tables.
Adding a component
- Create
src/components/<Name>/index.tsxandstyles.module.css. - Export the component and its props type from
src/components/index.ts. - Register it in
src/theme/MDXComponents.tsx. - Document it here, including the "use it when" rule.
- Use only
--gm-*and--ifm-*CSS custom properties. No hard-coded colours.
Steps 2 and 3 are both required. Missing either means the component works in some files and not others.