name: add-step description: Add a new step to an existing Handzon tutorial. Reads the tutorial first to honor its gating, tone, and arc; confirms placement and components with the author; then scaffolds a populated step file and keeps _meta.json honest. triggers: ["add step", "new step", "next step", "append step", "insert step", "add a section"]
Use this when the author wants to add a step to an existing tutorial. If they're starting a new tutorial, use add-tutorial instead.
If the author already knows exactly what they want and just needs the file, point them at the shortcut at the bottom and stop.
1. Read the tutorial first
Before asking the author anything, gather context:
- Pick the tutorial. If the author didn't name one, list folders under
src/content/tutorials/(excluding_index.json) and ask which. - Load
<slug>/_meta.json. Note three things that change how you scaffold:gated: true→ every step must end with a completion item (<Quiz>or<Checkpoint>) before the<Recap>.difficulty→ sets the tone of the new step.estimatedDuration→ if present, you'll need to update it in step 5.
- List the existing steps (
ls <slug>/*.mdx) to see the arc and find the highest numeric prefix. - Read the most recent step to absorb the author's voice, the components they've been using, and what the reader has just done. Don't repeat that step — build on it.
2. Confirm purpose and placement (one question per turn)
Skip anything the author already volunteered. Ask the rest in order:
- Purpose — finish the sentence: "After this step, the reader can ___." One concrete capability. If they say "learn about X", push back once for the action verb.
- Placement — where does the step go?
- Append (most common) — next integer after the highest existing prefix.
- Insert between two steps — pick an unused prefix that sorts correctly. Prefixes are sortable strings (
02a-,02b-,025-all work between02-and03-). Prefer alphabetic suffixes (02a-) over renumbering. - Renumber existing steps — only if the author explicitly asks. Flag the cost (every existing step file gets renamed, URLs change, anyone who linked to a step breaks).
- Duration — 3, 5, or 10 min? Use this for the step's frontmatter and for the
_meta.json.estimatedDurationre-sum in section 5.
3. Match the step to components
Don't ship a prose-heavy step. Before writing the file, pick the components that fit what the step is doing. Common mappings:
- Showing project / folder structure →
<FileTree paths={[...]}>(not a code fence with slashes) - Showing a command and its output →
<Terminal entries={[{command, output}]}>(not a fenced bash block) - Variants (npm/pnpm/yarn, mac/linux/windows, SQLite/Postgres) →
<Tabs group="...">— reuse thegroupvalue the rest of the tutorial uses so the reader's selection persists - Code changes →
<Diff before={...} after={...}>(not two consecutive fences) - Optional solutions / spoilers →
<Hint>(collapsible) or<Reveal>(click-to-show) - Architecture / sequence / flow →
<Mermaid>or a```mermaidfence - Opening screenshot, walkthrough video, or slide deck →
heroMediain step frontmatter - Inline embeddable video or slide deck →
<Embed src="..."/>(addtype="slides"for a hosted deck like Google Slides or Speaker Deck); downloadable asset →<Download href="/downloads/..."/> - Runnable JS/TS →
<Playground>(v1: JS/TS only) - Knowledge check →
<Quiz id="<step-area>/<concept>">— useful mid-tutorial or when introducing a tricky concept - Inline "stuck?" escape hatch →
<HelpMe topic="..."/>— drop next to a specific hard spot (gnarly diff, tricky regex, opaque terminal output) when the tutorial has AI enabled. Don't put one at the end of every step — that'sautoStepHelpterritory (seeadd-helpme). - End-of-step summary →
<Recap items={[...]}/>— every step - Progress gate →
<Checkpoint id="<step-area>/<outcome>" label="..."/>— before the<Recap>when the step needs a concrete confirmation
The full prop signatures live in AGENTS.md under "MDX components".
Show the author your component picks for the step (one line) and confirm before scaffolding:
Step
04-deploy-to-render.mdx:<Tabs group="pkg">(same as previous steps),<Terminal>for the deploy command,<Checkpoint>(tutorial is gated),<Recap>.
4. Scaffold the step file
Slugify the step title (deploy-to-render, kebab-case). The filename is <NN>-<step-slug>.mdx in the tutorial folder. Verify the prefix doesn't already exist.
Write frontmatter and a useful skeleton — not just a <Callout>. Drop in empty instances of the components agreed in section 3 (only the ones for this step). Any prose you write (intro sentence, <Callout> body, <Recap> items) must follow the authoring-voice rules — no em dashes, no AI tells, second person, present tense. Strip the comment hints below before saving — they're guidance, not output:
About summary. It does double duty: the landing page uses it as a teaser and the AI assistant uses it when summarising prior steps in its context window. Write one sentence that names the concrete outcome, not the topic. Good: "Wire the form to a server action that writes to Postgres." Bad: "Learning about server actions."
---
title: <Step title>
duration: <e.g. 5 min>
summary: <One-line outcome; doubles as landing teaser and AI step context>
# Optional when the step should open with media:
# heroMedia:
# kind: image
# src: ./assets/example.png
# alt: Short description of the image
---
In this step you'll <one sentence describing the step's outcome>.
<Callout type="info">
<What the reader should have ready, or what they did in the previous step.>
</Callout>
## <First section heading>
{/* TODO(author): write the body of this step */}
{/* Drop in the components agreed in section 3, e.g.: */}
{/* <FileTree paths={[]} /> */}
{/* <Tabs group=""><Tab label="">…</Tab></Tabs> */}
{/* <Terminal entries={[{ command: "", output: "" }]} /> */}
{/* <Diff before={``} after={``} /> */}
{/* <Quiz id="<step-area>/<concept>" question="" options={[]} answer={0} explanation="" /> */}
<Checkpoint id="<step-area>/<outcome>" label="I did <thing>." />
<Recap items={[
"<bullet>",
"<bullet>",
]} />
Omit the <Checkpoint> line if the step is already gated by a quiz or does not need a concrete confirmation. Keep <Recap> always.
5. Keep _meta.json honest
If _meta.json.estimatedDuration is set, update it. Sum the duration values across all step frontmatters (including the new one) and round to a sensible value ("20 min", "45 min", "1 hr"). If the field isn't set, leave it alone — it's auto-summed at build time.
Do not touch title, description, tags, difficulty, or prerequisites here — that's not what add-step is for. If the new step changes the tutorial's overall scope, mention it and ask the author whether they want to update those fields separately.
6. Hand off
Tell the author exactly what to do next:
- Run
pnpm devand openhttp://localhost:4321/<tutorial-slug>/<step-slug>to see the scaffold. - Write the body, then replace the empty component placeholders with real content.
- Companion skills:
authoring-voice— Handzon's house voice rules. Invoke before writing the step's prose.add-quiz,add-checkpoint,add-playground,add-mermaid-diagram,add-helpme— for the components they picked.configure-ai-assistant— only if this step exposes a need to tune the tutor (different tone, disabled skill, etc.). Otherwise inherit the tutorial's existing_meta.json.ai.
- When the tutorial feels done, run
review-tutorial— the pre-publish checklist.
Don't
- Don't pick a numeric prefix that collides with an existing step. Verify with
lsbefore writing. - Don't forget a completion item (
<Quiz>or<Checkpoint>) when the tutorial isgated: true. Without one, the reader can advance without doing the work. - Don't ship prose-heavy steps. If a step has 3+ paragraphs of running text without a component, you're using the wrong tool — reach for
<FileTree>,<Diff>,<Terminal>,<Tabs>, or<Playground>. - Don't reach for a fenced code block when a component fits better. A bash fence with
$prompts should be<Terminal>; a list of file paths should be<FileTree>; before/after code should be<Diff>. - Don't
importMDX components — they're globally registered. - Don't renumber existing step files unless the author explicitly asks. Use an alphabetic suffix (
02a-) to insert between steps. - Don't change
_meta.jsonfields other thanestimatedDuration. Scope creep — use a separate edit for that. - Don't pick a
<Tabs group="...">value that disagrees with the rest of the tutorial. Selection persistence relies on a stable group key.
Shortcut
For authors who already know the step's purpose, placement, and components, run:
pnpm handzon:step
This prompts for the tutorial, title, and duration, then writes a minimal stub (frontmatter + <Callout> + <Recap>). The author then fills in components by hand or with add-quiz/add-checkpoint/etc. Use this path when the author explicitly says they don't need the planning step.