Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions .github/ISSUE_TEMPLATE/bug_report.md

This file was deleted.

23 changes: 0 additions & 23 deletions .github/ISSUE_TEMPLATE/feature_request.md

This file was deleted.

10 changes: 0 additions & 10 deletions .github/PULL_REQUEST_TEMPLATE.md

This file was deleted.

5 changes: 4 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
run: |
uv run python docs/tools/notebooks.py execute
uv run python docs/tools/notebooks.py convert --strict
uv run python docs/tools/examples.py

- name: Build the site
working-directory: docs
Expand All @@ -59,9 +60,11 @@ jobs:
- name: Smoke test the built site
working-directory: docs
run: |
for page in /index.html /getting-started/installation/index.html /tutorials/example-tutorial/index.html /api/app/index.html /api/app/main/index.html; do
for page in /index.html /getting-started/installation/index.html /tutorials/index.html /tutorials/example-tutorial/index.html /full-examples/index.html /full-examples/sine-wave/index.html /api/app/index.html /api/app/main/index.html; do
test -f "dist$page" || { echo "missing dist$page"; exit 1; }
done
test -f dist/tutorials/example-tutorial/example_tutorial.ipynb
test -f dist/full-examples/sine-wave/plot-1.png
grep -q 'href="/template-python/' dist/index.html || { echo "links do not use the base path"; exit 1; }
echo "all pages built with the /template-python base path"

Expand Down
36 changes: 0 additions & 36 deletions CODE_OF_CONDUCT.md

This file was deleted.

8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ NOTEBOOKS = $(PYTHON) docs/tools/notebooks.py
DOCS_ENV = DOCS_PYTHON=$(shell $(PYTHON) -c "import sys; print(sys.executable)")
FORCE ?=

.PHONY: help install test lint readme readme-check docs-install docs-notebooks docs-dev docs-build docs-preview docs-clean
.PHONY: help install test lint readme readme-check docs-install docs-notebooks docs-examples docs-dev docs-build docs-preview docs-clean

help: ## list the targets
@grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-16s %s\n", $$1, $$2}'
Expand Down Expand Up @@ -37,17 +37,23 @@ docs-notebooks: ## execute the changed tutorials and convert all of them (FORCE
$(NOTEBOOKS) execute $(if $(FORCE),--force,)
$(NOTEBOOKS) convert

docs-examples: ## run full Python examples and generate pages with their plots
$(PYTHON) docs/tools/examples.py

docs-dev: ## live preview at http://localhost:4321/template-python/
$(NOTEBOOKS) convert
$(PYTHON) docs/tools/examples.py
cd docs && $(DOCS_ENV) DOCS_VALIDATE_LINKS=false npm run dev

docs-build: ## the static site in docs/dist, as in CI
$(NOTEBOOKS) convert
$(PYTHON) docs/tools/examples.py
cd docs && npm run check:mdx && $(DOCS_ENV) npm run build

docs-preview: ## serve docs/dist
cd docs && npm run preview

