mkdocs-markdoc
An MkDocs plugin that completely replaces the default Python-Markdown renderer
with Stripe's Markdoc. Every .md page in your
docs site is parsed and rendered by Markdoc's HTML renderer — no React
required.
How it works
MkDocs ──on_page_markdown──▶ plugin.py ──stdin──▶ markdoc_runner.js
│
HTML string ◀──stdout──────────────┘
The Python plugin hooks into on_page_markdown, pipes the raw Markdown to a
bundled Node.js script via subprocess, and returns the HTML string that
MkDocs injects into the theme template.
Prerequisites
| Requirement | Minimum version |
|---|---|
| Python | 3.9 |
| MkDocs | 1.5 |
| Node.js | 18 LTS |
| npm | 8 |
Installation
1 — Install the Python package
# From the repo root (editable/development install)
pip install -e .
# Or once published to PyPI
pip install mkdocs-markdoc
2 — Install the Node.js Markdoc library
The @markdoc/markdoc npm package must be resolvable by Node.js when it runs
the bundled markdoc_runner.js script. Install it in one of these
locations (Node's module resolution will find it):
# Option A – global install (simplest for local dev / CI)
npm install -g @markdoc/markdoc
# Option B – local install in your docs project root
cd /path/to/your/docs-project
npm install @markdoc/markdoc
3 — Enable the plugin in mkdocs.yml
# mkdocs.yml
site_name: My Docs
plugins:
- markdoc # ← add this; remove or comment out the default 'search'
# plugin only if you no longer need it
Note: MkDocs' built-in
searchplugin is independent of the Markdown renderer and can be kept alongsidemarkdoc:plugins: - search - markdoc
Configuration options
All options are optional.
plugins:
- markdoc:
# Path to the Node.js executable.
# Default: "node" (resolved via $PATH)
node_path: /usr/local/bin/node
# Path to a JS or JSON file that exports a Markdoc config object.
# When omitted, Markdoc uses its built-in defaults (standard Markdown
# nodes, no custom tags or functions).
markdoc_config: docs/markdoc.config.js
# Milliseconds to wait for the Node subprocess before raising an error.
# Default: 30000 (30 seconds)
timeout: 30000
Example markdoc.config.js
// docs/markdoc.config.js
const { nodes, Tag } = require("@markdoc/markdoc");
module.exports = {
tags: {
callout: {
render: "div",
attributes: {
type: { type: String, default: "note" },
},
},
},
nodes: {
// Override the default heading to add anchor IDs
heading: {
...nodes.heading,
render: "h1",
},
},
};
Running the docs locally
mkdocs serve
Caveats & trade-offs
- Markdoc syntax differs from CommonMark. Markdoc is a superset of Markdown, but some edge-cases render differently. Review the Markdoc syntax reference when migrating an existing docs site.
- Node.js subprocess overhead. Each page spawns (and immediately exits) one Node process. For large sites with hundreds of pages the build time will increase compared to the native Python-Markdown renderer. If this becomes a bottleneck, consider batching pages in a future version.
- MkDocs extensions are bypassed. Because we skip Python-Markdown entirely,
any
markdown_extensions:listed inmkdocs.ymlwill have no effect. Equivalent behaviour must be implemented via Markdoc tags/nodes/functions.
Metadata
Release files for mkdocs-markdoc 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mkdocs_markdoc-0.2.1.tar.gz | 13.4 kB | With provenance | Details for mkdocs_markdoc-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mkdocs_markdoc-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for mkdocs_markdoc-0.2.1-py3-none-any.whl |
Total release size: 28.3 kB
Release files / mkdocs_markdoc-0.2.1.tar.gz
| Download URL | mkdocs_markdoc-0.2.1.tar.gz |
|---|---|
| Size | 13.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
72e1cdeab65071adb4ea14140bbeb6c8aa560b43309172c03b51a4584c882410
|
|
BLAKE2b-256 checksum How to use checksums |
4a1db455b3e971c2084658a6dabf5ebd824a70f80ba77de6cecb39b9a11d25e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 23, 2026.
Transparency logRelease files / mkdocs_markdoc-0.2.1-py3-none-any.whl
| Download URL | mkdocs_markdoc-0.2.1-py3-none-any.whl |
|---|---|
| Size | 14.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
938d6e3ea8b7b89b7f94d153a3047b243e36a06daadbfe0e5fc06ed644b82905
|
|
BLAKE2b-256 checksum How to use checksums |
e7c52d97699b373a9708c42f4f406d18f8166701714dff4a4fa296860974fcda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 23, 2026.
Transparency logSecurity for mkdocs-markdoc 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mkdocs_markdoc-0.2.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.