Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

richdocs

A batteries-included documentation experience for MkDocs Material.

Shiki syntax highlighting · runnable live code · API-symbol hover & auto-linking · mkdocstrings enum/decorator badges · a polished collapsible TOC — all from a single plugin entry.

PyPI Python CI License

Live demo →


Why

MkDocs Material is excellent, but a great API-docs site usually means hand-wiring a pile of hooks, JavaScript, CSS, and mkdocstrings template overrides — and then re-doing it for the next project. richdocs packages that whole experience into one configurable plugin. The default look is the VS Code "Shades of Purple" theme; everything is overridable.

Features

  • 🎨 Shiki syntax highlighting — VS Code-accurate highlighting at runtime (the default theme is Shades of Purple), in both code blocks and inline code.
  • ▶️ Runnable live code — execute Python/shell blocks against a local Jupyter kernel, right in the page (dev only).
  • 🔗 API-symbol hover & auto-linking — inline `Symbol` mentions link to your mkdocstrings reference automatically, and hovering symbols in code blocks shows rich tooltips; click to jump.
  • 🏷️ Smarter mkdocstrings rendering — enums render as enum / member, and headings & the TOC show decorator badges (property, classmethod, …).
  • 🧭 Polished TOC — scroll-spy tuned for long API pages, plus collapsible sections that expand on demand.
  • 🌈 One dark palette, fully themeable — override any color or the Shiki theme from mkdocs.yml.

Install

pip install richdocs

richdocs pulls in mkdocs-material and mkdocstrings[python], so that's all you need.

Quickstart

Add the plugin to mkdocs.yml — the only required option is the package you're documenting:

theme:
  name: material
  palette:
    scheme: slate          # richdocs ships a single dark scheme

plugins:
  - search
  - richdocs:              # ← list BEFORE mkdocstrings
      package: your_package
  - mkdocstrings:
      handlers:
        python:
          paths: [src]

That's it. The plugin registers its stylesheets/scripts, points mkdocstrings at its templates, indexes your API, and serves the Shiki theme — no extra_css / extra_javascript / custom_templates plumbing required.

Ordering: list richdocs before mkdocstrings so its enum/badge templates take effect.

Configuration

Everything except package is optional and has sensible defaults:

plugins:
  - richdocs:
      package: your_package        # required: the Python package to document & index

      api:
        id_prefix: your_package     # mkdocstrings anchor prefix (default: = package)
        page_priority_overrides: {} # {"/api/reference/": 100, ...} canonical-page tuning
        registry_exports: {}        # {name: "pkg.module.singleton"} for registry singletons
        ambiguous_short_names: []   # short names to never auto-link
        prefer_class_for_short: {}  # {short_name: ClassName} to disambiguate
        short_name_blocklist: []
        extra_modules: []           # extra submodules whose __all__ to index
        section_suffixes: ["-functions", "-attributes", "-classes"]
        linkify:                    # what / how symbols get linked
          short_names: true         # link `Robot`, not just `pkg.Robot`
          dotted: true              # resolve `fmt.joint_names` via the rightmost segment
          skip_extensions: [md, py, yaml, yml, npz, json, toml, txt]
          aliases: {}               # {"the result": "pkg.RetargetingResult"}

      symbols:                      # relabel / recolor API badges (override-only)
        labels: {}                  # {function: def, attribute: var, enum: enum, ...}
        colors: {}                  # {enum: {fg: "#7ee8d3", bg: "#7ee8d324"}, class: {fg: "#b362ff"}, ...}
        decorator_labels: {}        # rewrite decorator-label text {property: prop, classmethod: cls}

      live_code:                    # runnable code blocks
        enabled: true
        runtime: jupyter            # jupyter (local) | pyodide (browser) | auto
        jupyter_url: http://127.0.0.1:8888/
        token: your_package-docs    # default: <package>-docs
        launcher_port: 8889
        launcher_script: scripts/docs-jupyter.sh
        kernel: python3
        runnable_languages: [python, bash]
        pyodide:                    # in-browser Python (works on a published static site)
          version: "0.27.2"
          packages: []              # WASM-wheel packages to install, e.g. [numpy, pandas]

      theme:
        palette: {}                 # override any color (see Theming)
        layout: {}                  # TOC spacing tokens
        highlight:                  # Shiki syntax highlighting
          theme: shades-of-purple   # bundled id, or path to a Shiki theme JSON
          inline: true              # highlight inline code too
          default_language: python  # for untagged fenced blocks
          languages: [python, bash, yaml, toml, json, markdown]
          aliases: {py: python, sh: bash, yml: yaml}

      toc:
        collapse_default: true      # nested API/category sections start collapsed
        scrollspy_offset: 0         # extra px added to the active-heading threshold

      features:                     # coarse on/off
        shiki: true
        api_hover: true
        linkify_inline_code: true
        toc_collapsible: true
        toc_scrollspy: true
        hide_empty_toc: true

Theming

Override individual palette colors with friendly keys (or any raw --rd-* CSS custom property):

