From b7e450bb9cf9bd6a4398ed96d274da3ef5d3f7b3 Mon Sep 17 00:00:00 2001 From: Guillaume Tauzin <4648633+gtauzin@users.noreply.github.com> Date: Sun, 29 Mar 2026 11:58:53 +0200 Subject: [PATCH] feat(template): group example gallery by Diataxis category - Add category field to gallery metadata and group by tutorial/how-to - Extract _build_gallery_cards helper and reuse in API examples - Update examples page intro to describe grouped notebooks - Update contribute.md notebook structure guidelines - Create diataxis-notebook-writer skill with tutorial/how-to patterns - Add companion notebook sections to tutorial and howto writer skills - Add notebook classification to docs planner skill Backported from stateful-y/sklearn-optuna#21 (91268db) --- .github/skills/diataxis-docs-planner/SKILL.md | 2 + .github/skills/diataxis-howto-writer/SKILL.md | 12 ++ .../skills/diataxis-notebook-writer/SKILL.md | 68 +++++++++ .../references/howto-notebook.md | 121 ++++++++++++++++ .../references/tutorial-notebook.md | 129 ++++++++++++++++++ .../skills/diataxis-tutorial-writer/SKILL.md | 12 ++ .../skills/diataxis-docs-planner/SKILL.md | 2 + .../skills/diataxis-howto-writer/SKILL.md | 12 ++ .../skills/diataxis-notebook-writer/SKILL.md | 68 +++++++++ .../references/howto-notebook.md | 121 ++++++++++++++++ .../references/tutorial-notebook.md | 129 ++++++++++++++++++ .../skills/diataxis-tutorial-writer/SKILL.md | 12 ++ template/docs/hooks.py.jinja | 54 +++++--- .../docs/pages/how-to/contribute.md.jinja | 54 +++++--- ...de_examples %}examples.md{% endif %}.jinja | 2 +- .../hello.py.jinja | 1 + tests/test_docs_content.py | 11 ++ tests/test_propagated_features.py | 11 ++ 18 files changed, 780 insertions(+), 41 deletions(-) create mode 100644 .github/skills/diataxis-notebook-writer/SKILL.md create mode 100644 .github/skills/diataxis-notebook-writer/references/howto-notebook.md create mode 100644 .github/skills/diataxis-notebook-writer/references/tutorial-notebook.md create mode 100644 template/.github/skills/diataxis-notebook-writer/SKILL.md create mode 100644 template/.github/skills/diataxis-notebook-writer/references/howto-notebook.md create mode 100644 template/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md diff --git a/.github/skills/diataxis-docs-planner/SKILL.md b/.github/skills/diataxis-docs-planner/SKILL.md index 87f5828..729f8cc 100644 --- a/.github/skills/diataxis-docs-planner/SKILL.md +++ b/.github/skills/diataxis-docs-planner/SKILL.md @@ -49,6 +49,7 @@ Read all files in `docs/` and classify each page by quadrant using the compass: - For each page, note: file path, current title, actual quadrant, intended quadrant - Flag pages that mix quadrants (e.g., a "getting started" that is half tutorial, half reference) - Flag pages that are misclassified (e.g., an "explanation" page that is really a how-to) +- Check `examples/` for marimo notebooks: classify each by quadrant using its `__gallery__` metadata `category` field and verify it matches the notebook content ### Step 3: Identify Gaps @@ -89,6 +90,7 @@ Output a structured documentation plan: - How-to pages → `diataxis-howto-writer` - Reference pages → `diataxis-reference-writer` - Explanation pages → `diataxis-explanation-writer` + - Companion notebooks → `diataxis-notebook-writer` ## MkDocs Nav Patterns diff --git a/.github/skills/diataxis-howto-writer/SKILL.md b/.github/skills/diataxis-howto-writer/SKILL.md index 99d3c51..3daed51 100644 --- a/.github/skills/diataxis-howto-writer/SKILL.md +++ b/.github/skills/diataxis-howto-writer/SKILL.md @@ -184,3 +184,15 @@ A tutorial teaches general skills through a specific exercise. A how-to guide he - **Tool-centric framing** — "How to use the X class" is not addressed to a human need - **Missing conditionals** — Real-world tasks branch; acknowledge this with if/then guidance - **Burying the action** — Lead with what to do, not why + +## Companion Notebooks + +How-to doc pages can have an interactive companion notebook (marimo). When one exists, add a callout after the title: + +```markdown +!!! tip "Interactive notebook" + See the companion notebook for a runnable example. + [View](/examples/slug/) · [Open in marimo](/examples/slug/edit/) +``` + +Use the `diataxis-notebook-writer` skill when creating or editing the companion notebook itself. diff --git a/.github/skills/diataxis-notebook-writer/SKILL.md b/.github/skills/diataxis-notebook-writer/SKILL.md new file mode 100644 index 0000000..66ab803 --- /dev/null +++ b/.github/skills/diataxis-notebook-writer/SKILL.md @@ -0,0 +1,68 @@ +--- +name: diataxis-notebook-writer +description: Write or rework marimo example notebooks following Diataxis principles. Use when asked to create, edit, or rework interactive notebook examples that serve as tutorial or how-to companions to documentation pages. Triggers on "write a notebook example", "rework notebook", "example notebook", "interactive example", "marimo example", "tutorial notebook", "how-to notebook". +--- + +# Diataxis Notebook Writer + +Write marimo notebook examples that follow Diataxis quadrant conventions for voice, structure, and content boundaries. + +Notebooks serve only **tutorials** and **how-to guides** - never explanation or reference. Explanation belongs in markdown pages read away from the keyboard. Reference mirrors code structure, not user tasks. + +## Quadrant Decision + +Ask two questions to classify the notebook: + +1. Does it teach a beginner by guiding them through a learning experience? -> **Tutorial** +2. Does it help a competent user accomplish a specific real-world task? -> **How-to** + +If it does neither (conceptual discussion, API description), it should not be a notebook. + +## File Placement and Metadata + +Place notebooks in `examples/`. Every notebook must define `__gallery__` metadata: + +```python +__gallery__ = { + "title": "How to Stop Optimization Early with Callbacks", # goal-oriented for how-to + "description": "Stop unneeded work early by adding Optuna callbacks to your search.", + "category": "how-to", # "tutorial" or "how-to" + "companion": "pages/how-to/use-callbacks.md", # optional: path to companion doc page +} +``` + +**Title conventions:** +- Tutorial: descriptive noun phrase - "OptunaSearchCV Quickstart" +- How-to: "How to [verb]..." - "How to Stop Optimization Early with Callbacks" + +## Notebook Cell Structure + +Both quadrants use **hidden setup cells** (`hide_code=True`) for imports and markdown narrative, with visible code cells for the actions the reader should focus on. + +**For quadrant-specific cell patterns, voice, and templates:** +- **Tutorial notebooks**: Read [references/tutorial-notebook.md](references/tutorial-notebook.md) +- **How-to notebooks**: Read [references/howto-notebook.md](references/howto-notebook.md) + +## Companion Doc Page Pattern + +When a notebook has a companion markdown page, add this admonition near the top of the doc page (after any prerequisites): + +```markdown +!!! tip "Interactive version available" + Try this guide as an interactive notebook: + [View](/examples/callbacks/) · [Open in marimo](/examples/callbacks/edit/) +``` + +## Common Anti-Patterns + +- **One-size-fits-all structure**: Using "What You'll Learn" + "Key Takeaways" in every notebook regardless of quadrant +- **Embedded explanation in how-to**: "Class imbalance is common because..." belongs in an explanation page, not a how-to notebook +- **Design reasoning in how-to**: "We set refit=False because the outer search doesn't need..." - just say "Set `refit=False`" +- **Tool-centric titles**: "Callbacks" instead of "How to Stop Optimization Early with Callbacks" +- **Tutorial language in how-to**: "What You'll Learn" presumes a learning orientation; how-to readers already know what they want + +## Related Skills + +- `diataxis-tutorial-writer` - for companion markdown tutorial pages +- `diataxis-howto-writer` - for companion markdown how-to pages +- `marimo-notebook` - for marimo format mechanics (cell syntax, reactivity, script mode) diff --git a/.github/skills/diataxis-notebook-writer/references/howto-notebook.md b/.github/skills/diataxis-notebook-writer/references/howto-notebook.md new file mode 100644 index 0000000..1eca0ea --- /dev/null +++ b/.github/skills/diataxis-notebook-writer/references/howto-notebook.md @@ -0,0 +1,121 @@ +# How-to Notebook Patterns + +Cell patterns for marimo notebooks classified as `"category": "how-to"` in `__gallery__`. + +A how-to notebook is a **recipe**. The reader already knows what they want to accomplish and needs practical directions to get there. The notebook lets them adapt the recipe to their real-world case. + +## Voice + +Use imperative and conditional language. Address the reader directly when needed, but focus on actions. + +- "This notebook shows how to stop optimization early using Optuna callbacks." +- "Wrap Optuna's `MaxTrialsCallback` using the `Callback` wrapper." +- "If you need multiple stopping criteria, pass a dictionary of callbacks." + +Never use "What You'll Learn" - the reader already knows what they want to achieve. + +## Cell Structure + +### Title cell (hidden, first narrative cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + # How to Stop Optimization Early with Callbacks + + This notebook shows how to stop optimization early by + adding Optuna callbacks to `OptunaSearchCV`. + + **Prerequisites:** Familiarity with the + OptunaSearchCV quickstart + ([View](/examples/quickstart/) · [Open in marimo](/examples/quickstart/edit/)). + """ + ) +``` + +Key points: +- Title starts with "How to [verb]..." +- One-sentence description of the goal +- Prerequisites as a single line linking to prior knowledge + +### Step cells (hidden, between code cells) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 1. Wrap the Callback + + Wrap Optuna's `MaxTrialsCallback` with the `Callback` + wrapper for sklearn compatibility. + """ + ) +``` + +Key points: +- Numbered steps with action verbs +- One to two sentences max - what to do, not why +- No conceptual explanation; link to explanation page if context is needed + +### Verification cells (hidden, after result) + +```python +@app.cell(hide_code=True) +def _(mo, n_trials_run): + mo.md( + f""" + Requested trials: 20 + Actual trials run: {n_trials_run} + """ + ) +``` + +Key points: +- Show the result that proves the task succeeded +- No interpretation beyond the facts + +### Conditional guidance (when variations exist) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 3. Multiple Callbacks + + If you need multiple stopping criteria, pass a dictionary + of callbacks. Each callback is invoked at the end of every trial. + """ + ) +``` + +Key points: +- "If you need X, do Y" - conditional imperatives +- Present variations as branches the user can follow or skip +- Don't explain why they might need it + +### No closing summary + +How-to notebooks end after the final verification step. Do not add: +- "Key Takeaways" sections +- "What We Learned" summaries +- "Next Steps" sections (these are optional; include only if directly relevant) + +The task is done. The reader moves on. + +## Principles Checklist + +- [ ] Title is "How to [verb]..." - goal-oriented +- [ ] `__gallery__` title matches the goal format +- [ ] No "What You'll Learn" section +- [ ] No "Key Takeaways" or summary section +- [ ] Markdown cells contain only directional action prose +- [ ] No embedded explanation - link out for "why" content +- [ ] No design reasoning - just show what to do +- [ ] Conditional imperatives for variations ("If you need X, do Y") +- [ ] Verification step shows the task succeeded +- [ ] Numbered steps for clear progression +- [ ] Assumes competence from prerequisites diff --git a/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md b/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md new file mode 100644 index 0000000..38c48fd --- /dev/null +++ b/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md @@ -0,0 +1,129 @@ +# Tutorial Notebook Patterns + +Cell patterns for marimo notebooks classified as `"category": "tutorial"` in `__gallery__`. + +A tutorial notebook is a **lesson**. The reader acquires skills through guided hands-on practice. The notebook is the classroom - every cell produces visible output the learner can verify. + +## Voice + +Use first-person plural throughout: **"we"**, **"our"**, **"let's"**. + +- "We create a classification dataset" +- "Now we define the search space" +- "Let's run the search and inspect the results" + +Never use "you will learn" - that is presumptuous. Use "we will [do concrete thing]" instead. + +## Cell Structure + +### Title cell (hidden, first narrative cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + # OptunaSearchCV Quickstart + + In this notebook, we will run a hyperparameter search using + `OptunaSearchCV` and inspect the best parameters and score. + Along the way, we will define search spaces with Optuna + distributions and see how the results API works. + + **Prerequisites:** Basic familiarity with scikit-learn's + fit/predict API. + """ + ) +``` + +Key points: +- State what **we will do**, not what "you will learn" +- Mention concrete outcomes, not abstract learning objectives +- Prerequisites in a single line, not a bulleted list + +### Section cells (hidden, between code cells) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 1. Prepare Data and Estimator + + We start by creating a classification dataset and + initializing a LogisticRegression estimator. + """ + ) +``` + +Key points: +- Number the sections for clear progression +- One sentence of context - what we do, not why +- No explanation of concepts - link to explanation page if needed + +### Observation cells (hidden, after code output) + +```python +@app.cell(hide_code=True) +def _(mo, search): + mo.md( + f""" + **Best params:** {search.best_params_} + **Best score:** {search.best_score_:.3f} + + Notice that `best_params_` returns the same format as + scikit-learn's `GridSearchCV`. The score is the mean + cross-validated score from the best trial. + """ + ) +``` + +Key points: +- Show exact expected output +- "Notice that..." closes the learning loop +- One sentence of observation, not a paragraph of explanation + +### Closing cell (hidden, final cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## What We Built + + We ran a hyperparameter search with `OptunaSearchCV` and found + the best regularization parameter for a LogisticRegression. Along + the way, we: + + - Defined a search space with `FloatDistribution` + - Ran the search with `OptunaSearchCV.fit()` + - Inspected `best_params_` and `best_score_` + + **Next steps:** + + - How to resume optimization from prior trials: + [View](/examples/study_management/) · [Open in marimo](/examples/study_management/edit/) + - How to stop optimization early with callbacks: + [View](/examples/callbacks/) · [Open in marimo](/examples/callbacks/edit/) + """ + ) +``` + +Key points: +- "What We Built" - celebrate accomplishment, don't summarize theory +- Brief bullet list of concrete things done, not concepts learned +- Link to how-to notebooks, not more tutorials + +## Principles Checklist + +- [ ] Every code cell produces visible output (no silent cells) +- [ ] "We" language throughout, never "you will learn" +- [ ] Title says what we will do, not what you will learn +- [ ] "Notice that..." observations after key outputs +- [ ] One-sentence max explanation per concept; link out for depth +- [ ] Single path - no branching, no CategoricalDistribution choices unless essential +- [ ] All code cells are re-runnable with deterministic results +- [ ] Ends with "What We Built", not "Key Takeaways" +- [ ] Numbered sections guide sequential progression +- [ ] No options or alternatives - just one clear path diff --git a/.github/skills/diataxis-tutorial-writer/SKILL.md b/.github/skills/diataxis-tutorial-writer/SKILL.md index fca6780..fc96d80 100644 --- a/.github/skills/diataxis-tutorial-writer/SKILL.md +++ b/.github/skills/diataxis-tutorial-writer/SKILL.md @@ -206,3 +206,15 @@ You have [accomplished concrete thing]. Along the way, you: - Not a reference (describes machinery, doesn't guide action) - Not an explanation (discusses topics, doesn't guide action) - Not "the basics" — tutorials can be advanced; the distinction is study vs. work + +## Companion Notebooks + +Tutorial doc pages can have an interactive companion notebook (marimo). When one exists, add a callout after the title: + +```markdown +!!! tip "Interactive notebook" + Follow along in the Quickstart notebook for a hands-on version of this tutorial. + [View](/examples/slug/) · [Open in marimo](/examples/slug/edit/) +``` + +Use the `diataxis-notebook-writer` skill when creating or editing the companion notebook itself. diff --git a/template/.github/skills/diataxis-docs-planner/SKILL.md b/template/.github/skills/diataxis-docs-planner/SKILL.md index 87f5828..729f8cc 100644 --- a/template/.github/skills/diataxis-docs-planner/SKILL.md +++ b/template/.github/skills/diataxis-docs-planner/SKILL.md @@ -49,6 +49,7 @@ Read all files in `docs/` and classify each page by quadrant using the compass: - For each page, note: file path, current title, actual quadrant, intended quadrant - Flag pages that mix quadrants (e.g., a "getting started" that is half tutorial, half reference) - Flag pages that are misclassified (e.g., an "explanation" page that is really a how-to) +- Check `examples/` for marimo notebooks: classify each by quadrant using its `__gallery__` metadata `category` field and verify it matches the notebook content ### Step 3: Identify Gaps @@ -89,6 +90,7 @@ Output a structured documentation plan: - How-to pages → `diataxis-howto-writer` - Reference pages → `diataxis-reference-writer` - Explanation pages → `diataxis-explanation-writer` + - Companion notebooks → `diataxis-notebook-writer` ## MkDocs Nav Patterns diff --git a/template/.github/skills/diataxis-howto-writer/SKILL.md b/template/.github/skills/diataxis-howto-writer/SKILL.md index 99d3c51..3daed51 100644 --- a/template/.github/skills/diataxis-howto-writer/SKILL.md +++ b/template/.github/skills/diataxis-howto-writer/SKILL.md @@ -184,3 +184,15 @@ A tutorial teaches general skills through a specific exercise. A how-to guide he - **Tool-centric framing** — "How to use the X class" is not addressed to a human need - **Missing conditionals** — Real-world tasks branch; acknowledge this with if/then guidance - **Burying the action** — Lead with what to do, not why + +## Companion Notebooks + +How-to doc pages can have an interactive companion notebook (marimo). When one exists, add a callout after the title: + +```markdown +!!! tip "Interactive notebook" + See the companion notebook for a runnable example. + [View](/examples/slug/) · [Open in marimo](/examples/slug/edit/) +``` + +Use the `diataxis-notebook-writer` skill when creating or editing the companion notebook itself. diff --git a/template/.github/skills/diataxis-notebook-writer/SKILL.md b/template/.github/skills/diataxis-notebook-writer/SKILL.md new file mode 100644 index 0000000..66ab803 --- /dev/null +++ b/template/.github/skills/diataxis-notebook-writer/SKILL.md @@ -0,0 +1,68 @@ +--- +name: diataxis-notebook-writer +description: Write or rework marimo example notebooks following Diataxis principles. Use when asked to create, edit, or rework interactive notebook examples that serve as tutorial or how-to companions to documentation pages. Triggers on "write a notebook example", "rework notebook", "example notebook", "interactive example", "marimo example", "tutorial notebook", "how-to notebook". +--- + +# Diataxis Notebook Writer + +Write marimo notebook examples that follow Diataxis quadrant conventions for voice, structure, and content boundaries. + +Notebooks serve only **tutorials** and **how-to guides** - never explanation or reference. Explanation belongs in markdown pages read away from the keyboard. Reference mirrors code structure, not user tasks. + +## Quadrant Decision + +Ask two questions to classify the notebook: + +1. Does it teach a beginner by guiding them through a learning experience? -> **Tutorial** +2. Does it help a competent user accomplish a specific real-world task? -> **How-to** + +If it does neither (conceptual discussion, API description), it should not be a notebook. + +## File Placement and Metadata + +Place notebooks in `examples/`. Every notebook must define `__gallery__` metadata: + +```python +__gallery__ = { + "title": "How to Stop Optimization Early with Callbacks", # goal-oriented for how-to + "description": "Stop unneeded work early by adding Optuna callbacks to your search.", + "category": "how-to", # "tutorial" or "how-to" + "companion": "pages/how-to/use-callbacks.md", # optional: path to companion doc page +} +``` + +**Title conventions:** +- Tutorial: descriptive noun phrase - "OptunaSearchCV Quickstart" +- How-to: "How to [verb]..." - "How to Stop Optimization Early with Callbacks" + +## Notebook Cell Structure + +Both quadrants use **hidden setup cells** (`hide_code=True`) for imports and markdown narrative, with visible code cells for the actions the reader should focus on. + +**For quadrant-specific cell patterns, voice, and templates:** +- **Tutorial notebooks**: Read [references/tutorial-notebook.md](references/tutorial-notebook.md) +- **How-to notebooks**: Read [references/howto-notebook.md](references/howto-notebook.md) + +## Companion Doc Page Pattern + +When a notebook has a companion markdown page, add this admonition near the top of the doc page (after any prerequisites): + +```markdown +!!! tip "Interactive version available" + Try this guide as an interactive notebook: + [View](/examples/callbacks/) · [Open in marimo](/examples/callbacks/edit/) +``` + +## Common Anti-Patterns + +- **One-size-fits-all structure**: Using "What You'll Learn" + "Key Takeaways" in every notebook regardless of quadrant +- **Embedded explanation in how-to**: "Class imbalance is common because..." belongs in an explanation page, not a how-to notebook +- **Design reasoning in how-to**: "We set refit=False because the outer search doesn't need..." - just say "Set `refit=False`" +- **Tool-centric titles**: "Callbacks" instead of "How to Stop Optimization Early with Callbacks" +- **Tutorial language in how-to**: "What You'll Learn" presumes a learning orientation; how-to readers already know what they want + +## Related Skills + +- `diataxis-tutorial-writer` - for companion markdown tutorial pages +- `diataxis-howto-writer` - for companion markdown how-to pages +- `marimo-notebook` - for marimo format mechanics (cell syntax, reactivity, script mode) diff --git a/template/.github/skills/diataxis-notebook-writer/references/howto-notebook.md b/template/.github/skills/diataxis-notebook-writer/references/howto-notebook.md new file mode 100644 index 0000000..1eca0ea --- /dev/null +++ b/template/.github/skills/diataxis-notebook-writer/references/howto-notebook.md @@ -0,0 +1,121 @@ +# How-to Notebook Patterns + +Cell patterns for marimo notebooks classified as `"category": "how-to"` in `__gallery__`. + +A how-to notebook is a **recipe**. The reader already knows what they want to accomplish and needs practical directions to get there. The notebook lets them adapt the recipe to their real-world case. + +## Voice + +Use imperative and conditional language. Address the reader directly when needed, but focus on actions. + +- "This notebook shows how to stop optimization early using Optuna callbacks." +- "Wrap Optuna's `MaxTrialsCallback` using the `Callback` wrapper." +- "If you need multiple stopping criteria, pass a dictionary of callbacks." + +Never use "What You'll Learn" - the reader already knows what they want to achieve. + +## Cell Structure + +### Title cell (hidden, first narrative cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + # How to Stop Optimization Early with Callbacks + + This notebook shows how to stop optimization early by + adding Optuna callbacks to `OptunaSearchCV`. + + **Prerequisites:** Familiarity with the + OptunaSearchCV quickstart + ([View](/examples/quickstart/) · [Open in marimo](/examples/quickstart/edit/)). + """ + ) +``` + +Key points: +- Title starts with "How to [verb]..." +- One-sentence description of the goal +- Prerequisites as a single line linking to prior knowledge + +### Step cells (hidden, between code cells) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 1. Wrap the Callback + + Wrap Optuna's `MaxTrialsCallback` with the `Callback` + wrapper for sklearn compatibility. + """ + ) +``` + +Key points: +- Numbered steps with action verbs +- One to two sentences max - what to do, not why +- No conceptual explanation; link to explanation page if context is needed + +### Verification cells (hidden, after result) + +```python +@app.cell(hide_code=True) +def _(mo, n_trials_run): + mo.md( + f""" + Requested trials: 20 + Actual trials run: {n_trials_run} + """ + ) +``` + +Key points: +- Show the result that proves the task succeeded +- No interpretation beyond the facts + +### Conditional guidance (when variations exist) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 3. Multiple Callbacks + + If you need multiple stopping criteria, pass a dictionary + of callbacks. Each callback is invoked at the end of every trial. + """ + ) +``` + +Key points: +- "If you need X, do Y" - conditional imperatives +- Present variations as branches the user can follow or skip +- Don't explain why they might need it + +### No closing summary + +How-to notebooks end after the final verification step. Do not add: +- "Key Takeaways" sections +- "What We Learned" summaries +- "Next Steps" sections (these are optional; include only if directly relevant) + +The task is done. The reader moves on. + +## Principles Checklist + +- [ ] Title is "How to [verb]..." - goal-oriented +- [ ] `__gallery__` title matches the goal format +- [ ] No "What You'll Learn" section +- [ ] No "Key Takeaways" or summary section +- [ ] Markdown cells contain only directional action prose +- [ ] No embedded explanation - link out for "why" content +- [ ] No design reasoning - just show what to do +- [ ] Conditional imperatives for variations ("If you need X, do Y") +- [ ] Verification step shows the task succeeded +- [ ] Numbered steps for clear progression +- [ ] Assumes competence from prerequisites diff --git a/template/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md b/template/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md new file mode 100644 index 0000000..38c48fd --- /dev/null +++ b/template/.github/skills/diataxis-notebook-writer/references/tutorial-notebook.md @@ -0,0 +1,129 @@ +# Tutorial Notebook Patterns + +Cell patterns for marimo notebooks classified as `"category": "tutorial"` in `__gallery__`. + +A tutorial notebook is a **lesson**. The reader acquires skills through guided hands-on practice. The notebook is the classroom - every cell produces visible output the learner can verify. + +## Voice + +Use first-person plural throughout: **"we"**, **"our"**, **"let's"**. + +- "We create a classification dataset" +- "Now we define the search space" +- "Let's run the search and inspect the results" + +Never use "you will learn" - that is presumptuous. Use "we will [do concrete thing]" instead. + +## Cell Structure + +### Title cell (hidden, first narrative cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + # OptunaSearchCV Quickstart + + In this notebook, we will run a hyperparameter search using + `OptunaSearchCV` and inspect the best parameters and score. + Along the way, we will define search spaces with Optuna + distributions and see how the results API works. + + **Prerequisites:** Basic familiarity with scikit-learn's + fit/predict API. + """ + ) +``` + +Key points: +- State what **we will do**, not what "you will learn" +- Mention concrete outcomes, not abstract learning objectives +- Prerequisites in a single line, not a bulleted list + +### Section cells (hidden, between code cells) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## 1. Prepare Data and Estimator + + We start by creating a classification dataset and + initializing a LogisticRegression estimator. + """ + ) +``` + +Key points: +- Number the sections for clear progression +- One sentence of context - what we do, not why +- No explanation of concepts - link to explanation page if needed + +### Observation cells (hidden, after code output) + +```python +@app.cell(hide_code=True) +def _(mo, search): + mo.md( + f""" + **Best params:** {search.best_params_} + **Best score:** {search.best_score_:.3f} + + Notice that `best_params_` returns the same format as + scikit-learn's `GridSearchCV`. The score is the mean + cross-validated score from the best trial. + """ + ) +``` + +Key points: +- Show exact expected output +- "Notice that..." closes the learning loop +- One sentence of observation, not a paragraph of explanation + +### Closing cell (hidden, final cell) + +```python +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + ## What We Built + + We ran a hyperparameter search with `OptunaSearchCV` and found + the best regularization parameter for a LogisticRegression. Along + the way, we: + + - Defined a search space with `FloatDistribution` + - Ran the search with `OptunaSearchCV.fit()` + - Inspected `best_params_` and `best_score_` + + **Next steps:** + + - How to resume optimization from prior trials: + [View](/examples/study_management/) · [Open in marimo](/examples/study_management/edit/) + - How to stop optimization early with callbacks: + [View](/examples/callbacks/) · [Open in marimo](/examples/callbacks/edit/) + """ + ) +``` + +Key points: +- "What We Built" - celebrate accomplishment, don't summarize theory +- Brief bullet list of concrete things done, not concepts learned +- Link to how-to notebooks, not more tutorials + +## Principles Checklist + +- [ ] Every code cell produces visible output (no silent cells) +- [ ] "We" language throughout, never "you will learn" +- [ ] Title says what we will do, not what you will learn +- [ ] "Notice that..." observations after key outputs +- [ ] One-sentence max explanation per concept; link out for depth +- [ ] Single path - no branching, no CategoricalDistribution choices unless essential +- [ ] All code cells are re-runnable with deterministic results +- [ ] Ends with "What We Built", not "Key Takeaways" +- [ ] Numbered sections guide sequential progression +- [ ] No options or alternatives - just one clear path diff --git a/template/.github/skills/diataxis-tutorial-writer/SKILL.md b/template/.github/skills/diataxis-tutorial-writer/SKILL.md index fca6780..fc96d80 100644 --- a/template/.github/skills/diataxis-tutorial-writer/SKILL.md +++ b/template/.github/skills/diataxis-tutorial-writer/SKILL.md @@ -206,3 +206,15 @@ You have [accomplished concrete thing]. Along the way, you: - Not a reference (describes machinery, doesn't guide action) - Not an explanation (discusses topics, doesn't guide action) - Not "the basics" — tutorials can be advanced; the distinction is study vs. work + +## Companion Notebooks + +Tutorial doc pages can have an interactive companion notebook (marimo). When one exists, add a callout after the title: + +```markdown +!!! tip "Interactive notebook" + Follow along in the Quickstart notebook for a hands-on version of this tutorial. + [View](/examples/slug/) · [Open in marimo](/examples/slug/edit/) +``` + +Use the `diataxis-notebook-writer` skill when creating or editing the companion notebook itself. diff --git a/template/docs/hooks.py.jinja b/template/docs/hooks.py.jinja index 0f66cd2..1fb03bf 100644 --- a/template/docs/hooks.py.jinja +++ b/template/docs/hooks.py.jinja @@ -359,6 +359,7 @@ def _get_gallery_items(project_root): items.append({ "title": gallery.get("title", stem.replace("_", " ").title()), "description": gallery.get("description", ""), + "category": gallery.get("category", ""), "view_path": view_path, "open_path": open_path, "stem": stem, @@ -369,12 +370,43 @@ def _get_gallery_items(project_root): def _build_gallery_html(project_root): - """Build gallery card grid as Material 'grid cards' markdown.""" + """Build gallery card grid as Material 'grid cards' markdown, grouped by category.""" items = _get_gallery_items(project_root) if not items: return "\n" + # Group items by category, preserving order within each group + _CATEGORY_ORDER = ["tutorial", "how-to"] + _CATEGORY_HEADINGS = { + "tutorial": "Tutorials", + "how-to": "How-to Guides", + } + + grouped: dict[str, list[dict]] = {} + for item in items: + cat = item.get("category") or "other" + grouped.setdefault(cat, []).append(item) + + sections = [] + for cat in _CATEGORY_ORDER: + group = grouped.pop(cat, []) + if not group: + continue + heading = _CATEGORY_HEADINGS.get(cat, cat.title()) + cards = _build_gallery_cards(group) + sections.append(f"## {heading}\n\n{cards}") + + # Remaining uncategorized items + for _cat, group in grouped.items(): + cards = _build_gallery_cards(group) + sections.append(cards) + + return "\n\n".join(sections) + "\n" + + +def _build_gallery_cards(items): + """Build a Material 'grid cards' block from a list of gallery items.""" cards = [] for item in items: desc = item["description"] or "No description." @@ -481,25 +513,7 @@ def _build_api_examples_html(project_root, qualified_name): seen.add(item["stem"]) unique_items.append(item) - cards = [] - for item in unique_items: - desc = item["description"] or "No description." - cards.append( - f"- **{item['title']}**\n" - f"\n" - f" ---\n" - f"\n" - f" {desc}\n" - f"\n" - f" [View]({item['view_path']}) · " - f"[Open in marimo]({item['open_path']})" - ) - - return ( - "## Examples\n\n" - "The following example notebooks use this component:\n\n" - '