MkDocs Custom Plugin Development
MkDocs plugins are Python classes connected via build lifecycle events. They can modify page content, navigation, configuration, and final HTML output.
Plugin Structure
# my_mkdocs_plugin/__init__.py
from mkdocs.plugins import BasePlugin
from mkdocs.config import config_options
from mkdocs.config.base import Config
class MyPluginConfig(Config):
api_url = config_options.Type(str, default='')
cache_timeout = config_options.Type(int, default=3600)
enabled = config_options.Type(bool, default=True)
class MyMkDocsPlugin(BasePlugin[MyPluginConfig]):
def on_config(self, config):
"""Called after loading mkdocs.yml"""
if not self.config.enabled:
return config
# Can modify global config
config['extra']['my_plugin_version'] = '1.0.0'
return config
def on_page_markdown(self, markdown, page, config, files):
"""Modify Markdown before HTML conversion"""
# Replace custom tags
markdown = markdown.replace('{{VERSION}}', self._get_version())
return markdown
def on_page_content(self, html, page, config, files):
"""Modify rendered page HTML"""
# Add custom banner to specific pages
if page.meta.get('deprecated'):
banner = '<div class="deprecated-notice">⚠️ Deprecated section</div>'
html = banner + html
return html
def on_page_context(self, context, page, config, nav):
"""Add variables to template context"""
context['api_status'] = self._get_api_status()
return context
def on_files(self, files, config):
"""Add/remove files from build"""
return files
def on_nav(self, nav, config, files):
"""Modify navigation"""
return nav
def on_post_build(self, config):
"""After build completion"""
self._notify_build_complete()
def _get_version(self):
import requests
resp = requests.get(f"{self.config.api_url}/version", timeout=5)
return resp.json().get('version', 'unknown')
Registration via entry_points
# pyproject.toml
[project.entry-points."mkdocs.plugins"]
my-plugin = "my_mkdocs_plugin:MyMkDocsPlugin"
# mkdocs.yml
plugins:
- my-plugin:
api_url: https://api.myproject.com
cache_timeout: 7200
Plugin for Generating API Pages
class ApiDocsPlugin(BasePlugin):
"""Generates documentation pages from OpenAPI spec"""
def on_files(self, files, config):
import yaml
import requests
from mkdocs.structure.files import File
spec = requests.get(self.config.openapi_url).json()
for path, methods in spec['paths'].items():
for method, operation in methods.items():
content = self._generate_endpoint_page(path, method, operation, spec)
# Create virtual file without disk writing
file = File.generated(
config,
f"api/{self._path_to_slug(path)}-{method}.md",
content=content,
)
files.append(file)
return files
def _generate_endpoint_page(self, path, method, operation, spec):
return f"""# {operation.get('summary', path)}
**{method.upper()}** `{path}`
{operation.get('description', '')}
## Parameters
{self._render_parameters(operation.get('parameters', []))}
## Responses
{self._render_responses(operation.get('responses', {}))}
"""
Developing a plugin for generating pages from external sources takes 2–5 days.