plugins:
  - richdocs:
      package: your_package
      theme:
        palette:
          page_bg: "#1e1e3f"
          code_bg: "#2d2b55"
          sidebar_bg: "#222244"
          gold: "#fad000"          # accent
          purple_bright: "#b362ff" # links
          # ...or a raw token:
          "--rd-text-muted": "#a599e9"

Supported friendly keys: page_bg, sidebar_bg, code_bg, code_fg, surface_1surface_4, text, text_muted, text_soft, purple, purple_bright, gold/accent, enum_fg/enum_bg, member_fg/member_bg, and the TOC layout tokens toc_row_gap, toc_branch_gap, toc_section_gap, toc_link_min_height.

Symbol labels & colors

Rename or recolor the API symbol-kind badges (headings and TOC) per construct — override-only, so unset kinds keep the bundled defaults:

plugins:
  - richdocs:
      package: your_package
      symbols:
        labels:
          function: def          # "" empties the badge
          attribute: var
          enum: enum
          member: member
        colors:
          enum:  { fg: "#7ee8d3", bg: "#7ee8d324" }
          class: { fg: "#b362ff" }

Recognized kinds: module, class, enum, function, method, attribute, type_alias, member. Setting a kind's color also recolors the decorator labels that map to it (e.g. property follows attribute). Dataclasses keep griffe's built-in dataclass label out of the box; recolor them via the class kind.

You can also rewrite the text of mkdocstrings' decorator labels (these come from griffe, so they're handled by a build-time pass rather than the badge CSS):

plugins:
  - richdocs:
      package: your_package
      symbols:
        decorator_labels: { property: prop, classmethod: cls, staticmethod: static }

Live code: local Jupyter or in-browser Pyodide

Runnable code blocks have two backends, chosen by live_code.runtime:

  • jupyter (default) — a local Jupyter kernel (full Python, any package). On a published site it shows a "needs Jupyter" notice rather than running.
  • pyodide — CPython compiled to WebAssembly, running in the browser (in a Web Worker, so the page stays responsive), so blocks are runnable on a published static site (e.g. GitHub Pages) with no server. The header shows a "Python · browser" indicator. Python only (shell blocks need Jupyter); install WASM-wheel packages via live_code.pyodide.packages (e.g. numpy, pandas — not torch/mujoco).
  • auto — use Jupyter if it's reachable, otherwise fall back to Pyodide.

Opt into web execution deliberately. Pyodide can only run browser-compatible code — crucially, your own package usually isn't available in the browser, so blocks that import your_package will fail under pyodide/auto. Use them only when your runnable blocks are stdlib- or WASM-wheel-only. That's why the default is jupyter.

plugins:
  - richdocs:
      package: your_package
      live_code:
        runtime: auto
        pyodide:
          packages: [numpy]

How it works

A single RichDocsPlugin (MkDocs entry point) replaces what used to be four build hooks plus scattered asset wiring:

Event What it does
on_config validates config, derives defaults, registers bundled CSS/JS, points mkdocstrings at the templates
on_files emits richdocs-config.js (window.__richdocsConfig, read by the JS) and richdocs-palette.css (your overrides)
on_page_markdown auto-links inline `Symbol` mentions to the API reference
on_post_build scans the built site to index API anchors (javascripts/api-symbols.json) and injects decorator badges into the TOC
on_serve runs a tiny local helper so the page can launch Jupyter for live code

Requirements

  • Python 3.11+
  • MkDocs Material 9.5+
  • mkdocstrings[python] 0.25+ (for the API features)

Development

git clone https://github.com/ryanrudes/richdocs
cd richdocs
uv venv && uv pip install -e ".[dev]"
uv run pytest        # unit tests
uv run ruff check .  # lint

License

Apache-2.0 © Ryan Rudes

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

richdocs-0.4.1.tar.gz (83.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

richdocs-0.4.1-py3-none-any.whl (98.5 kB view details)

Uploaded Python 3

File details

Details for the file richdocs-0.4.1.tar.gz.

File metadata

  • Download URL: richdocs-0.4.1.tar.gz
  • Upload date:
  • Size: 83.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for richdocs-0.4.1.tar.gz
Algorithm Hash digest
SHA256 8700d80affae85331204bbb0ba5edaf421dc9ccc6c8126af5f61230915ee5f27
MD5 d70a2aca3d8aa8d0f9fe87230d367f62
BLAKE2b-256 32941450f7e469794f685b91857d0009d25b8ee654d5f6dd14ec19cc7748d34f

See more details on using hashes here.

Provenance

The following attestation bundles were made for richdocs-0.4.1.tar.gz:

Publisher: release.yml on ryanrudes/richdocs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file richdocs-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: richdocs-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 98.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for richdocs-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f9355fa64ca649485e812e97c034da601344f2672118579e85a7f626c0443017
MD5 304cadd0d85eeaa1d0cc092a2d6ade28
BLAKE2b-256 79566131a22b519e0ae4a4125f1a3b1705090ccc2980c4902db792011bd388a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for richdocs-0.4.1-py3-none-any.whl:

Publisher: release.yml on ryanrudes/richdocs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page