{"id":51342538,"url":"https://github.com/ryanrudes/richdocs","last_synced_at":"2026-07-02T09:02:57.555Z","repository":{"id":367647040,"uuid":"1281704130","full_name":"ryanrudes/richdocs","owner":"ryanrudes","description":"A batteries-included documentation experience for MkDocs Material: Shiki highlighting, runnable live code, API-symbol hover \u0026 auto-linking, and TOC enhancements.","archived":false,"fork":false,"pushed_at":"2026-06-26T22:31:13.000Z","size":173,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-27T00:26:57.254Z","etag":null,"topics":["documentation","mkdocs","mkdocs-material","mkdocs-plugin","mkdocstrings","python","shiki"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryanrudes.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-26T20:46:14.000Z","updated_at":"2026-06-26T22:31:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ryanrudes/richdocs","commit_stats":null,"previous_names":["ryanrudes/richdocs"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ryanrudes/richdocs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanrudes%2Frichdocs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanrudes%2Frichdocs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanrudes%2Frichdocs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanrudes%2Frichdocs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryanrudes","download_url":"https://codeload.github.com/ryanrudes/richdocs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanrudes%2Frichdocs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35040024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["documentation","mkdocs","mkdocs-material","mkdocs-plugin","mkdocstrings","python","shiki"],"created_at":"2026-07-02T09:02:56.726Z","updated_at":"2026-07-02T09:02:57.547Z","avatar_url":"https://github.com/ryanrudes.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# richdocs\n\n**A batteries-included documentation experience for [MkDocs Material](https://squidfunk.github.io/mkdocs-material/).**\n\nShiki syntax highlighting · runnable live code · API-symbol hover \u0026 auto-linking · mkdocstrings enum/decorator badges · a polished collapsible TOC — all from a single plugin entry.\n\n[![PyPI](https://img.shields.io/pypi/v/richdocs.svg)](https://pypi.org/project/richdocs/)\n[![Python](https://img.shields.io/pypi/pyversions/richdocs.svg)](https://pypi.org/project/richdocs/)\n[![CI](https://github.com/ryanrudes/richdocs/actions/workflows/ci.yml/badge.svg)](https://github.com/ryanrudes/richdocs/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n\n[**Live demo →**](https://ryanrudes.github.io/richdocs/)\n\n\u003c/div\u003e\n\n---\n\n## Why\n\nMkDocs 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.\n\n## Features\n\n- 🎨 **Shiki syntax highlighting** — VS Code-accurate highlighting at runtime (the default theme is *Shades of Purple*), in both code blocks and inline code.\n- ▶️ **Runnable live code** — execute Python/shell blocks against a local Jupyter kernel, right in the page (dev only).\n- 🔗 **API-symbol hover \u0026 auto-linking** — inline `` `Symbol` `` mentions link to your mkdocstrings reference automatically, and hovering symbols in code blocks shows rich tooltips; click to jump.\n- 🏷️ **Smarter mkdocstrings rendering** — enums render as `enum` / `member`, and headings \u0026 the TOC show decorator badges (`property`, `classmethod`, …).\n- 🧭 **Polished TOC** — scroll-spy tuned for long API pages, plus collapsible sections that expand on demand.\n- 🌈 **One dark palette, fully themeable** — override any color or the Shiki theme from `mkdocs.yml`.\n\n## Install\n\n```bash\npip install richdocs\n```\n\n`richdocs` pulls in `mkdocs-material` and `mkdocstrings[python]`, so that's all you need.\n\n## Quickstart\n\nAdd the plugin to `mkdocs.yml` — the only required option is the package you're documenting:\n\n```yaml\ntheme:\n  name: material\n  palette:\n    scheme: slate          # richdocs ships a single dark scheme\n\nplugins:\n  - search\n  - richdocs:              # ← list BEFORE mkdocstrings\n      package: your_package\n  - mkdocstrings:\n      handlers:\n        python:\n          paths: [src]\n```\n\nThat'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.\n\n\u003e **Ordering:** list `richdocs` **before** `mkdocstrings` so its enum/badge templates take effect.\n\n## Configuration\n\nEverything except `package` is optional and has sensible defaults:\n\n```yaml\nplugins:\n  - richdocs:\n      package: your_package        # required: the Python package to document \u0026 index\n\n      api:\n        id_prefix: your_package     # mkdocstrings anchor prefix (default: = package)\n        page_priority_overrides: {} # {\"/api/reference/\": 100, ...} canonical-page tuning\n        registry_exports: {}        # {name: \"pkg.module.singleton\"} for registry singletons\n        ambiguous_short_names: []   # short names to never auto-link\n        prefer_class_for_short: {}  # {short_name: ClassName} to disambiguate\n        short_name_blocklist: []\n        extra_modules: []           # extra submodules whose __all__ to index\n        section_suffixes: [\"-functions\", \"-attributes\", \"-classes\"]\n        linkify:                    # what / how symbols get linked\n          short_names: true         # link `Robot`, not just `pkg.Robot`\n          dotted: true              # resolve `fmt.joint_names` via the rightmost segment\n          skip_extensions: [md, py, yaml, yml, npz, json, toml, txt]\n          aliases: {}               # {\"the result\": \"pkg.RetargetingResult\"}\n\n      symbols:                      # relabel / recolor API badges (override-only)\n        labels: {}                  # {function: def, attribute: var, enum: enum, ...}\n        colors: {}                  # {enum: {fg: \"#7ee8d3\", bg: \"#7ee8d324\"}, class: {fg: \"#b362ff\"}, ...}\n        decorator_labels: {}        # rewrite decorator-label text {property: prop, classmethod: cls}\n\n      live_code:                    # runnable code blocks\n        enabled: true\n        runtime: jupyter            # jupyter (local) | pyodide (browser) | auto\n        jupyter_url: http://127.0.0.1:8888/\n        token: your_package-docs    # default: \u003cpackage\u003e-docs\n        launcher_port: 8889\n        launcher_script: scripts/docs-jupyter.sh\n        kernel: python3\n        runnable_languages: [python, bash]\n        pyodide:                    # in-browser Python (works on a published static site)\n          version: \"0.27.2\"\n          packages: []              # WASM-wheel packages to install, e.g. [numpy, pandas]\n\n      theme:\n        palette: {}                 # override any color (see Theming)\n        layout: {}                  # TOC spacing tokens\n        highlight:                  # Shiki syntax highlighting\n          theme: shades-of-purple   # bundled id, or path to a Shiki theme JSON\n          inline: true              # highlight inline code too\n          default_language: python  # for untagged fenced blocks\n          languages: [python, bash, yaml, toml, json, markdown]\n          aliases: {py: python, sh: bash, yml: yaml}\n\n      toc:\n        collapse_default: true      # nested API/category sections start collapsed\n        scrollspy_offset: 0         # extra px added to the active-heading threshold\n\n      features:                     # coarse on/off\n        shiki: true\n        api_hover: true\n        linkify_inline_code: true\n        toc_collapsible: true\n        toc_scrollspy: true\n        hide_empty_toc: true\n```\n\n### Theming\n\nOverride individual palette colors with friendly keys (or any raw `--rd-*` CSS custom property):\n\n```yaml\nplugins:\n  - richdocs:\n      package: your_package\n      theme:\n        palette:\n          page_bg: \"#1e1e3f\"\n          code_bg: \"#2d2b55\"\n          sidebar_bg: \"#222244\"\n          gold: \"#fad000\"          # accent\n          purple_bright: \"#b362ff\" # links\n          # ...or a raw token:\n          \"--rd-text-muted\": \"#a599e9\"\n```\n\nSupported friendly keys: `page_bg`, `sidebar_bg`, `code_bg`, `code_fg`, `surface_1`–`surface_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`.\n\n### Symbol labels \u0026 colors\n\nRename or recolor the API symbol-kind badges (headings **and** TOC) per construct\n— override-only, so unset kinds keep the bundled defaults:\n\n```yaml\nplugins:\n  - richdocs:\n      package: your_package\n      symbols:\n        labels:\n          function: def          # \"\" empties the badge\n          attribute: var\n          enum: enum\n          member: member\n        colors:\n          enum:  { fg: \"#7ee8d3\", bg: \"#7ee8d324\" }\n          class: { fg: \"#b362ff\" }\n```\n\nRecognized kinds: `module`, `class`, `enum`, `function`, `method`, `attribute`,\n`type_alias`, `member`. Setting a kind's color also recolors the decorator labels\nthat map to it (e.g. `property` follows `attribute`). Dataclasses keep griffe's\nbuilt-in `dataclass` label out of the box; recolor them via the `class` kind.\n\nYou can also rewrite the **text** of mkdocstrings' decorator labels (these come\nfrom griffe, so they're handled by a build-time pass rather than the badge CSS):\n\n```yaml\nplugins:\n  - richdocs:\n      package: your_package\n      symbols:\n        decorator_labels: { property: prop, classmethod: cls, staticmethod: static }\n```\n\n## Live code: local Jupyter or in-browser Pyodide\n\nRunnable code blocks have two backends, chosen by `live_code.runtime`:\n\n- **`jupyter`** (default) — a local Jupyter kernel (full Python, any package).\n  On a published site it shows a \"needs Jupyter\" notice rather than running.\n- **`pyodide`** — CPython compiled to WebAssembly, running **in the browser** (in\n  a Web Worker, so the page stays responsive), so blocks are runnable on a\n  published static site (e.g. GitHub Pages) with no server. The header shows a\n  \"Python · browser\" indicator. Python only (shell blocks need Jupyter); install\n  WASM-wheel packages via `live_code.pyodide.packages` (e.g. `numpy`, `pandas` —\n  not `torch`/`mujoco`).\n- **`auto`** — use Jupyter if it's reachable, otherwise fall back to Pyodide.\n\n\u003e **Opt into web execution deliberately.** Pyodide can only run browser-compatible\n\u003e code — crucially, **your own package usually isn't available in the browser**, so\n\u003e blocks that `import your_package` will fail under `pyodide`/`auto`. Use them only\n\u003e when your runnable blocks are stdlib- or WASM-wheel-only. That's why the default\n\u003e is `jupyter`.\n\n```yaml\nplugins:\n  - richdocs:\n      package: your_package\n      live_code:\n        runtime: auto\n        pyodide:\n          packages: [numpy]\n```\n\n## How it works\n\nA single `RichDocsPlugin` (MkDocs entry point) replaces what used to be four build hooks plus scattered asset wiring:\n\n| Event | What it does |\n| --- | --- |\n| `on_config` | validates config, derives defaults, registers bundled CSS/JS, points mkdocstrings at the templates |\n| `on_files` | emits `richdocs-config.js` (`window.__richdocsConfig`, read by the JS) and `richdocs-palette.css` (your overrides) |\n| `on_page_markdown` | auto-links inline `` `Symbol` `` mentions to the API reference |\n| `on_post_build` | scans the built site to index API anchors (`javascripts/api-symbols.json`) and injects decorator badges into the TOC |\n| `on_serve` | runs a tiny local helper so the page can launch Jupyter for live code |\n\n## Requirements\n\n- Python 3.11+\n- MkDocs Material 9.5+\n- mkdocstrings[python] 0.25+ (for the API features)\n\n## Development\n\n```bash\ngit clone https://github.com/ryanrudes/richdocs\ncd richdocs\nuv venv \u0026\u0026 uv pip install -e \".[dev]\"\nuv run pytest        # unit tests\nuv run ruff check .  # lint\n```\n\n## License\n\n[Apache-2.0](LICENSE) © Ryan Rudes\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanrudes%2Frichdocs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryanrudes%2Frichdocs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanrudes%2Frichdocs/lists"}