mkdocs-decision-records
Manage decision records with mkdocs in a customizable and minimal fashion.
Features
- Customizable status colors and lifecycle
- Enforces information to be present for ADRs
- Allows description being kept as markdown
- Opt-in generated index page listing all decision records
Demo
You can find a Demo on GitHub Pages
Installation
- Install
mkdocs-decision-recordsfrom the PyPi registry using your favorite package manager - Configure your
mkdocs.ymlplugins: - decision-records: # Folder where your decision records are located, defaults to adr decisions_folder: adr # Optional prefix to prepend to ticket numbers ticket_url_prefix: https://ticket.example.com/ # Configure amount of required deciders required_deciders_count: 1 # Configure the length of decision IDs (default: 3) decision_id_length: 3 # Enable validation that IDs match the configured length (default: false) # When enabled, IDs that don't match the configured length will be rejected validate_id_length: false # Generate an index.md listing all decision records (default: false) generate_index_page: false # Configure available stages and the badge colors lifecycle_stages: {status}: {color}
- Create your ADRs ensuring to add the frontmatter meta data:
--- id: 000 status: proposed | rejected | accepted | deprecated | … | superseded [superseded_by: <id it has been replaced with>] date: YYYY-MM-DD deciders: - decider 1 - decider 2 # Optional ticket ticket: FOO-1 --- ## Context and Problem Statement [Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.] ## Decision Drivers <!-- optional --> * [driver 1, e.g., a force, facing concern, …] * [driver 2, e.g., a force, facing concern, …] * … <!-- numbers of drivers can vary --> ## Considered Options * [option 1] * [option 2] * [option 3] ## Decision Outcome Chosen option: "[option 1]", because [justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force force | … | comes out best (see below)]. ## Pros and Cons of the Options <!-- optional --> ### [option 1] [example | description | pointer to more information | …] <!-- optional --> * Good, because [argument a] * Good, because [argument b] * Bad, because [argument c] * … <!-- numbers of pros and cons can vary --> ### [option 2] [example | description | pointer to more information | …] <!-- optional --> * Good, because [argument a] * Good, because [argument b] * Bad, because [argument c] * … <!-- numbers of pros and cons can vary --> ### [option 3] [example | description | pointer to more information | …] <!-- optional --> * Good, because [argument a] * Good, because [argument b] * Bad, because [argument c] * … <!-- numbers of pros and cons can vary --> ## Links <!-- optional --> * [Link type] [Link to ADR] <!-- example: Refined by [ADR-0005](0005-example.md) --> * … <!-- numbers of links can vary -->
Superseding ADRs
This plugin is opinionated about using superseded status.
When setting the status to superseded, make to sure also set superseded_by to the ADR id it has been replaced with.
---
# adr details
status: superseded
superseded_by: 123
---
<!-- Deprecated ADR -->
Generated decision index
On every build, the plugin writes a decision_index.json to the root of the built site (e.g. site/decision_index.json).
It contains one entry per decision record (templates excluded), and can be used to build custom search or listing
features on top of the generated site.
Each entry has the shape:
{
"id": "000",
"date": "2024-01-01",
"title": "Example decision",
"status": "accepted",
"url": "adr/000-example-decision/",
"deciders": ["Jane Doe"],
"ticket": "FOO-123",
"toc": "...",
"sections": [
{ "title": "Context and Problem Statement", "text": "..." }
],
"superseded_by": "001"
}
urlis the rendered page's URL, relative to the site root (join it with the site's base URL to get a link to the decision record)decidersandticketmirror the record's frontmatter;decidersis[]andticketisnullwhen not settocis the page's table of contents, as produced by MkDocssectionslists the page's headings with their rendered text contentsuperseded_byis only present whenstatusissuperseded
Generated index page
With generate_index_page: true, the plugin writes an index.md into the decisions folder (e.g.
adr/index.md) listing every decision record as a markdown table:
| ID | Date | Title | Status | Ticket | Deciders |
|---|---|---|---|---|---|
| 001 | 2021-03-26 | Mechanism to validate mjml code | accepted | FOO-100 | Jane, John, Jill |
- The template record (
id: 000) is never listed; if it is the only record, no file is written at all. - Rows are sorted by ID in ascending numeric order.
- The title cell links to the decision record and drops the id prefix the record pages show.
- The status cell renders the configured lifecycle badge.
- The
Ticketcolumn only exists whenticket_url_prefixis configured. - Only the first three deciders are listed; additional ones are summarized as
.... - While the option is enabled, an existing
index.mdin the decisions folder is overwritten.
The generated page is rendered like any other documentation page, so it works as a section landing
page for plugins that pick up a folder's index.md.
Motivation
I love ADRs and documenting decisions in general. This plugin makes it a bit easier, enforcing basic meta information while keeping the format open enough so you can do your thing.
Contributing
I love your input! I want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the configuration
- Submitting a fix
- Proposing new features
- Becoming a maintainer
To get started please read the Contribution Guidelines.
Development
Requirements
- Python 3.12+
- Poetry
Build
poetry install
Alternatives
- mkdocs-material
- Needs to use the theme
- ADR graph
- mkdocs-macros-adr-summary
- works entirely with macros
- no metadata table at the top
Metadata
Release files for mkdocs-decision-records 3.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mkdocs_decision_records-3.2.0.tar.gz | 24.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mkdocs_decision_records-3.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.1 kB
Release files / mkdocs_decision_records-3.2.0.tar.gz
| Download URL | mkdocs_decision_records-3.2.0.tar.gz |
|---|---|
| Size | 24.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
28d8be33260e71176acdc6d1c5de5e30ed72449b85ffb69a0fb75eb1ebe0531e
|
|
BLAKE2b-256 checksum How to use checksums |
f3a6d39cfbbd7d12a17ea74b3ff6697d20cca2c4977a95244f4196199c518977
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","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}
|
Release files / mkdocs_decision_records-3.2.0-py3-none-any.whl
| Download URL | mkdocs_decision_records-3.2.0-py3-none-any.whl |
|---|---|
| Size | 28.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
42c0c6f2075bf61f223763bc41435c0ee018c073b514ef0371ca19a72e451e08
|
|
BLAKE2b-256 checksum How to use checksums |
2f31a2b84a4591d82b6114560c03a5302cba08813f25dc4e491e6d340f7fe2cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","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}
|