From 2bf1bc6178181a1152684322804e7267c9b0e063 Mon Sep 17 00:00:00 2001 From: Guillaume Tauzin <4648633+gtauzin@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:53:50 +0100 Subject: [PATCH 1/2] docs: restructure template and root docs to Diataxis folder-per-quadrant Reorganize generated project documentation into canonical Diataxis folders: - pages/tutorials/ (getting-started, examples) - pages/how-to/ (configure, troubleshooting, contribute) - pages/reference/ (api) - pages/explanation/ (concepts) Also restructure root repo docs (quickstart -> tutorials/) and update all cross-references in hooks.py, mkdocs.yml, index.md, tests, and skills. --- .../references/file-mapping.md | 2 +- docs/pages/reference/project-structure.md | 28 ++- docs/pages/{ => tutorials}/quickstart.md | 14 +- mkdocs.yml | 3 +- .../references/conflict-resolution.md | 17 +- .../references/file-classification.md | 12 +- template/CONTRIBUTING.md | 2 +- template/docs/hooks.py.jinja | 8 +- template/docs/index.md.jinja | 54 ++--- .../docs/pages/explanation/concepts.md.jinja | 20 ++ template/docs/pages/getting-started.md.jinja | 143 ----------- template/docs/pages/how-to/configure.md.jinja | 32 +++ .../contribute.md.jinja} | 2 +- .../pages/how-to/troubleshooting.md.jinja | 21 ++ .../api.md.jinja} | 0 .../pages/tutorials/getting-started.md.jinja | 75 ++++++ ...de_examples %}examples.md{% endif %}.jinja | 4 +- template/docs/pages/user-guide.md.jinja | 226 ------------------ template/mkdocs.yml.jinja | 16 +- .../hello.py.jinja | 4 +- tests/test_docs_content.py | 87 ++++--- tests/test_hooks.py | 16 +- tests/test_propagated_features.py | 10 +- tests/test_template.py | 22 +- 24 files changed, 314 insertions(+), 504 deletions(-) rename docs/pages/{ => tutorials}/quickstart.md (86%) create mode 100644 template/docs/pages/explanation/concepts.md.jinja delete mode 100644 template/docs/pages/getting-started.md.jinja create mode 100644 template/docs/pages/how-to/configure.md.jinja rename template/docs/pages/{contributing.md.jinja => how-to/contribute.md.jinja} (99%) create mode 100644 template/docs/pages/how-to/troubleshooting.md.jinja rename template/docs/pages/{api-reference.md.jinja => reference/api.md.jinja} (100%) create mode 100644 template/docs/pages/tutorials/getting-started.md.jinja rename template/docs/pages/{ => tutorials}/{% if include_examples %}examples.md{% endif %}.jinja (63%) delete mode 100644 template/docs/pages/user-guide.md.jinja diff --git a/.github/skills/backport-commit/references/file-mapping.md b/.github/skills/backport-commit/references/file-mapping.md index 2f6cb74..0c273d2 100644 --- a/.github/skills/backport-commit/references/file-mapping.md +++ b/.github/skills/backport-commit/references/file-mapping.md @@ -25,7 +25,7 @@ Some files use conditionals in the filename itself. | Generated Path | Template Path | |---|---| -| `docs/pages/examples.md` | `template/docs/pages/{% if include_examples %}examples.md{% endif %}.jinja` | +| `docs/pages/tutorials/examples.md` | `template/docs/pages/tutorials/{% if include_examples %}examples.md{% endif %}.jinja` | | `docs/stylesheets/gallery.css` | `template/docs/stylesheets/{% if include_examples %}gallery.css{% endif %}` | | `tests/test_examples.py` | `template/tests/{% if include_examples %}test_examples.py{% endif %}.jinja` | diff --git a/docs/pages/reference/project-structure.md b/docs/pages/reference/project-structure.md index 5e0d514..357e857 100644 --- a/docs/pages/reference/project-structure.md +++ b/docs/pages/reference/project-structure.md @@ -19,10 +19,17 @@ my-package/ │ └── pull_request_template.md ├── docs/ │ ├── index.md -│ ├── getting-started.md -│ ├── user-guide.md -│ ├── api-reference.md -│ └── contributing.md +│ ├── tutorials/ +│ │ ├── getting-started.md +│ │ └── examples.md +│ ├── how-to/ +│ │ ├── configure.md +│ │ ├── troubleshooting.md +│ │ └── contribute.md +│ ├── reference/ +│ │ └── api.md +│ └── explanation/ +│ └── concepts.md ├── src/ │ └── package_name/ │ ├── __init__.py @@ -99,10 +106,13 @@ The project uses a **src layout** - all package code lives under `src//** # All source code tests/** # All test files examples/** # conditional: include_examples -docs/pages/user-guide.md -docs/pages/getting-started.md -docs/pages/examples.md # conditional: include_examples +docs/pages/explanation/concepts.md +docs/pages/tutorials/getting-started.md +docs/pages/tutorials/examples.md # conditional: include_examples docs/examples/** # conditional: include_examples ``` @@ -160,7 +160,7 @@ This ensures the skill only spends effort merging files that actually have local - **Preserve local**: All changelog entries - **Strategy**: Keep the local CHANGELOG.md content. Only update the header/format if the template changed it. Never discard changelog entries. -### docs/index.md, docs/pages/contributing.md, docs/pages/api-reference.md +### docs/index.md, docs/pages/how-to/contribute.md, docs/pages/reference/api.md - **Accept from template**: Structural/format changes, new template sections - **Preserve local**: Custom content within existing sections, additional sections diff --git a/template/CONTRIBUTING.md b/template/CONTRIBUTING.md index 75f743a..0b2fc5b 100644 --- a/template/CONTRIBUTING.md +++ b/template/CONTRIBUTING.md @@ -18,7 +18,7 @@ just test-fast For the complete contributing guide - including test strategy, code quality standards, commit conventions, and CI/CD details - see: -**[Full Contributing Guide](docs/pages/contributing.md)** +**[Full Contributing Guide](docs/pages/how-to/contribute.md)** ## Reporting Issues diff --git a/template/docs/hooks.py.jinja b/template/docs/hooks.py.jinja index fe8ab2b..0f66cd2 100644 --- a/template/docs/hooks.py.jinja +++ b/template/docs/hooks.py.jinja @@ -529,7 +529,7 @@ def _build_module_toc(config, current_src_path=None): api_dir = docs_dir / "pages" / "api" project_root = docs_dir.parent - is_index = current_src_path is None or current_src_path == "pages/api-reference.md" + is_index = current_src_path is None or current_src_path == "pages/reference/api.md" modules = _get_submodules(project_root) module_toc = [] @@ -542,8 +542,8 @@ def _build_module_toc(config, current_src_path=None): # Compute relative URL if is_index: - # api-reference.md is at pages/api-reference/, submodule pages at pages/api/ - page_url = f"../api/{md_filename.replace('.md', '/')}" + # reference/api.md is at pages/reference/api/, submodule pages at pages/api/ + page_url = f"../../api/{md_filename.replace('.md', '/')}" else: page_url = f"../{md_filename.replace('.md', '/')}".replace("//", "/") @@ -903,7 +903,7 @@ def on_page_content(html, page, config, files): if src.startswith("pages/api/generated/"): html = _process_api_page_content(html, page, config) - if src == "pages/api-reference.md": + if src == "pages/reference/api.md": # API index: flat module list (api-index.html template) page.meta["module_toc"] = _build_module_toc(config, current_src_path=src) elif ( diff --git a/template/docs/index.md.jinja b/template/docs/index.md.jinja index ab1c70c..586d130 100644 --- a/template/docs/index.md.jinja +++ b/template/docs/index.md.jinja @@ -5,82 +5,68 @@ {{ description }} -[Add 1-2 paragraphs explaining: -- What this package integrates or provides -- The main value proposition -- Key use cases or target audience] -
- **Get Started in 5 Minutes** --- - Install {{ project_name }} and [achieve first result] - - Install → Initialize → Run → Done + Install {{ project_name }} and run your first example. - [Getting Started](pages/getting-started.md) + [Getting Started](pages/tutorials/getting-started.md) - **Need Help?** --- - Find answers to common questions and troubleshooting tips + Find answers to common questions and troubleshooting tips. - [FAQ & Troubleshooting](pages/user-guide.md#troubleshooting) + [Troubleshooting](pages/how-to/troubleshooting.md) - **Learn the Concepts** --- - Understand [core concepts or how components work together] + Understand the design and core ideas behind {{ project_name }}. - [Introduction](pages/user-guide.md) · [User guide](pages/user-guide.md) + [Concepts](pages/explanation/concepts.md) {% if include_examples %} - **See It In Action** --- - Explore a complete example [describe what the example demonstrates] + Explore interactive example notebooks. - [Example Project](pages/examples.md) + [Examples](pages/tutorials/examples.md) {% endif %}
## Table of Contents -### [Getting started](pages/getting-started.md) - -Step-by-step guide to installing and setting up {{ project_name }} in your project. +### [Getting Started](pages/tutorials/getting-started.md) -- [1. [First Setup Step]](pages/getting-started.md#step-1-import-and-initialize) -- [2. [Installation or Configuration]](pages/getting-started.md#step-2-configure-your-setup) -- [3. [Initialize/Configure Step]](pages/getting-started.md#step-3-use-the-main-functionality) +Install and run your first example. {% if include_examples %} -### [Example](pages/examples.md) +### [Examples](pages/tutorials/examples.md) -A practical example demonstrating how to use {{ project_name }} in a real project. - -- [Project overview](pages/examples.md#examples) -- [Quick start](pages/examples.md#running-examples-locally) +Interactive notebooks demonstrating {{ project_name }} in practice. {% endif %} -### [User guide](pages/user-guide.md) +### [Configuration](pages/how-to/configure.md) + +Set up and customize {{ project_name }} for your project. -In-depth documentation on the design, architecture, and core concepts. +### [API Reference](pages/reference/api.md) -- [Core Concepts](pages/user-guide.md#core-concepts) -- [Configuration](pages/user-guide.md#configuration) -- [Best Practices](pages/user-guide.md#best-practices) +Complete API reference - classes, functions, and options. -### [Reference](pages/api-reference/) +### [Concepts](pages/explanation/concepts.md) -Detailed reference for the {{ project_name }} API, including classes, functions, and configuration options. +Design, architecture, and core ideas. ## License -{{ project_name }} is open source and licensed under the [{{ license }} License](https://opensource.org/licenses/{{ license }}). You are free to use, modify, and distribute this software under the terms of this license. +{{ project_name }} is open source and licensed under the [{{ license }} License](https://opensource.org/licenses/{{ license }}). diff --git a/template/docs/pages/explanation/concepts.md.jinja b/template/docs/pages/explanation/concepts.md.jinja new file mode 100644 index 0000000..c68feb5 --- /dev/null +++ b/template/docs/pages/explanation/concepts.md.jinja @@ -0,0 +1,20 @@ +# About {{ project_name }} + +{{ description }} + +## Core Concepts + +Describe the key abstractions, terminology, and mental models for your package. + +## Architecture + +Explain how the package is structured and how the components fit together. + +## Limitations + +Document known constraints and trade-offs so users can make informed decisions. + +## See Also + +- [Getting Started](../tutorials/getting-started.md) - install and first example +- [API Reference](../reference/api.md) - detailed API documentation diff --git a/template/docs/pages/getting-started.md.jinja b/template/docs/pages/getting-started.md.jinja deleted file mode 100644 index 16cd5fc..0000000 --- a/template/docs/pages/getting-started.md.jinja +++ /dev/null @@ -1,143 +0,0 @@ -# Getting Started - -This guide will help you install and start using {{ project_name }} in minutes. - -## Installation - -### Step 1: Install the package - -Choose your preferred package manager: - -=== "pip" - - ```bash - pip install {{ package_name }} - ``` - -=== "uv" - - ```bash - uv add {{ package_name }} - ``` - -=== "conda" - - ```bash - conda install -c conda-forge {{ package_name }} - ``` - -=== "mamba" - - ```bash - mamba install -c conda-forge {{ package_name }} - ``` - -> **Note**: For conda/mamba, ensure the package is published to conda-forge first. - -### Step 2: Verify installation - -```python -import {{ package_name }} -print({{ package_name }}.__version__) -``` - -## Basic Usage - -### Step 1: [Import and initialize] - -```python -from {{ package_name }}.example import hello - -# Basic usage example -result = hello("World") -print(result) # Output: Hello, World! -``` - -### Step 2: [Configure your setup] - -Create a configuration file or set up options: - -```yaml -# config.yaml (if your package supports config files) -{{ package_name }}: - option_1: value # Description of what this controls - option_2: true # Description of what this controls - option_3: 10 # Description of what this controls -``` - -Or configure in code: - -```python -from {{ package_name }} import [MainClass] - -# Initialize with custom configuration -instance = [MainClass]( - option_1="value", # Description - option_2=True, # Description - option_3=10, # Description -) -``` - -### Step 3: [Use the main functionality] - -```python -# [Add realistic example showing actual usage] -# For example: -# result = instance.process(data) -# output = instance.transform(input_data) - -# Example with the provided function -greeting = hello("Python") -print(greeting) -``` - -## Complete Example - -Here's a complete working example: - -```python -from {{ package_name }}.example import hello - -# [Replace with realistic multi-step example] -# Step 1: Initialize -names = ["Alice", "Bob", "Charlie"] - -# Step 2: Process -greetings = [hello(name) for name in names] - -# Step 3: Display results -for greeting in greetings: - print(greeting) -``` - -{% if include_examples %}## Try Interactive Examples - -For hands-on learning with interactive notebooks, see the [Examples](examples.md) page where you can: - -- Run code directly in your browser -- Experiment with different parameters -- See visual outputs in real-time -- Download standalone HTML versions - -Or run locally: - -=== "just" - - ```bash - just example - ``` - -=== "uv run" - - ```bash - uv run marimo edit examples/hello.py - ``` -{% endif %} -## Next Steps - -Now that you have {{ project_name }} installed and running: - -- **Learn the concepts**: Read the [User Guide](user-guide.md) to understand core concepts and capabilities -{% if include_examples %}- **Explore examples**: Check out the [Examples](examples.md) for real-world use cases -{% endif %}- **Dive into the API**: Browse the [API Reference](api-reference.md) for detailed documentation -- **Get help**: Visit [GitHub Discussions](https://github.com/{{ github_username }}/{{ project_slug }}/discussions) or [open an issue](https://github.com/{{ github_username }}/{{ project_slug }}/issues) diff --git a/template/docs/pages/how-to/configure.md.jinja b/template/docs/pages/how-to/configure.md.jinja new file mode 100644 index 0000000..c7be78c --- /dev/null +++ b/template/docs/pages/how-to/configure.md.jinja @@ -0,0 +1,32 @@ +# How to Configure {{ project_name }} + +This guide shows you how to set up and customize {{ project_name }} for your project. + +## Basic Configuration + +```python +from {{ package_name }} import [MainClass] + +instance = [MainClass]( + option_1="value", + option_2=True, +) +``` + +## Configuration File + +```yaml +# config.yaml +{{ package_name }}: + option_1: value + option_2: true +``` + +## Advanced Configuration + +Describe advanced configuration patterns here: environment variables, multiple environments, runtime overrides. + +## See Also + +- [Concepts](../explanation/concepts.md) - understand the design +- [API Reference](../reference/api.md) - full list of options diff --git a/template/docs/pages/contributing.md.jinja b/template/docs/pages/how-to/contribute.md.jinja similarity index 99% rename from template/docs/pages/contributing.md.jinja rename to template/docs/pages/how-to/contribute.md.jinja index bc00553..1b9c8d4 100644 --- a/template/docs/pages/contributing.md.jinja +++ b/template/docs/pages/how-to/contribute.md.jinja @@ -523,7 +523,7 @@ Run the example test suite to verify your notebook passes: uv run pytest tests/test_examples.py -m example ``` -Add a link to your example in `docs/pages/examples.md`: +Add a link to your example in `docs/pages/tutorials/examples.md`: ```markdown - [Example Name](../examples//) - Brief description diff --git a/template/docs/pages/how-to/troubleshooting.md.jinja b/template/docs/pages/how-to/troubleshooting.md.jinja new file mode 100644 index 0000000..86e3a0c --- /dev/null +++ b/template/docs/pages/how-to/troubleshooting.md.jinja @@ -0,0 +1,21 @@ +# Troubleshooting + +Solutions to common problems when using {{ project_name }}. + +## Installation Issues + +**Problem: Package not found** +: Verify the package name and that it is published: `pip install {{ package_name }}` + +**Problem: Import error after installation** +: Make sure you installed in the active environment: `python -c "import {{ package_name }}"` + +## Runtime Issues + +**Problem: Unexpected behavior** +: Check your configuration and consult the [Configuration guide](configure.md). + +## Getting Help + +- [Open an issue on GitHub](https://github.com/{{ github_username }}/{{ project_slug }}/issues/new) +- [Start a discussion](https://github.com/{{ github_username }}/{{ project_slug }}/discussions) diff --git a/template/docs/pages/api-reference.md.jinja b/template/docs/pages/reference/api.md.jinja similarity index 100% rename from template/docs/pages/api-reference.md.jinja rename to template/docs/pages/reference/api.md.jinja diff --git a/template/docs/pages/tutorials/getting-started.md.jinja b/template/docs/pages/tutorials/getting-started.md.jinja new file mode 100644 index 0000000..97de9dc --- /dev/null +++ b/template/docs/pages/tutorials/getting-started.md.jinja @@ -0,0 +1,75 @@ +# Getting Started + +In this tutorial, we will install {{ project_name }} and run a first example. + +## Installation + +Choose your preferred package manager: + +=== "pip" + + ```bash + pip install {{ package_name }} + ``` + +=== "uv" + + ```bash + uv add {{ package_name }} + ``` + +=== "conda" + + ```bash + conda install -c conda-forge {{ package_name }} + ``` + +=== "mamba" + + ```bash + mamba install -c conda-forge {{ package_name }} + ``` + +> **Note**: For conda/mamba, ensure the package is published to conda-forge first. + +Verify the installation: + +```python +import {{ package_name }} +print({{ package_name }}.__version__) +``` + +## Your First Example + +```python +from {{ package_name }}.example import hello + +result = hello("World") +print(result) # Output: Hello, World! +``` + +{% if include_examples %} +## Try Interactive Examples + +For hands-on learning with interactive notebooks, see the [Examples](examples.md) page. + +Run locally: + +=== "just" + + ```bash + just example + ``` + +=== "uv run" + + ```bash + uv run marimo edit examples/hello.py + ``` +{% endif %} +## Next Steps + +- **Learn the concepts**: Read [Concepts](../explanation/concepts.md) to understand the design +{% if include_examples %}- **Explore examples**: Check out the [Examples](examples.md) for interactive notebooks +{% endif %}- **Dive into the API**: Browse the [API Reference](../reference/api.md) for detailed documentation +- **Get help**: Visit [GitHub Discussions](https://github.com/{{ github_username }}/{{ project_slug }}/discussions) or [open an issue](https://github.com/{{ github_username }}/{{ project_slug }}/issues) diff --git a/template/docs/pages/{% if include_examples %}examples.md{% endif %}.jinja b/template/docs/pages/tutorials/{% if include_examples %}examples.md{% endif %}.jinja similarity index 63% rename from template/docs/pages/{% if include_examples %}examples.md{% endif %}.jinja rename to template/docs/pages/tutorials/{% if include_examples %}examples.md{% endif %}.jinja index 5bbda75..7286628 100644 --- a/template/docs/pages/{% if include_examples %}examples.md{% endif %}.jinja +++ b/template/docs/pages/tutorials/{% if include_examples %}examples.md{% endif %}.jinja @@ -16,6 +16,6 @@ python examples/hello.py ## Next Steps -- Browse the [API Reference](api-reference.md) for detailed documentation -- Check the [User Guide](user-guide.md) to understand core concepts +- Browse the [API Reference](../reference/api.md) for detailed documentation +- Check the [Concepts](../explanation/concepts.md) to understand core ideas {% endif -%} diff --git a/template/docs/pages/user-guide.md.jinja b/template/docs/pages/user-guide.md.jinja deleted file mode 100644 index 2dbdf7e..0000000 --- a/template/docs/pages/user-guide.md.jinja +++ /dev/null @@ -1,226 +0,0 @@ -# User Guide - -This guide provides comprehensive documentation for {{ project_name }}. - -## Overview - -{{ description }} - -[Add 2-3 paragraphs expanding on: -- What makes this package unique -- Core philosophy and design principles -- When to use it vs alternatives] - -## Prerequisites - -Before diving into {{ project_name }}, it's helpful to understand: - -### [Prerequisite Technology/Concept 1] - -[Brief 2-3 sentence explanation of what this is and why it matters. Link to external docs for deeper learning.] - -Learn more: [Official Documentation](https://example.com) - -### [Prerequisite Technology/Concept 2] - -[Brief explanation of the second prerequisite technology or concept.] - -Learn more: [Official Documentation](https://example.com) - -## Why {{ project_name }}? - -[2-3 paragraphs explaining the philosophy and value proposition: -- What problem space does this address? -- What's the approach or methodology? -- How does it fit into the broader ecosystem? -- What makes this solution effective?] - -### For [User Persona 1] Users - -If you're coming from [context/background], {{ project_name }} offers: - -- **[Benefit 1]**: [2-3 line detailed explanation of how this helps this persona specifically] -- **[Benefit 2]**: [2-3 line detailed explanation of how this helps this persona specifically] -- **[Benefit 3]**: [2-3 line detailed explanation of how this helps this persona specifically] -- **[Benefit 4]**: [2-3 line detailed explanation of how this helps this persona specifically] - -### For [User Persona 2] Users - -If you're familiar with [alternative approach/tool], you'll appreciate: - -- **[Benefit 1]**: [2-3 line detailed explanation of how this helps this persona specifically] -- **[Benefit 2]**: [2-3 line detailed explanation of how this helps this persona specifically] -- **[Benefit 3]**: [2-3 line detailed explanation of how this helps this persona specifically] - -## Core Concepts - -### [Concept 1: Primary Concept Name] - -[2-3 paragraphs explaining this core concept: -- What it is and why it exists -- How it works at a conceptual level -- Why this design choice was made -- Examples or analogies that clarify] - -```python -# Example demonstrating the concept -from {{ package_name }} import [Class] - -# [Brief code example] -``` - -### [Concept 2: Secondary Concept Name] - -[Detailed explanation of the second core concept with similar depth] - -```python -# Example demonstrating the concept -``` - -## Key Features - -### [Feature 1: Feature Name] - -[2-3 paragraphs explaining this feature: -- What capability this provides -- Why it matters and what problems it solves -- How to use it effectively -- When to use this feature] - -**Example:** - -```python -from {{ package_name }} import [Component] - -# Demonstrate the feature with realistic code -``` - -Learn more: [Related concept or external documentation](https://example.com) - -### [Feature 2: Feature Name] - -[Detailed explanation of this feature] - -**Example:** - -```python -# Realistic example code -``` - -### [Feature 3: Feature Name] - -[Detailed explanation with focus on practical use] - -### [Feature 4: Feature Name] - -[Explanation including trade-offs and best practices] - -### [Feature 5: Feature Name] - -[Explanation of advanced or specialized feature] - -### [Feature 6: Feature Name] *(Experimental)* - -[Explanation of experimental or future features, noting maturity level and potential changes] - -> **Note**: This feature is experimental and may change in future versions. - -## Configuration - -### Basic Configuration - -[Explanation of how to configure the package] - -```python -from {{ package_name }} import [ConfigClass] - -config = [ConfigClass]( - option_1="value", # Description of what this controls - option_2=True, # Description of what this controls -) -``` - -Or using a configuration file: - -```yaml -# config.yaml -{{ package_name }}: - option_1: value - option_2: true -``` - -### Advanced Configuration - -[More advanced configuration options and patterns] - -## Best Practices - -### 1. [Best Practice Category 1] - -**Do:** -- [Specific recommendation with brief explanation] -- [Another recommendation] - -**Don't:** -- [Anti-pattern to avoid with explanation why] - -### 2. [Best Practice Category 2] - -[Explanation of recommended patterns and approaches] - -### 3. [Best Practice Category 3] - -[Additional guidance on effective usage] - -## Limitations and Considerations - -Understanding the limitations helps you make informed decisions: - -1. **[Limitation 1]**: [Explanation of the trade-off or constraint and why it exists] - -2. **[Limitation 2]**: [Explanation of what's not supported and potential workarounds] - -3. **[Consideration 3]**: [Important factor to consider when using this package] - -## Troubleshooting - -### [Common Issue 1] - -**Problem**: [Description of the problem users encounter] - -**Solution**: [Step-by-step solution with code examples] - -```python -# Example showing the solution -``` - -### [Common Issue 2] - -**Problem**: [Description] - -**Solution**: [Resolution with explanation] - -**Solution**: [Resolution with explanation] - -## FAQ - -### [Question 1]? - -[Detailed answer addressing the question comprehensively] - -### [Question 2]? - -[Answer with examples or links as needed] - -### [Question 3]? - -[Answer that might reference other sections or external resources] - -## Next Steps - -Now that you understand the core concepts and features: - -- Follow the [Getting Started](getting-started.md) guide to start using {{ project_name }} -{% if include_examples %}- Explore the [Examples](examples.md) for real-world use cases -{% endif %}- Check the [API Reference](api-reference.md) for detailed API documentation -- Join the community on [GitHub Discussions](https://github.com/{{ github_username }}/{{ project_slug }}/discussions) diff --git a/template/mkdocs.yml.jinja b/template/mkdocs.yml.jinja index 1fd1d67..d3b926c 100644 --- a/template/mkdocs.yml.jinja +++ b/template/mkdocs.yml.jinja @@ -138,11 +138,17 @@ plugins: nav: - Home: index.md - - Getting Started: pages/getting-started.md - - User Guide: pages/user-guide.md -{% if include_examples %} - Examples: pages/examples.md -{% endif %} - API Reference: pages/api-reference.md - - Contributing: pages/contributing.md + - Tutorials: + - Getting Started: pages/tutorials/getting-started.md +{% if include_examples %} - Examples: pages/tutorials/examples.md +{% endif %} - How-to Guides: + - Configuration: pages/how-to/configure.md + - Troubleshooting: pages/how-to/troubleshooting.md + - Contributing: pages/how-to/contribute.md + - Reference: + - API: pages/reference/api.md + - Explanation: + - Concepts: pages/explanation/concepts.md extra: social: diff --git a/template/{% if include_examples %}examples{% endif %}/hello.py.jinja b/template/{% if include_examples %}examples{% endif %}/hello.py.jinja index 8848c57..bd8a3ae 100644 --- a/template/{% if include_examples %}examples{% endif %}/hello.py.jinja +++ b/template/{% if include_examples %}examples{% endif %}/hello.py.jinja @@ -129,9 +129,9 @@ def _(mo): | Topic | Resource | |-------|----------| - | User Guide | [User Guide](../pages/user-guide/) | + | Concepts | [Concepts](../pages/explanation/concepts/) | | API Reference | [API Reference](../pages/api/) | - | Contributing | [Contributing Guide](../pages/contributing/) | + | Contributing | [Contributing Guide](../pages/how-to/contribute/) | | marimo docs | [marimo.io](https://marimo.io) | **Try these commands:** diff --git a/tests/test_docs_content.py b/tests/test_docs_content.py index fb93216..e17dd3b 100644 --- a/tests/test_docs_content.py +++ b/tests/test_docs_content.py @@ -81,7 +81,7 @@ def test_getting_started_exists(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - getting_started = result.project_dir / "docs" / "pages" / "getting-started.md" + getting_started = result.project_dir / "docs" / "pages" / "tutorials" / "getting-started.md" assert getting_started.is_file() def test_getting_started_includes_installation(self, copie): @@ -89,7 +89,7 @@ def test_getting_started_includes_installation(self, copie): result = copie.copy(extra_answers={"package_name": "my_package"}) assert result.exit_code == 0 - getting_started = result.project_dir / "docs" / "pages" / "getting-started.md" + getting_started = result.project_dir / "docs" / "pages" / "tutorials" / "getting-started.md" content = getting_started.read_text(encoding="utf-8") # Should mention installation @@ -103,7 +103,7 @@ def test_getting_started_includes_usage_example(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - getting_started = result.project_dir / "docs" / "pages" / "getting-started.md" + getting_started = result.project_dir / "docs" / "pages" / "tutorials" / "getting-started.md" content = getting_started.read_text(encoding="utf-8") # Should have code blocks @@ -113,32 +113,53 @@ def test_getting_started_includes_usage_example(self, copie): assert "usage" in content.lower() or "example" in content.lower() -class TestUserGuidePage: - """Test the user guide documentation page.""" +class TestConceptsPage: + """Test the concepts (explanation) documentation page.""" - def test_user_guide_exists(self, copie): - """Test that user guide page exists.""" + def test_concepts_exists(self, copie): + """Test that concepts page exists.""" result = copie.copy(extra_answers={}) assert result.exit_code == 0 - user_guide = result.project_dir / "docs" / "pages" / "user-guide.md" - assert user_guide.is_file() + concepts = result.project_dir / "docs" / "pages" / "explanation" / "concepts.md" + assert concepts.is_file() - def test_user_guide_has_substantial_content(self, copie): - """Test that user guide has meaningful content.""" + def test_concepts_has_content(self, copie): + """Test that concepts page has meaningful content.""" result = copie.copy(extra_answers={}) assert result.exit_code == 0 - user_guide = result.project_dir / "docs" / "pages" / "user-guide.md" - content = user_guide.read_text(encoding="utf-8") - - # Should be non-trivial - assert len(content.strip()) > 200 + concepts = result.project_dir / "docs" / "pages" / "explanation" / "concepts.md" + content = concepts.read_text(encoding="utf-8") # Should have multiple sections assert content.count("#") >= 2 +class TestConfigurePage: + """Test the configuration how-to page.""" + + def test_configure_exists(self, copie): + """Test that configure page exists.""" + result = copie.copy(extra_answers={}) + assert result.exit_code == 0 + + configure = result.project_dir / "docs" / "pages" / "how-to" / "configure.md" + assert configure.is_file() + + +class TestTroubleshootingPage: + """Test the troubleshooting how-to page.""" + + def test_troubleshooting_exists(self, copie): + """Test that troubleshooting page exists.""" + result = copie.copy(extra_answers={}) + assert result.exit_code == 0 + + troubleshooting = result.project_dir / "docs" / "pages" / "how-to" / "troubleshooting.md" + assert troubleshooting.is_file() + + class TestAPIReferencePage: """Test the API reference documentation page.""" @@ -147,7 +168,7 @@ def test_api_reference_exists(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - api_reference = result.project_dir / "docs" / "pages" / "api-reference.md" + api_reference = result.project_dir / "docs" / "pages" / "reference" / "api.md" assert api_reference.is_file() def test_api_reference_includes_package_name(self, copie): @@ -155,7 +176,7 @@ def test_api_reference_includes_package_name(self, copie): result = copie.copy(extra_answers={"package_name": "custom_pkg"}) assert result.exit_code == 0 - api_reference = result.project_dir / "docs" / "pages" / "api-reference.md" + api_reference = result.project_dir / "docs" / "pages" / "reference" / "api.md" content = api_reference.read_text(encoding="utf-8") # Should reference the package via the API_TABLE placeholder @@ -166,7 +187,7 @@ def test_api_reference_has_code_documentation(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - api_reference = result.project_dir / "docs" / "pages" / "api-reference.md" + api_reference = result.project_dir / "docs" / "pages" / "reference" / "api.md" content = api_reference.read_text(encoding="utf-8") # Should have API_TABLE placeholder (resolved at build time by hooks) @@ -181,7 +202,7 @@ def test_contributing_page_exists(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" assert contributing.is_file() def test_contributing_includes_development_setup(self, copie): @@ -189,7 +210,7 @@ def test_contributing_includes_development_setup(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should mention development setup @@ -203,7 +224,7 @@ def test_contributing_includes_testing_info(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should mention testing @@ -217,7 +238,7 @@ def test_contributing_includes_lint_documentation(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should have lint section @@ -238,7 +259,7 @@ def test_contributing_has_github_links_in_questions_section(self, copie): result = copie.copy(extra_answers=custom_answers) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should have Questions section @@ -255,7 +276,7 @@ def test_contributing_has_proper_semver_list_formatting(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should have Version Numbering section with Semantic Versioning @@ -281,7 +302,7 @@ def test_contributing_has_improved_mermaid_colors(self, copie): result = copie.copy(extra_answers={}) assert result.exit_code == 0 - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" content = contributing.read_text(encoding="utf-8") # Should have mermaid diagram with improved styling @@ -301,7 +322,7 @@ def test_examples_page_exists_when_enabled(self, copie): result = copie.copy(extra_answers={"include_examples": True}) assert result.exit_code == 0 - examples_page = result.project_dir / "docs" / "pages" / "examples.md" + examples_page = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" assert examples_page.is_file() def test_examples_page_not_exists_when_disabled(self, copie): @@ -309,7 +330,7 @@ def test_examples_page_not_exists_when_disabled(self, copie): result = copie.copy(extra_answers={"include_examples": False}) assert result.exit_code == 0 - examples_page = result.project_dir / "docs" / "pages" / "examples.md" + examples_page = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" assert not examples_page.exists() def test_examples_page_references_notebooks(self, copie): @@ -317,7 +338,7 @@ def test_examples_page_references_notebooks(self, copie): result = copie.copy(extra_answers={"include_examples": True}) assert result.exit_code == 0 - examples_page = result.project_dir / "docs" / "pages" / "examples.md" + examples_page = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" content = examples_page.read_text(encoding="utf-8") # Should reference examples or notebooks @@ -331,7 +352,7 @@ def test_examples_page_uses_gallery_placeholder(self, copie): result = copie.copy(extra_answers={"include_examples": True}) assert result.exit_code == 0 - examples_page = result.project_dir / "docs" / "pages" / "examples.md" + examples_page = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" assert examples_page.is_file() content = examples_page.read_text(encoding="utf-8") @@ -533,8 +554,8 @@ def test_all_docs_use_correct_package_name(self, copie): docs_pages = [ result.project_dir / "docs" / "index.md", - result.project_dir / "docs" / "pages" / "getting-started.md", - result.project_dir / "docs" / "pages" / "api-reference.md", + result.project_dir / "docs" / "pages" / "tutorials" / "getting-started.md", + result.project_dir / "docs" / "pages" / "reference" / "api.md", ] for page in docs_pages: @@ -564,7 +585,7 @@ def test_docs_use_correct_github_username(self, copie): assert "github.com/my-custom-org/my-project" in content # Check contributing page - contributing = result.project_dir / "docs" / "pages" / "contributing.md" + contributing = result.project_dir / "docs" / "pages" / "how-to" / "contribute.md" if contributing.exists(): contrib_content = contributing.read_text(encoding="utf-8") # Should reference the correct repository diff --git a/tests/test_hooks.py b/tests/test_hooks.py index 150c462..2a9bab2 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -82,8 +82,8 @@ def test_on_post_build_copies_markdown(copie_with_examples, tmp_path): # Verify markdown files were copied assert (site_dir / "index.md").is_file(), "index.md not copied" - assert (site_dir / "pages" / "getting-started.md").is_file(), "getting-started.md not copied" - assert (site_dir / "pages" / "contributing.md").is_file(), "contributing.md not copied" + assert (site_dir / "pages" / "tutorials" / "getting-started.md").is_file(), "getting-started.md not copied" + assert (site_dir / "pages" / "how-to" / "contribute.md").is_file(), "contribute.md not copied" finally: sys.path.pop(0) @@ -210,8 +210,8 @@ def test_on_post_build_converts_html_to_markdown(copie_with_examples, tmp_path): # Verify markdown files exist in site directory site_dir = copie_with_examples.project_dir / "site" assert (site_dir / "index.md").is_file(), "index.md not found in site" - assert (site_dir / "pages" / "getting-started.md").is_file(), "getting-started.md not found in site" - assert (site_dir / "pages" / "api-reference.md").is_file(), "api-reference.md not found" + assert (site_dir / "pages" / "tutorials" / "getting-started.md").is_file(), "getting-started.md not found in site" + assert (site_dir / "pages" / "reference" / "api.md").is_file(), "api.md not found" # Verify markdown content is cleaned (not just raw source) index_md = (site_dir / "index.md").read_text(encoding="utf-8") @@ -379,10 +379,10 @@ def test_markdown_accessible_after_docs_build(copie_with_examples): # Verify both HTML and markdown exist for each page pages = [ "index", - "pages/getting-started", - "pages/user-guide", - "pages/api-reference", - "pages/contributing", + "pages/tutorials/getting-started", + "pages/explanation/concepts", + "pages/reference/api", + "pages/how-to/contribute", ] for page in pages: diff --git a/tests/test_propagated_features.py b/tests/test_propagated_features.py index 795aa34..04d8b57 100644 --- a/tests/test_propagated_features.py +++ b/tests/test_propagated_features.py @@ -107,10 +107,10 @@ def test_exclude_docs_has_api_submodule(self, copie_session_default): assert "api-submodule.html" in content def test_nav_uses_api_reference(self, copie_session_default): - """Test that nav points to pages/api-reference.md.""" + """Test that nav points to pages/reference/api.md.""" result = copie_session_default content = (result.project_dir / "mkdocs.yml").read_text() - assert "pages/api-reference.md" in content + assert "pages/reference/api.md" in content class TestAPISubmodulePages: @@ -134,7 +134,7 @@ def test_api_submodule_template_has_placeholders(self, copie_session_default): def test_api_index_has_table_placeholder(self, copie_session_default): """Test that API reference page has the API_TABLE placeholder.""" result = copie_session_default - content = (result.project_dir / "docs" / "pages" / "api-reference.md").read_text() + content = (result.project_dir / "docs" / "pages" / "reference" / "api.md").read_text() assert "" in content assert "# API Reference" in content @@ -205,7 +205,7 @@ class TestGallerySystem: def test_examples_page_has_gallery_placeholder(self, copie): """Test that examples.md uses the GALLERY placeholder.""" result = copie.copy(extra_answers={"include_examples": True}) - content = (result.project_dir / "docs" / "pages" / "examples.md").read_text() + content = (result.project_dir / "docs" / "pages" / "tutorials" / "examples.md").read_text() assert "" in content def test_hello_notebook_has_gallery_metadata(self, copie): @@ -345,7 +345,7 @@ class TestContributingFix: def test_contributing_uses_min_python_version(self, copie): """Test that contributing.md uses min_python_version, not undefined python_version.""" result = copie.copy(extra_answers={"min_python_version": "3.12"}) - content = (result.project_dir / "docs" / "pages" / "contributing.md").read_text() + content = (result.project_dir / "docs" / "pages" / "how-to" / "contribute.md").read_text() assert "Python 3.12+" in content diff --git a/tests/test_template.py b/tests/test_template.py index 1ec4290..35f7215 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -120,7 +120,7 @@ def test_generated_project_structure(copie_session_default): # Check docs docs_dir = result.project_dir / "docs" assert (docs_dir / "index.md").is_file() - assert (docs_dir / "pages" / "contributing.md").is_file() + assert (docs_dir / "pages" / "how-to" / "contribute.md").is_file() # Check GitHub workflows workflows_dir = result.project_dir / ".github" / "workflows" @@ -495,15 +495,15 @@ def test_examples_directory_when_enabled(copie): assert "-n auto" in justfile_content # Check examples.md exists and uses gallery placeholder - examples_md = result.project_dir / "docs" / "pages" / "examples.md" - assert examples_md.is_file(), "docs/pages/examples.md not created" + examples_md = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" + assert examples_md.is_file(), "docs/pages/tutorials/examples.md not created" examples_content = examples_md.read_text(encoding="utf-8") assert "" in examples_content assert "## Running Examples Locally" in examples_content # Check mkdocs.yml includes examples in nav and has exclude_docs mkdocs_content = (result.project_dir / "mkdocs.yml").read_text(encoding="utf-8") - assert "Examples: pages/examples.md" in mkdocs_content + assert "Examples: pages/tutorials/examples.md" in mkdocs_content # Check for exclude_docs with CLAUDE.md files assert "exclude_docs:" in mkdocs_content assert "examples/**/CLAUDE.md" in mkdocs_content @@ -520,7 +520,9 @@ def test_examples_directory_when_enabled(copie): assert "marimo edit examples/hello.py" in readme_content # Check CONTRIBUTING mentions adding examples with new pytest approach - contributing_content = (result.project_dir / "docs" / "pages" / "contributing.md").read_text(encoding="utf-8") + contributing_content = (result.project_dir / "docs" / "pages" / "how-to" / "contribute.md").read_text( + encoding="utf-8" + ) assert "### Adding Examples" in contributing_content assert "test_examples" in contributing_content or "test-examples" in contributing_content @@ -563,16 +565,16 @@ def test_examples_directory_when_disabled(copie): assert len(example_command_lines) == 0, "example command should not exist" # Check examples.md doesn't exist or is empty - examples_md = result.project_dir / "docs" / "examples.md" + examples_md = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" if examples_md.exists(): content = examples_md.read_text(encoding="utf-8").strip() assert content == "", ( - f"docs/examples.md should be empty when examples are disabled, but contains: {content[:100]}" + f"docs/pages/tutorials/examples.md should be empty when examples are disabled, but contains: {content[:100]}" ) # Check mkdocs.yml doesn't include examples in nav mkdocs_content = (result.project_dir / "mkdocs.yml").read_text(encoding="utf-8") - assert "Examples: examples.md" not in mkdocs_content + assert "Examples: tutorials/examples.md" not in mkdocs_content # Check GitHub workflow doesn't include examples job tests_workflow = result.project_dir / ".github" / "workflows" / "tests.yml" @@ -784,7 +786,7 @@ def test_markdown_docs_created_and_clean(copie): assert len(md_files) > 0, f"No markdown files found in site/. Site structure: {list(site_dir.iterdir())}" # Verify key markdown files exist - expected_md_files = ["index.md", "getting-started.md", "user-guide.md"] + expected_md_files = ["index.md", "getting-started.md", "concepts.md"] found_names = {f.name for f in md_files} for expected in expected_md_files: assert expected in found_names, f"{expected} not found in site/. Found: {found_names}" @@ -825,7 +827,7 @@ def test_three_tier_documentation_system(copie): assert result.exit_code == 0 # Tier 1: Verify embedded marimo setup in examples.md - examples_md = result.project_dir / "docs" / "pages" / "examples.md" + examples_md = result.project_dir / "docs" / "pages" / "tutorials" / "examples.md" examples_content = examples_md.read_text(encoding="utf-8") # Check for marimo-embed directive with inline code has_marimo = "/// marimo-embed" in examples_content and "@app.cell" in examples_content From ea1bbbbef37c2a2d8dcb8ca2e1c200b6cf794128 Mon Sep 17 00:00:00 2001 From: Guillaume Tauzin <4648633+gtauzin@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:23:52 +0100 Subject: [PATCH 2/2] fix: update quickstart link to new tutorials path --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index b2781a6..7d91e6a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,7 +20,7 @@ A modern Python package template using [Copier](https://copier.readthedocs.io/) ## Get Started -- **[Quick Start](pages/quickstart.md)** - Create your package in 5 minutes +- **[Quick Start](pages/tutorials/quickstart.md)** - Create your package in 5 minutes ## How-to Guides