Sphinx extension to document Architecture Decision Records (ADRs)
Project description
sphinx-adr
A Sphinx extension for documenting Architecture Decision Records (ADRs) directly inside your Sphinx documentation.
Inspired by ablog (for the directive-based authoring model) and log4brains (for the timeline UI with status badges).
Features
.. adr::directive -- mark any Sphinx page as an ADR with structured metadata (id, status, date, authors, tags)... adrlist::directive -- generate a vertical timeline / decision log with filtering and sorting.- Sidebar navigation -- compact timeline sidebar on ADR pages (ablog-style
html_sidebarspattern). - Status badges -- color-coded pills for Proposed, Accepted, Deprecated, and Superseded.
- ID badges -- teal monospace badge for each record's identifier, visually distinct from status and tags.
- Timeline layout -- vertical timeline with status-colored glowing dots, cards, excerpts, and tag pills.
- Works with any Sphinx theme -- tested with alabaster, pydata-sphinx-theme, and sphinx-book-theme.
- Dark mode support -- automatically adapts to light/dark mode on pydata-sphinx-theme, sphinx-book-theme, and furo.
- Incremental & parallel safe -- integrates cleanly with Sphinx's build system.
Quick start
1. Install
pip install sphinx-adr
2. Enable the extension
In your Sphinx conf.py:
extensions = ["sphinx_adr"]
# Path to ADR documents (default: "adr")
adr_path = "adr"
# Show the ADR sidebar only on ADR pages (ablog-style pattern)
html_sidebars = {
"adr/*": ["adr_nav.html"],
}
3. Write an ADR
Create a file such as adr/0001-use-sphinx.rst:
ADR-0001: Use Sphinx for Documentation
=======================================
.. adr::
:id: ADR-0001
:status: Accepted
:date: 2024-01-15
:authors: Alice, Bob
:tags: tooling, documentation
We will use Sphinx as our primary documentation tool.
Context and Problem Statement
-----------------------------
We need a documentation system that supports multiple output formats,
is well-integrated with Python projects, and allows us to write
documentation alongside the code.
Decision Outcome
----------------
Chosen option: **Sphinx**, because it is the de-facto standard for
Python projects and has a rich extension ecosystem.
4. Create a decision log page
Architecture Decision Log
=========================
.. adrlist::
.. toctree::
:hidden:
0001-use-sphinx
0002-adopt-adr-process
5. Build
sphinx-build -b html docs docs/_build/html
Directive reference
.. adr::
Marks the current page as an ADR. Place it near the top of the document, right after the title.
| Option | Required | Description |
|---|---|---|
:id: |
yes | Unique identifier for the ADR, e.g. ADR-0001 |
:status: |
yes | One of Proposed, Accepted, Deprecated, Superseded |
:date: |
no | Date string, e.g. 2024-01-15 |
:authors: |
no | Comma-separated author names |
:tags: |
no | Comma-separated tags for categorisation |
:superseded-by: |
no | Docname of the ADR that supersedes this one (when status is Superseded) |
The directive body is used as a short excerpt displayed in the timeline listing.
.. adrlist::
Generates a timeline-based listing of all ADRs in the project.
| Option | Default | Description |
|---|---|---|
:status: |
(all) | Comma-separated statuses to include, e.g. Accepted, Proposed |
:tags: |
(all) | Comma-separated tags to filter by |
:sort: |
date-desc |
Sort order: date-desc, date-asc, or status |
Configuration
| Config value | Default | Description |
|---|---|---|
adr_path |
"adr" |
Directory containing ADR documents |
adr_statuses |
["Proposed", "Accepted", "Deprecated", "Superseded"] |
Allowed status values |
Sidebar setup (ablog-style)
The extension provides an adr_nav.html sidebar template. Use Sphinx's html_sidebars to control which pages display it:
# Show ADR sidebar only on pages under adr/
html_sidebars = {
"adr/*": ["adr_nav.html"],
}
Regular pages keep their normal theme sidebar. This follows the same pattern as ablog.
Interactive controls
Timeline
- Hover on a timeline card to see an elevated shadow and glowing status dot.
- Click the title link to navigate to the full ADR document.
- Filter ADRs by status or tags using
.. adrlist::options.
Sidebar navigation
- Current page is highlighted with bold text and link color.
- Hover on any entry to see the title highlighted and dot glow.
- Each entry shows the ID badge, title, and status pill at a glance.
Theme compatibility
| Theme | Light mode | Dark mode | Notes |
|---|---|---|---|
| alabaster | yes | -- | Sphinx default, no dark mode |
| pydata-sphinx-theme | yes | yes | Toggle via navbar switcher |
| sphinx-book-theme | yes | yes | Built on pydata, same mechanism |
| furo | yes | yes | Via prefers-color-scheme |
Development
Prerequisites
- Python 3.13+
- uv
Setup
git clone https://github.com/bngoy/sphinx-adr.git
cd sphinx-adr
# Install in development mode
uv sync --extra dev
Common commands
# Run tests
uv run pytest tests/ -v
# Lint and format
uv run ruff check .
uv run ruff format .
# Build demo docs
uv run sphinx-build -b html docs docs/_build/html
# Build theme examples (requires examples extra)
uv sync --extra examples
uv run sphinx-build -b html examples/pydata-theme examples/pydata-theme/_build/html
uv run sphinx-build -b html examples/book-theme examples/book-theme/_build/html
uv run sphinx-build -b html examples/alabaster examples/alabaster/_build/html
Project structure
sphinx-adr/
├── VERSION # Single source of truth for package version
├── pyproject.toml # Package metadata, build config, ruff config, uv scripts
├── sphinx_adr/
│ ├── __init__.py # Extension setup, config values, version
│ ├── directives.py # AdrDirective, AdrListDirective
│ ├── nodes.py # Custom docutils nodes (adr_meta, adr_list)
│ ├── collector.py # Metadata collection & timeline rendering
│ ├── templates/
│ │ └── adr_nav.html # Sidebar navigation Jinja2 template
│ └── static/
│ └── sphinx_adr.css # Timeline styling, status/ID badges, dark mode
├── docs/ # Demo site (dogfoods the extension)
│ ├── conf.py
│ ├── index.rst
│ └── adr/ # Sample ADRs
├── examples/ # Theme-specific examples
│ ├── alabaster/
│ ├── pydata-theme/
│ └── book-theme/
├── tests/
│ ├── conftest.py # make_project fixture
│ └── test_extension.py # 7 tests
└── .github/workflows/
├── ci.yml # Lint + test on every push/PR
├── auto-tag.yml # Tag repo from VERSION on PR merge
└── release.yml # Build and publish to PyPI on tag
License
Apache 2.0 -- see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sphinx_adr-0.2.0.tar.gz.
File metadata
- Download URL: sphinx_adr-0.2.0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d361e256889646f3cf96e4eecee167123470a804c956487bc68b26add1916657
|
|
| MD5 |
9bd4e48301e70f3b3346f70040567516
|
|
| BLAKE2b-256 |
90fbea6fb11559743927355d9132e5e4f817d28daf1ab007a13b05c2d04401a2
|
File details
Details for the file sphinx_adr-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sphinx_adr-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7c1b7183592e0b1d7ab3b15fdfa732b1fb6e36f6fe5b4ecbe6fff0eafd7126d
|
|
| MD5 |
3ff0d187b941ca928dffdefe0876f08c
|
|
| BLAKE2b-256 |
1ff07d5ca092cdf987006d9f5cbe854cf0dddc89ff732b363e98403c858a5a5b
|