Write xmris documentation page

Create or edit tutorials, explainers, or contributor guides in xmris docs using MyST notebooks with live code cells.

Sby Skills Guide Bot
DocumentationIntermediate
007/26/2026
Claude Code
#documentation#myst#notebooks#tutorials#explainers

Recommended for


name: docs-page description: Create or edit any hand-authored page in the xmris docs — tutorial notebooks (docs/notebooks/), concept explainers (docs/explanation/), or contributor guides (docs/contributing/). Use when adding or restructuring a doc page, writing notebook tests for a function, documenting a new .xmr method, thinning or consolidating existing pages, or fixing a page that renders wrong.

Write an xmris docs page

All three hand-authored genres are MyST notebooks — jupytext frontmatter plus a kernelspec — so any of them can reach for live code-cells, real output and plots. What separates them is shape, reader, and where the cells are executed.

1. Route by genre — read one template, not all four

| | Tutorial | Explainer | Guide | |---|---|---|---| | Lives in | docs/notebooks/<area>/ | docs/explanation/ | docs/contributing/ | | Reader wants | to do the task | to know why it is like this | to contribute | | Shape | demonstrate → assert, step by step | motivated narrative, claim → live proof | numbered steps + commands | | uv run test (nbmake + coverage) | ✅ | ✅ | ❌ | | myst build --execute (deploy.yml, on PRs) | ✅ | ✅ | ✅ | | Template | templates/tutorial.md | templates/explainer.md | templates/guide.md |

templates/patterns.md is the shared MyST pattern library — read it alongside whichever genre template applies. It holds the devices mined from the pages that work, each pointing at its live example so you copy rather than reinvent.

Two paths never route here:

  • docs/diary/ belongs to the dev-diary skill. Hand off; do not write an entry from here. (check_docs.py still checks entries — the structural rules in §2 bind every page in the tree.)
  • docs/api_reference/ is generated and gitignored. docs_api() clears the directory before regenerating, so a hand edit there is destroyed with no git history to recover it. Fix the docstring in src/ instead.

House style — motivated narrative, one home per concept, every article stands alone, the MyST palette carries the argument — lives in CLAUDE.md § "Documentation style" and is not restated here. One carve-out: the motivated narrative rule binds explainers and tutorials, not guides. A numbered list of commands is the correct shape for setup.md; novelizing an install guide makes it worse.

2. Rules that survive genre

Every one of these is enforced by check_docs.py, which the Docs style CI job runs over the whole tree on every PR. The build is silent about all of them; the gate is not. The tree is at zero errors — do not be the change that reopens the backlog.

  • Frontmatter is exact, and display_name: Python 3 (xmris) is the frozen project label. If your local Jupyter rewrites it (to .venv, Python 3 (ipykernel), …), fix it back before committing. Execution is unaffected either way; name: python3 resolves to the uv venv.
  • Nothing before (target)= + # H1. mystmd lifts the first heading into the page title but only removes it from the body when it leads the page. Put anything first — even a hidden remove-cell — and the title renders twice. The setup cell always comes after the H1. Exactly one H1 per file; never restate the title as another header.
  • Explicit MyST target above every header (Commandment 8), kebab-case, prefixed with the page topic. Auto-generated slugs are numbered by document positionid-1-, id-2- — so inserting one section silently renumbers every anchor below it and breaks deep links.
  • Never link .ipynb. myst.yml excludes notebooks/**/*.ipynb, so the link resolves to null and dies — with no build warning. Use [text](#explicit-target) or a relative .md path.
  • A new doi.org link must be frozen into docs/myst.doi.bib (cd docs && uv run myst build --doi-bib, then commit it). mystmd resolves DOI links against the network at build time, so an unfrozen one makes the build fail whenever a runner's lookup is rate-limited — on somebody else's pull request. Link text is irrelevant; [paper](https://doi.org/…) is resolved just like [](…).
  • TOC entry in docs/myst.yml is mandatory (except testonly_). The sidebar shows the TOC title — keep it consistent with the H1. A page missing from the TOC never renders.
  • Reader-facing cells use plain strings ("time", "frequency") — the low entrance barrier is deliberate. ATTRS/DIMS/COORDS appear only in hidden test cells or in passages explicitly addressed to contributors.
  • Commit only the .md. docs/**/*.ipynb is gitignored; edits made in an .ipynb twin are invisible to both tests and docs until synced back (uv run jupytext --sync <file>).

Tone across all three: conversational, sharp, concise, no filler — but never assuming expertise. Background an expert would skip goes in a :::{dropdown}, off the main line.

3. Editing an existing page

Most doc work is editing, and the house rules make thinning expected work, not scope creep.

  • Run the checker on the page before you start. It should already be at zero errors; if it is not, you inherited a broken page and CI will blame your PR for it — fix it and say so.
  • Every header already carries a target, so the live risk is renaming one: targets are page-global in MyST, and a rename breaks every deep link to it. Grep first — git grep -nF "#old-slug" -- docs — and prefer adding a new section over re-keying an old one.
  • Consolidating across pages is the one home per concept rule doing its job. Say what you moved in the PR body, and keep the orienting recap on the page you thinned.

4. Verify before finishing

uv run python .claude/skills/docs-page/check_docs.py docs/<path>/<page>.md

Errors are render-breaking and exit 1 — the same exit code the Docs style CI job gates on, so this run is the gate, locally. Warnings are drift and exit 0. Then, for a tutorial or an explainertest-gen walks docs/notebooks/ and docs/explanation/, so both are in the pytest suite:

uv run test-gen
uv run pytest "tests/autogen_notebooks/<category>/<name>.ipynb" -n0 --no-cov
# explainers land flat under explanation/:
uv run pytest "tests/autogen_notebooks/explanation/<name>.ipynb" -n0 --no-cov

(--nbmake is already in pytest addopts.) A page only joins that suite once it carries a jupytext kernelspec — that is the exact condition _is_executable_page tests, so a frontmatter-less page is skipped rather than failing with no kernel to start.

Guide cells are executed by the docs build only — cd docs && uv run myst build --html --execute locally, the same command deploy.yml runs on every PR. A guide that pulls in an external file (the per-skill Contribute pages quote each SKILL.md this way — a literalinclude with :filename: as the label and :class: skill-quote) is re-read on every build, so the quoted content is always current; a missing or renamed path surfaces as a ⛔️ error and hard-fails myst build --strict. (uv run docs and myst start serve a live preview and never exit; they are for reading the site, not for checking it.)

Two pathspec traps, both of which produced wrong answers while auditing this repo:

  • git grep … -- 'docs/**/*.md' silently skips docs/index.md — no intermediate directory. Use -- docs.
  • grep -r docs/ walks ~9,800 gitignored _build/ files carrying stale copies of everything.

Checklist

<!-- excerpt:start -->
  • [ ] Genre identified; the matching template and patterns.md read
  • [ ] Frontmatter exact, display_name: Python 3 (xmris)
  • [ ] (target)= + single H1 is the very first content; a target above every header
  • [ ] Reader-facing cells use plain dim strings; config singletons only in hidden cells
  • [ ] Synthetic MRS data comes from simulate_fid; tutorials open with the functions-used table
  • [ ] TOC entry in docs/myst.yml (unless testonly_); no .ipynb links
  • [ ] New doi.org link frozen into docs/myst.doi.bib (myst build --doi-bib) and committed
  • [ ] check_docs.py passes on the page (0 errors)
  • [ ] Tutorial only: single-notebook nbmake run is green
  • [ ] Only the .md staged
<!-- excerpt:end -->
Related skills