Skip to main content

Add a Source-Cited AI Chatbot to MkDocs and Material

· 4 min read
Michael Fisher
ChattyBox maintainer and technical writer

MkDocs themes expose different override directories, and Material can navigate between pages without a complete reload. A durable integration must preserve the theme's existing scripts, load the widget once, and coexist with search and navigation on mobile.

Author and technical reviewer: Michael Fisher, ChattyBox maintainer. Published and technically checked July 10, 2026 against repository revision 3b0f4d5. The original evidence is the two runnable theme examples and the verification protocol below; no traffic, deflection, or answer-accuracy result is claimed.

1. Choose the correct override directory

For Material for MkDocs, point custom_dir at an overrides directory:

site_name: My documentation
theme:
name: material
custom_dir: overrides
features:
- navigation.instant

For the built-in theme, use a separate custom theme directory:

site_name: My documentation
theme:
name: mkdocs
custom_dir: custom_theme

Keeping the variants separate makes it clear which upstream base template is being extended. The repository sample includes both under examples/mkdocs-chattybox.

2. Extend the scripts block

Create overrides/main.html for Material or custom_theme/main.html for the built-in theme:

{% extends "base.html" %}

{% block scripts %}
{{ super() }}
<script
id="chattybox-widget"
src="https://chattybox.ai/widget.js"
async
data-api-key="YOUR_API_KEY"
data-api-url="YOUR_CHAT_API_URL"
data-chattybox-widget="true"
></script>
{% endblock %}

{{ super() }} preserves scripts provided by the theme, including navigation and search behavior. Omitting it can make the widget appear to work while silently breaking the documentation interface. The stable ID also gives you a direct duplicate-loader assertion.

Use project-specific values from the widget installation reference. The MkDocs AI chatbot guide covers source scope, crawl behavior, and the questions to evaluate before publishing.

3. Build both variants

From examples/mkdocs-chattybox:

python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt

cd material
mkdocs build --strict

cd ../vanilla
mkdocs build --strict

--strict turns warnings into failures, which catches broken navigation and configuration issues before the widget is evaluated.

4. Run the browser checks

Serve each variant and verify:

  1. Built-in search still opens and returns the expected documentation result.
  2. Material instant navigation changes routes without duplicating the widget loader.
  3. document.querySelectorAll('#chattybox-widget').length remains 1 after several route changes.
  4. At a 390 px viewport, the launcher does not cover search, navigation, or next/previous controls.
  5. A supported question cites the expected page, and an unsupported question produces a conservative fallback.

The first four checks validate integration behavior. The fifth depends on the pages you index and requires a representative evaluation set; follow the scraping guide and launch checklist rather than treating a successful script load as proof of answer quality.

5. Preserve a restrictive CSP

Allow the widget host in script-src, the configured API origin in connect-src, and the font origins in style-src and font-src when needed. The current widget injects component styles, so an otherwise strict policy also needs an explicit inline-style strategy. Avoid wildcard source lists.

Maintenance checklist

Rebuild both theme variants after MkDocs or Material upgrades, because upstream template block names can change. Keep the script ID stable, preserve super(), and re-run the search, instant-navigation, mobile-overlap, and source-citation checks.

For end-to-end rollout planning, use the documentation chatbot implementation checklist.

Sources