ADR 020: Use MkDocs with Material theme for project documentation¶
Status¶
Accepted
Context¶
Every non-trivial project needs a documentation site that is easy to write, easy to maintain, and easy to deploy. The documentation tooling should:
- Use Markdown — The team already writes Markdown in READMEs, ADRs, and inline docs.
- Generate API docs — Automatically render docstrings so API reference stays in sync with code.
- Look professional — A polished theme with dark mode, search, and code highlighting.
- Stay in the Python ecosystem — Avoid adding Node.js or other runtime dependencies.
- Support local preview — Live-reload dev server for authoring.
Decision¶
Use MkDocs as the static site generator with the following stack:
| Component | Package | Purpose |
|---|---|---|
| Site generator | mkdocs>=1.6 |
Builds Markdown into a static HTML site |
| Theme | mkdocs-material>=9.4 |
Material Design theme with dark/light toggle, search, code copy |
| Markdown extensions | pymdown-extensions>=10.0 |
Tabbed content, admonitions, syntax highlighting |
| API docs | mkdocstrings[python]>=0.27 |
Auto-generates reference docs from Google-style docstrings |
Configuration lives in a single file:
# mkdocs.yml
site_name: simple-python-boilerplate
docs_dir: docs
theme:
name: material
plugins:
- search
- mkdocstrings
Documentation source lives in docs/ alongside ADRs, notes, and design docs.
Consequences¶
Positive¶
- Markdown-native — No new syntax to learn; same format as READMEs and ADRs
- API docs stay in sync —
mkdocstringsrenders docstrings directly from source code - Fast iteration —
mkdocs serveprovides live-reload during authoring - Rich features out of the box — Material theme includes search, dark mode, code copy, navigation tabs
- Python-only toolchain — No Node.js or npm required
- Static output — Builds to plain HTML; can be hosted anywhere (GitHub Pages, S3, etc.)
- Hatch integration —
hatch run docs:serveandhatch run docs:buildprovide convenient entry points
Negative¶
- Extra dependencies — Four packages added to
[project.optional-dependencies.docs] - Flat docs directory — All documentation lives in
docs/, which keeps paths simple but mixes MkDocs content with ADRs and design docs - Material theme lock-in — Heavily using Material-specific features makes switching themes harder
- Build step required — Must run
mkdocs buildto produce the site; not just raw Markdown
Neutral¶
- Documentation dependencies are isolated in an optional
docsextra, not installed by default - MkDocs configuration is declarative YAML, consistent with other project config files
Alternatives Considered¶
Sphinx¶
The traditional Python documentation tool, using reStructuredText.
Rejected because: reStructuredText has a steeper learning curve than Markdown. Sphinx configuration is more complex (conf.py with imperative Python). The team already writes Markdown everywhere else in the project.
Docsify / VitePress / Docusaurus¶
JavaScript-based documentation generators.
Rejected because: Adds a Node.js dependency to a Python-only project. Contradicts the goal of keeping the toolchain within the Python ecosystem.
Plain Markdown (no generator)¶
Serve docs directly from GitHub's Markdown rendering.
Rejected because: No search, no API docs generation, no consistent theme, no local preview with live-reload. Adequate for small projects but doesn't scale.
Jupyter Book¶
Sphinx-based tool with MyST Markdown support.
Rejected because: Heavier dependency tree. Better suited for computational narratives and tutorials than API reference documentation.
Implementation¶
- mkdocs.yml — Site configuration (theme, plugins, nav, extensions)
- docs/ — Documentation source files
- pyproject.toml — Dependencies in
[project.optional-dependencies.docs] - pyproject.toml — Hatch scripts in
[tool.hatch.envs.docs.scripts]:hatch run docs:serve— Live-reload dev serverhatch run docs:build— Build static site (strict mode)