Versioning Documentation with ProperDocs and mike
If you're using ProperDocs, versioned publishing should be straightforward. Build the docs for a release, publish them under a stable version label, and leave older versions alone. Until mike v2.2.0, that simple workflow still carried a nagging question: did the rest of the tooling really understand ProperDocs, or was it still assuming MkDocs under the hood?
mike publishes each supported release as its own directory tree on a deployment branch, usually gh-pages. Old versions stay put even when today's main branch moves on. In the mike v2.2.0 release, that process got simpler for ProperDocs users: when the properdocs package is installed, mike runs properdocs instead of mkdocs. No separate workflow branch. No wrapper script. No extra switch to remember.
The release notes include:
Add support for ProperDocs.
In practice, that means mike now checks for the properdocs package first. When it's present, mike uses the properdocs command and includes properdocs.yml and properdocs.yaml in its default configuration file search order.
That is exactly the kind of compatibility work you want in a documentation pipeline. Install the generator you actually use, install mike, and let tool detection do the boring part correctly.
ProperDocs exists because some teams need the MkDocs 1.x operating model to keep working. They have plugins, theme overrides, snippets, macros, and workflow assumptions built around that ecosystem. Versioned publishing shouldn't force those teams into a second set of build logic.
Before this change, the friction wasn't that versioned docs were impossible. The friction was that ProperDocs users had to think too much about whether the surrounding tooling still assumed MkDocs. That extra uncertainty is how CI jobs grow unnecessary conditionals and side paths.
With mike v2.2.0, the command flow is really simple:
Model¶
mike isn't a documentation generator. ProperDocs builds the site and mike publishes versioned copies of that built site onto a deployment branch.
That separation is useful because it keeps the release artifact stable. When you publish 1.4, you want the docs for 1.4 to stay there even after main moves on to 1.5 or 2.0.
The deployment branch ends up looking roughly like this:
Each version directory is already-built documentation. You aren't asking the toolchain to rebuild the previous release documentation every time you publish.
Minimal Setup¶
Use a virtual environment and pin the docs stack like any other build dependency.
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "properdocs" "mike>=2.2.0,<3"
In the repository, pin the versions in a requirements file with your theme and plugins:
properdocs
mkdocs-materialx==10.1.6
mkdocs-glightbox==0.5.2
mkdocs-minify-plugin==0.8.0
mike>=2.2.0,<3
One detail matters here: if you want mike to use ProperDocs, install ProperDocs in the environment that runs the publish job. The detection is package-based.
Minimal Configuration¶
Most sites don't need much beyond a correct site_url and a normal ProperDocs configuration. When you want the version selector behavior to be explicit, put mike in properdocs.yml:
site_name: Example with ProperDocs
site_url: https://docs.example.com/
remote_branch: gh-pages
remote_name: origin
plugins:
- search
- mike:
alias_type: symlink
canonical_version: latest
version_selector: true
If the site lives under a subpath, make site_url match the public address. Version selectors and canonical URLs get weird fast when the site thinks it lives somewhere else.
Release Commands¶
Build locally first:
Publish a release line and mark it as latest:
Move latest when you ship the next minor line:
Set the default landing version:
Preview the deployed versioned site instead of just the current source tree:
That last command is worth calling out. properdocs serve previews the working tree you are editing. mike serve previews what is already published on the deployment branch. Those are different checks, and you usually want both.
Policy¶
For most documentation sets, a simple version policy is enough:
- Publish immutable
major.minorversions. - Use
latestfor the newest generally available release.
If every merge to main rewrites public docs, you are not really doing versioned publishing. You are just redeploying the present. mike is most useful when release labels mean something stable.
Outcome¶
The important part of mike v2.2.0 isn't that it added one more supported generator, but that ProperDocs users can now keep a normal versioned-docs workflow without building a parallel publishing story around generator detection.