docs-clean: ## remove generated pages, assets and build output
$(NOTEBOOKS) clean
rm -rf docs/src/content/docs/full-examples docs/public/full-examples
rm -rf docs/dist docs/.astro
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ Commits](https://www.conventionalcommits.org/); see

The documentation in `docs/` is an Astro + Starlight site: hand-written
pages, the notebooks in `tutorials/` executed and published as pages,
and the API reference generated from the docstrings with
complete Python scripts in `examples/` published with their plots, and
the API reference generated from the docstrings with
[starlight-pydocs](https://ewels.github.io/starlight-pydocs/). It needs
Node 22 or newer.

``` bash
make docs-install # npm packages and the Python docs extra
make docs-notebooks # execute tutorials/*.ipynb and convert them to pages
make docs-examples # run examples/*.py and publish their plots
make docs-dev # live preview at http://localhost:4321/template-python/
make docs-build # the static site in docs/dist
```
Expand All @@ -115,4 +117,4 @@ its release date), and add the release notes to `CHANGELOG.md`. The push
to `main` creates a GitHub release with a `vX.Y.Z` tag and publishes the
package to PyPI with trusted publishing (OIDC). The one-time PyPI and
GitHub configuration is described in the [publishing
guide](https://max-models.github.io/template-python/development/publishing/).
tutorial](https://max-models.github.io/template-python/development/publishing/).
6 changes: 4 additions & 2 deletions README.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ Commit messages follow [Conventional Commits](https://www.conventionalcommits.or
## Build docs

The documentation in `docs/` is an Astro + Starlight site: hand-written pages, the notebooks
in `tutorials/` executed and published as pages, and the API reference generated from the
in `tutorials/` executed and published as pages, complete Python scripts in `examples/`
published with their plots, and the API reference generated from the
docstrings with [starlight-pydocs](https://ewels.github.io/starlight-pydocs/). It needs
Node 22 or newer.

```bash
make docs-install # npm packages and the Python docs extra
make docs-notebooks # execute tutorials/*.ipynb and convert them to pages
make docs-examples # run examples/*.py and publish their plots
make docs-dev # live preview at http://localhost:4321/template-python/
make docs-build # the static site in docs/dist
```
Expand All @@ -113,4 +115,4 @@ Before merging a release to `main`, update the version in `pyproject.toml`,
notes to `CHANGELOG.md`. The push to `main` creates a GitHub release with a `vX.Y.Z` tag and
publishes the package to PyPI with trusted publishing (OIDC). The one-time PyPI and GitHub
configuration is described in the
[publishing guide](https://max-models.github.io/template-python/development/publishing/).
[publishing tutorial](https://max-models.github.io/template-python/development/publishing/).
2 changes: 2 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ node_modules/
.cache/
public/tutorials/
src/content/docs/tutorials/*.mdx
public/full-examples/
src/content/docs/full-examples/
4 changes: 4 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export default defineConfig({
label: 'Tutorials',
items: [{ autogenerate: { directory: 'tutorials' } }],
},
{
label: 'Full examples',
items: [{ autogenerate: { directory: 'full-examples' } }],
},
{
label: 'Development',
items: [
Expand Down
45 changes: 45 additions & 0 deletions docs/public/tutorials/example-tutorial/example_tutorial.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0",
"metadata": {},
"source": [
"# Example guide\n",
"\n",
"Run a small example and view its output."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1",
"metadata": {},
"outputs": [],
"source": [
"print(\"Example guide published in the docs!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions docs/src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const shouldRenderSearch =
const navLinks = [
{ label: 'Getting started', href: withBase('/getting-started/installation/'), section: withBase('/getting-started/') },
{ label: 'Tutorials', href: withBase('/tutorials/'), section: withBase('/tutorials/') },
{ label: 'Full examples', href: withBase('/full-examples/'), section: withBase('/full-examples/') },
{ label: 'Development', href: withBase('/development/docs/'), section: withBase('/development/') },
{ label: 'API', href: withBase('/api/app/'), section: withBase('/api/') },
];
Expand Down
27 changes: 26 additions & 1 deletion docs/src/components/NotebookHeader.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Props {
status?: 'executed' | 'not run';
}
const { download, source, status = 'executed' } = Astro.props;
const filename = download.split('/').at(-1) ?? 'tutorial.ipynb';
const github = `https://github.com/max-models/template-python/blob/devel/${source}`;
const notes = {
executed: 'Run when the site was built.',
Expand All @@ -20,11 +21,35 @@ const notes = {
---

<div class="notebook-header not-content">
<a class="notebook-button" href={withBase(download)} download>Download notebook</a>
<a class="notebook-button" href={withBase(download)} download={filename} data-notebook-download>Download notebook</a>
<a class="notebook-button secondary" href={github}>View on GitHub</a>
<span class="notebook-note">{notes[status]}</span>
</div>

<script>
document.querySelectorAll<HTMLAnchorElement>('a[data-notebook-download]').forEach((link) => {
link.addEventListener('click', async (event) => {
event.preventDefault();
try {
const response = await fetch(link.href);
if (!response.ok) throw new Error(`Notebook download failed: ${response.status}`);
const blob = new Blob([await response.arrayBuffer()], { type: 'application/x-ipynb+json' });
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = link.download;
anchor.click();
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch {
const anchor = document.createElement('a');
anchor.href = link.href;
anchor.download = link.download;
anchor.click();
}
});
});
</script>

<style>
.notebook-header {
display: flex;
Expand Down
13 changes: 11 additions & 2 deletions docs/src/content/docs/development/docs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Building the docs
description: How this documentation site is built from Markdown pages, notebooks and docstrings.
description: How this documentation site is built from Markdown pages, Jupyter tutorials and docstrings.
---

The site in `docs/` is built with [Astro](https://astro.build/) and
Expand All @@ -9,6 +9,8 @@ The site in `docs/` is built with [Astro](https://astro.build/) and
- **Hand-written pages** in `docs/src/content/docs/`, as Markdown or MDX.
- **Tutorials**, converted from the Jupyter notebooks in `tutorials/` by `docs/tools/notebooks.py`.
Each notebook is executed and its outputs (text, images, tables) are written into an MDX page.
- **Full examples**, built from Python scripts in `examples/` by `docs/tools/examples.py`.
Each page shows the module docstring, the complete source file, and its Matplotlib plots.
- **API reference**, generated from the docstrings by
[starlight-pydocs](https://ewels.github.io/starlight-pydocs/), one page per module.

Expand All @@ -22,6 +24,7 @@ The site in `docs/` is built with [Astro](https://astro.build/) and
```bash
make docs-install # npm packages and the Python docs extra
make docs-notebooks # execute tutorials/*.ipynb and convert them to pages
make docs-examples # run examples/*.py and publish their plots
make docs-dev # live preview at http://localhost:4321/template-python/
make docs-build # the static site in docs/dist, as in CI
make docs-preview # serve docs/dist
Expand All @@ -33,7 +36,7 @@ make docs-clean # remove generated pages and build output

## Writing tutorials

Put a notebook in `tutorials/`. Its first `# Heading` becomes the page title and the first
Put a Jupyter notebook in `tutorials/`. Tutorials are authored only as `.ipynb` files. Its first `# Heading` becomes the page title and the first
paragraph its description. Cell tags control the output:

| Tag | Effect |
Expand All @@ -44,3 +47,9 @@ paragraph its description. Cell tags control the output:
| `raises-exception` | an error output is shown, not a failure |

Math in `$...$` and `$$...$$` is rendered with KaTeX.

## Writing full examples

Put a Python script in `examples/` with a module docstring. Its first line becomes the page
title and the rest becomes the description. Leave Matplotlib figures open at the end of the
script so the docs builder can save them as plots. The complete script is shown on the page.
4 changes: 4 additions & 0 deletions docs/src/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
<Card title="Tutorials" icon="document">
Jupyter notebooks in `tutorials/` are executed and published as pages of this site.
</Card>
<Card title="Full examples" icon="document">
Complete Python scripts in `examples/` are shown with their plots.
</Card>
<Card title="API reference" icon="setting">
Every module, class and function is documented from the docstrings with starlight-pydocs.
</Card>
Expand All @@ -39,5 +42,6 @@ import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
<LinkCard title="Installation" href="/template-python/getting-started/installation/" description="Create an environment and install the package." />
<LinkCard title="Quickstart" href="/template-python/getting-started/quickstart/" description="Run the command line entry point." />
<LinkCard title="Tutorials" href="/template-python/tutorials/" description="Executed notebooks with their outputs." />
<LinkCard title="Full examples" href="/template-python/full-examples/" description="Complete scripts and their plots." />
<LinkCard title="API reference" href="/template-python/api/app/" description="Generated from the docstrings." />
</CardGrid>
Loading
Loading