# ADR 0001: MkDocs vs. ProperDocs for the documentation site

- **Status**: Accepted
- **Date**: 2026-04-18
- **Deciders**: Anteroom maintainers
- **Issue**: [#1430](https://github.com/troylar/anteroom/issues/1430)

## Decision

**Pin `mkdocs<2` in the project's direct dependencies.** Do not migrate to ProperDocs at this time. Revisit if and when MkDocs 2.0 is actually announced with a release date, or if ProperDocs reaches meaningful maturity (see "Revisit triggers" below).

## Context

Starting 2026-03, installations of `mkdocs-material` began emitting a promotional warning from a separate package — **ProperDocs**, a hard fork of MkDocs 1.x by Tom Christie (the Encode author behind Starlette, HTTPX, Django REST Framework). The warning claims:

> MkDocs may break support for all existing plugins and themes soon! The owner of MkDocs has completely abandoned maintenance of the project, and instead is planning to publish a "version 2" which will not support any existing themes, plugins or even your configuration files. This v2 may eventually replace what you download with `pip install mkdocs`, suddenly breaking the build of your existing site.

This raised two distinct questions for Anteroom, which ships `aroom docs` as a user-visible subcommand that invokes `python -m mkdocs`:

1. Is MkDocs 2.0 imminent enough that a silent upstream bump could break `aroom docs`?
2. Is ProperDocs a production-appropriate replacement today?

## Evidence gathered (Phase 0 research)

### MkDocs upstream

- **PyPI**: latest release `mkdocs 1.6.1` on **2024-08-30** — no PyPI release in ~20 months as of this ADR.
- **GitHub** (`mkdocs/mkdocs`): last commit on **2025-10-20** — ~6 months idle as of this ADR. Still responsive to occasional merges.
- **v2 evidence**: branches `next` and `port2` exist in the repo. No release date has been announced publicly. No v2 PyPI pre-release, alpha, or beta.
- **Release cadence before 2024**: 1.5.x series released mid-2023 through early-2024; 1.6.0 in 2024-08; 1.6.1 a few weeks later; then silence.

### ProperDocs

- **PyPI**: `properdocs 1.6.7`, first release **2026-03-16**, latest **2026-03-20**. Three PyPI releases total.
- **GitHub** (`ProperDocs/properdocs`): created **2026-03-09**, last push **2026-04-07**. **96 stars**, **6 forks**, **5 open issues**. License is `BSD-2-Clause` per PyPI metadata.
- **Maintainer**: Tom Christie (Encode — Starlette, HTTPX, Django REST Framework). High individual credibility for Python web infrastructure.
- **Governance**: one-person project at time of writing; no public governance document, no multi-maintainer structure.
- **Technical design**: a real fork of MkDocs 1.6 (1500+ LOC in core modules plus `commands/`, `config/`, `structure/`, `themes/`, `templates/`, `livereload/`, `contrib/`, `localization/`). Module `properdocs.replacement` installs a `sys.meta_path` finder that transparently redirects `import mkdocs.*` to `properdocs.*`, so existing MkDocs plugins work unchanged against ProperDocs.
- **Binary/module rename**: `mkdocs build` → `properdocs build`; `python -m mkdocs` → `python -m properdocs`. The rename is the primary caller-facing change.
- **Promotional warning**: ships an opt-in `properdocs.replacement_warning.setup()` helper that plugin authors can add to their `__init__.py` to display the quoted warning when users run `mkdocs`. This is the mechanism by which `mkdocs-material` surfaces the notice.

### Drop-in compatibility — verified

Scratch venv at `/tmp/pd` with:
```
pip install properdocs mkdocs-material mkdocs-minify-plugin mkdocs-redirects pygments
```

Running our actual build:
```
properdocs build --strict -f mkdocs.yml -d /tmp/properdocs-site
```

Result: **clean `--strict` build**, `Documentation built in 2.16 seconds`, zero errors, zero warnings. Our existing `mkdocs.yml` (including `pymdownx.*`, `mkdocs-minify-plugin`, `mkdocs-redirects`, theme palette, extra CSS) resolves identically. Generator metadata in emitted HTML reads `mkdocs-ProperDocs 1.6.7, mkdocs-material-9.7.6`.

The compatibility shim means ProperDocs is a genuine drop-in today. That resolves the "does it work?" question unambiguously.

### What about Material for MkDocs?

Material is still developed against MkDocs upstream (published by Squidfunk, Martin Donath). Material does not require ProperDocs; it just works under either. The promotional warning is a recent addition to Material's install chain, not a commitment by Material to switch.

## Decision rationale

The decision is "pin `mkdocs<2`" rather than migrate to ProperDocs now or do nothing.

### Why not "migrate to ProperDocs now" (option a)

- **ProperDocs is 5 weeks old at time of ADR.** Tom Christie's personal track record is strong, but that doesn't substitute for a project proven in production across dozens of codebases over months or years.
- **96 stars, 6 forks, 5 open issues** — a very small community. Recovery from a maintainer bus-factor event is untested.
- **Binary rename has user-visible cost** for `aroom docs`: we'd update `_exec_mkdocs_serve()` (and now `_bg-worker-docs` after #1439 landed) to invoke `properdocs` instead of `mkdocs`, update docs and release notes, and absorb any follow-on issues.
- **No evidence of imminent MkDocs 2 breakage.** `next`/`port2` branches are not a release. Until a 2.0-rc lands on PyPI, the "silent breakage" scenario is hypothetical.
- The asymmetry is important: migrating TO ProperDocs and then BACK to MkDocs is a bigger ordeal than waiting.

### Why not "do nothing" (option c)

- The warning's specific concern — `pip install mkdocs` silently pulling a future incompatible 2.0 — is real, even if the timeline is unclear. A breaking bump could land on PyPI without coordination.
- A one-line version pin eliminates that risk for zero real cost. Staying reactive is worse than cheap prevention when the prevention costs nothing.

### Why "pin `mkdocs<2`" (option b, accepted)

- **Bounds the specific risk** (a silent MkDocs 2.0 bump) at the cost of one version constraint.
- **No binary rename, no call-site churn, no new trust boundary.** The project continues using the well-known upstream under its semver contract.
- **Fully reversible.** If MkDocs 2 ships with a real migration path we want, lift the pin. If ProperDocs matures and we decide to migrate, that's a second decision documented in a follow-up ADR.
- **Keeps MkDocs 1.6.x features intact.** All our current functionality (plugins, theme, extensions, `--strict` gating) is stable and supported.

## Revisit triggers

This decision should be revisited if ANY of the following happens:

1. **MkDocs 2.0 is announced with a release date or lands on PyPI.** Whether 2.0 is truly incompatible or not, we'd need to re-evaluate and update the pin.
2. **ProperDocs reaches 6+ months of age, has multiple active maintainers, and has released at least one stable minor beyond 1.6.x.** At that point it's a viable production dependency.
3. **MkDocs upstream releases a 1.7.x with features we need.** We'd loosen the pin to `<2` on a newer 1.x line.
4. **A critical CVE lands in MkDocs 1.6.x** and the upstream fix is in 2.x only. Forced migration decision.
5. **mkdocs-material pins against mkdocs 2.x exclusively** and stops supporting 1.x. Forced decision.

In all five cases, a follow-up issue should be opened citing this ADR and proposing a new decision.

## Follow-up work

Since the decision is (b) pin, a follow-up issue will be filed with the narrow implementation scope:

- Add `mkdocs<2` to `pyproject.toml` and `docs/requirements.txt`.
- Verify `aroom docs --build` still succeeds after the pin.

That follow-up was intentionally not created in this ADR so the ADR lands first and the follow-up can reference it by stable URL.

## Alternatives considered

- **(a) Migrate to ProperDocs now** — rejected because ProperDocs is 5 weeks old; too early to bet a shipping product's docs pipeline on it.
- **(c) Do nothing** — rejected because a silent MkDocs 2 PyPI bump is a real failure mode a version pin eliminates for free.
- **(d) Fork our own mkdocs** — not seriously considered; zero upside over (b).

## References

- MkDocs on PyPI: https://pypi.org/project/mkdocs/
- MkDocs on GitHub: https://github.com/mkdocs/mkdocs
- ProperDocs on PyPI: https://pypi.org/project/properdocs/
- ProperDocs on GitHub: https://github.com/ProperDocs/properdocs
- ProperDocs site: https://properdocs.org/
- Tom Christie's projects at Encode: https://www.encode.io/
- Nygard's ADR format: https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
- This issue: https://github.com/troylar/anteroom/issues/1430
