<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>ChattyBox Blog</title>
        <link>https://chattybox.ai/blog/</link>
        <description>ChattyBox Blog</description>
        <lastBuildDate>Fri, 10 Jul 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Add a Source-Cited AI Chatbot to Docusaurus 3]]></title>
            <link>https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/</link>
            <guid>https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/</guid>
            <pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A tested Docusaurus 3 integration pattern that survives client-side navigation, React development remounts, and restrictive content security policies.]]></description>
            <content:encoded><![CDATA[<p>Docusaurus behaves like a single-page application after the first page load. A widget integration that only works on the initial document, or that appends a second loader on every route change, is not production-ready. This guide uses a stable script identity and a theme root that remains mounted across documentation routes.</p>
<!-- -->
<p><strong>Author and technical reviewer:</strong> <a href="https://github.com/MichaelFisher1997" target="_blank" rel="noopener noreferrer">Michael Fisher</a>, ChattyBox maintainer. Published and technically checked July 10, 2026 against repository revision <a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/docusaurus-chattybox" target="_blank" rel="noopener noreferrer"><code>3b0f4d5</code></a>. The evidence is the runnable example and the repeatable checks below; this is an implementation tutorial, not a performance or accuracy benchmark.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="1-add-the-root-theme-component">1. Add the Root theme component<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#1-add-the-root-theme-component" class="hash-link" aria-label="Direct link to 1. Add the Root theme component" title="Direct link to 1. Add the Root theme component" translate="no">​</a></h2>
<p>Create <code>src/theme/Root.tsx</code> in your Docusaurus site:</p>
<div class="language-tsx codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-tsx codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> useEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">ReactNode</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'react'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">WIDGET_ID</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'chattybox-widget'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> children </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> children</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ReactNode</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">useEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">document</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getElementById</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token constant" style="color:rgb(189, 147, 249)">WIDGET_ID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> script </span><span class="token operator">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">document</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">createElement</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'script'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">WIDGET_ID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">src</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'https://chattybox.ai/widget.js'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">async</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">dataset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">apiKey</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'YOUR_API_KEY'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">dataset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">apiUrl</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'YOUR_CHAT_API_URL'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">dataset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">chattyboxWidget</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'true'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">document</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">appendChild</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">children</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>The stable <code>chattybox-widget</code> ID is the important part. React Strict Mode can remount effects during development, and Docusaurus changes routes without replacing the document. The guard makes both cases idempotent.</p>
<p>Use the API URL shown by your ChattyBox project rather than copying an example deployment. See the <a href="https://chattybox.ai/docs/widget/">widget installation reference</a> for the current attributes and the <a href="https://chattybox.ai/docusaurus-ai-chatbot/">Docusaurus product guide</a> for source-selection and evaluation guidance.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="2-keep-the-loader-mounted">2. Keep the loader mounted<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#2-keep-the-loader-mounted" class="hash-link" aria-label="Direct link to 2. Keep the loader mounted" title="Direct link to 2. Keep the loader mounted" translate="no">​</a></h2>
<p>Do not put this script inside an individual docs page or layout that Docusaurus replaces during navigation. The swizzled <code>Root</code> component wraps the application for its lifetime, so the widget remains available as visitors move between guides and references.</p>
<p>If your site already has <code>src/theme/Root.tsx</code>, merge the effect into the existing component rather than replacing authentication, analytics, or other providers.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="3-account-for-content-security-policy">3. Account for Content Security Policy<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#3-account-for-content-security-policy" class="hash-link" aria-label="Direct link to 3. Account for Content Security Policy" title="Direct link to 3. Account for Content Security Policy" translate="no">​</a></h2>
<p>A restrictive policy needs to allow:</p>
<ul>
<li class=""><code>https://chattybox.ai</code> in <code>script-src</code> for the widget loader.</li>
<li class="">Your configured chat API origin in <code>connect-src</code>.</li>
<li class=""><code>https://fonts.googleapis.com</code> in <code>style-src</code> and <code>https://fonts.gstatic.com</code> in <code>font-src</code> if the widget font is not already available.</li>
<li class="">Inline component styles in <code>style-src</code> for the current widget build.</li>
</ul>
<p>Start from your existing policy and add only the origins you actually use. Do not replace a restrictive policy with a broad wildcard.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="4-reproduce-the-integration-checks">4. Reproduce the integration checks<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#4-reproduce-the-integration-checks" class="hash-link" aria-label="Direct link to 4. Reproduce the integration checks" title="Direct link to 4. Reproduce the integration checks" translate="no">​</a></h2>
<p>The complete sample lives in <a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/docusaurus-chattybox" target="_blank" rel="noopener noreferrer"><code>examples/docusaurus-chattybox</code></a>. From that directory:</p>
<div class="language-bash codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-bash codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token plain">bun install</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">bun run start</span><br></div></code></pre></div></div>
<p>Then verify:</p>
<ol>
<li class="">Open two different docs routes without a full browser refresh.</li>
<li class="">Run <code>document.querySelectorAll('#chattybox-widget').length</code> after each navigation. It must remain <code>1</code>.</li>
<li class="">Ask a question answered by an indexed page and confirm the response links to that page.</li>
<li class="">Ask an unsupported question and confirm the assistant falls back instead of inventing a source.</li>
<li class="">Test the launcher at a narrow mobile viewport and check that it does not cover navigation or pagination controls.</li>
</ol>
<p>The script-count check proves duplicate prevention. It does not prove retrieval quality. Use a representative question set and the <a href="https://chattybox.ai/docs/scraping/">scraping guide</a> to validate source coverage before launch.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="what-to-monitor-after-launch">What to monitor after launch<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#what-to-monitor-after-launch" class="hash-link" aria-label="Direct link to What to monitor after launch" title="Direct link to What to monitor after launch" translate="no">​</a></h2>
<p>Record unresolved questions, incorrect citations, stale source pages, and routes where the launcher obscures site controls. Re-test after Docusaurus theme upgrades because changes to navigation and content layout can affect placement even when the loader remains correct.</p>
<p>For a broader rollout sequence, use the <a href="https://chattybox.ai/how-to-add-ai-chatbot-to-documentation/">documentation chatbot implementation checklist</a> and <a href="https://chattybox.ai/docs/launch-checklist/">launch checklist</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="sources">Sources<a href="https://chattybox.ai/blog/docusaurus-ai-chatbot-implementation/#sources" class="hash-link" aria-label="Direct link to Sources" title="Direct link to Sources" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/docusaurus-chattybox" target="_blank" rel="noopener noreferrer">ChattyBox Docusaurus 3 example at revision <code>3b0f4d5</code></a></li>
<li class=""><a href="https://docusaurus.io/docs/swizzling" target="_blank" rel="noopener noreferrer">Docusaurus swizzling documentation</a></li>
<li class=""><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" target="_blank" rel="noopener noreferrer">MDN Content Security Policy guide</a></li>
</ul>]]></content:encoded>
            <category>AI Chatbots</category>
            <category>Documentation</category>
            <category>Implementation</category>
            <category>Docusaurus</category>
        </item>
        <item>
            <title><![CDATA[Add a Source-Cited AI Chatbot to MkDocs and Material]]></title>
            <link>https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/</link>
            <guid>https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/</guid>
            <pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A reproducible MkDocs integration for Material instant navigation and the built-in MkDocs theme, with duplicate-loader, mobile, search, and CSP checks.]]></description>
            <content:encoded><![CDATA[<p>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.</p>
<!-- -->
<p><strong>Author and technical reviewer:</strong> <a href="https://github.com/MichaelFisher1997" target="_blank" rel="noopener noreferrer">Michael Fisher</a>, ChattyBox maintainer. Published and technically checked July 10, 2026 against repository revision <a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/mkdocs-chattybox" target="_blank" rel="noopener noreferrer"><code>3b0f4d5</code></a>. The original evidence is the two runnable theme examples and the verification protocol below; no traffic, deflection, or answer-accuracy result is claimed.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="1-choose-the-correct-override-directory">1. Choose the correct override directory<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#1-choose-the-correct-override-directory" class="hash-link" aria-label="Direct link to 1. Choose the correct override directory" title="Direct link to 1. Choose the correct override directory" translate="no">​</a></h2>
<p>For Material for MkDocs, point <code>custom_dir</code> at an <code>overrides</code> directory:</p>
<div class="language-yaml codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-yaml codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">site_name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> My documentation</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">theme</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> material</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">custom_dir</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> overrides</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">features</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> navigation.instant</span><br></div></code></pre></div></div>
<p>For the built-in theme, use a separate custom theme directory:</p>
<div class="language-yaml codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-yaml codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">site_name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> My documentation</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">theme</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> mkdocs</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">custom_dir</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> custom_theme</span><br></div></code></pre></div></div>
<p>Keeping the variants separate makes it clear which upstream base template is being extended. The repository sample includes both under <a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/mkdocs-chattybox" target="_blank" rel="noopener noreferrer"><code>examples/mkdocs-chattybox</code></a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="2-extend-the-scripts-block">2. Extend the scripts block<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#2-extend-the-scripts-block" class="hash-link" aria-label="Direct link to 2. Extend the scripts block" title="Direct link to 2. Extend the scripts block" translate="no">​</a></h2>
<p>Create <code>overrides/main.html</code> for Material or <code>custom_theme/main.html</code> for the built-in theme:</p>
<div class="language-html codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-html codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token plain">{% extends "base.html" %}</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">{% block scripts %}</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  {{ super() }}</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">chattybox-widget</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">https://chattybox.ai/widget.js</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">async</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">data-api-key</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">YOUR_API_KEY</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">data-api-url</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">YOUR_CHAT_API_URL</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">    </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">data-chattybox-widget</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">true</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">  </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">{% endblock %}</span><br></div></code></pre></div></div>
<p><code>{{ super() }}</code> 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.</p>
<p>Use project-specific values from the <a href="https://chattybox.ai/docs/widget/">widget installation reference</a>. The <a href="https://chattybox.ai/mkdocs-ai-chatbot/">MkDocs AI chatbot guide</a> covers source scope, crawl behavior, and the questions to evaluate before publishing.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="3-build-both-variants">3. Build both variants<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#3-build-both-variants" class="hash-link" aria-label="Direct link to 3. Build both variants" title="Direct link to 3. Build both variants" translate="no">​</a></h2>
<p>From <code>examples/mkdocs-chattybox</code>:</p>
<div class="language-bash codeBlockContainer_hqe0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_AzKq"><pre tabindex="0" class="prism-code language-bash codeBlock_ypHS thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_v7UJ"><div class="token-line" style="color:#F8F8F2"><span class="token plain">python -m venv .venv</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">. .venv/bin/activate</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">pip install -r requirements.txt</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">cd material</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mkdocs build --strict</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">cd ../vanilla</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">mkdocs build --strict</span><br></div></code></pre></div></div>
<p><code>--strict</code> turns warnings into failures, which catches broken navigation and configuration issues before the widget is evaluated.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="4-run-the-browser-checks">4. Run the browser checks<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#4-run-the-browser-checks" class="hash-link" aria-label="Direct link to 4. Run the browser checks" title="Direct link to 4. Run the browser checks" translate="no">​</a></h2>
<p>Serve each variant and verify:</p>
<ol>
<li class="">Built-in search still opens and returns the expected documentation result.</li>
<li class="">Material instant navigation changes routes without duplicating the widget loader.</li>
<li class=""><code>document.querySelectorAll('#chattybox-widget').length</code> remains <code>1</code> after several route changes.</li>
<li class="">At a 390 px viewport, the launcher does not cover search, navigation, or next/previous controls.</li>
<li class="">A supported question cites the expected page, and an unsupported question produces a conservative fallback.</li>
</ol>
<p>The first four checks validate integration behavior. The fifth depends on the pages you index and requires a representative evaluation set; follow the <a href="https://chattybox.ai/docs/scraping/">scraping guide</a> and <a href="https://chattybox.ai/docs/launch-checklist/">launch checklist</a> rather than treating a successful script load as proof of answer quality.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="5-preserve-a-restrictive-csp">5. Preserve a restrictive CSP<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#5-preserve-a-restrictive-csp" class="hash-link" aria-label="Direct link to 5. Preserve a restrictive CSP" title="Direct link to 5. Preserve a restrictive CSP" translate="no">​</a></h2>
<p>Allow the widget host in <code>script-src</code>, the configured API origin in <code>connect-src</code>, and the font origins in <code>style-src</code> and <code>font-src</code> when needed. The current widget injects component styles, so an otherwise strict policy also needs an explicit inline-style strategy. Avoid wildcard source lists.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="maintenance-checklist">Maintenance checklist<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#maintenance-checklist" class="hash-link" aria-label="Direct link to Maintenance checklist" title="Direct link to Maintenance checklist" translate="no">​</a></h2>
<p>Rebuild both theme variants after MkDocs or Material upgrades, because upstream template block names can change. Keep the script ID stable, preserve <code>super()</code>, and re-run the search, instant-navigation, mobile-overlap, and source-citation checks.</p>
<p>For end-to-end rollout planning, use the <a href="https://chattybox.ai/how-to-add-ai-chatbot-to-documentation/">documentation chatbot implementation checklist</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="sources">Sources<a href="https://chattybox.ai/blog/mkdocs-ai-chatbot-implementation/#sources" class="hash-link" aria-label="Direct link to Sources" title="Direct link to Sources" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/OpenStaticFish/chattybots/tree/3b0f4d5/examples/mkdocs-chattybox" target="_blank" rel="noopener noreferrer">ChattyBox MkDocs examples at revision <code>3b0f4d5</code></a></li>
<li class=""><a href="https://www.mkdocs.org/dev-guide/themes/" target="_blank" rel="noopener noreferrer">MkDocs theme customization</a></li>
<li class=""><a href="https://squidfunk.github.io/mkdocs-material/customization/" target="_blank" rel="noopener noreferrer">Material for MkDocs customization</a></li>
<li class=""><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" target="_blank" rel="noopener noreferrer">MDN Content Security Policy guide</a></li>
</ul>]]></content:encoded>
            <category>AI Chatbots</category>
            <category>Documentation</category>
            <category>Implementation</category>
            <category>MkDocs</category>
        </item>
        <item>
            <title><![CDATA[Introducing ChattyBox for Source-Cited Website Answers]]></title>
            <link>https://chattybox.ai/blog/introducing-chattybox/</link>
            <guid>https://chattybox.ai/blog/introducing-chattybox/</guid>
            <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Meet ChattyBox, an AI chatbot that learns from your public website and documentation to answer visitors with source citations.]]></description>
            <content:encoded><![CDATA[<p>ChattyBox helps teams turn public website content, documentation, help centers, and CMS pages into an AI chatbot that gives grounded answers with source citations. Instead of answering from generic model memory, it crawls the pages you choose and points visitors back to the exact sources behind each response.</p>
<!-- -->
<p>The product is built for teams that want a practical AI support layer without migrating documentation or rebuilding their site stack. Add your website URL, let ChattyBox crawl published content, test real questions, then install the widget with a script tag.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="why-we-built-it">Why We Built It<a href="https://chattybox.ai/blog/introducing-chattybox/#why-we-built-it" class="hash-link" aria-label="Direct link to Why We Built It" title="Direct link to Why We Built It" translate="no">​</a></h2>
<p>Most website chatbots either require a heavy sales-led setup or answer too broadly from model training data. ChattyBox focuses on the content you already publish, so visitors can ask natural-language questions and still verify the answer against your documentation.</p>
<p>That makes it useful for documentation sites, SaaS help centers, developer docs, CMS pages, and product websites where trust matters.</p>
<h2 class="anchor anchorTargetStickyNavbar_MdcL" id="what-comes-next">What Comes Next<a href="https://chattybox.ai/blog/introducing-chattybox/#what-comes-next" class="hash-link" aria-label="Direct link to What Comes Next" title="Direct link to What Comes Next" translate="no">​</a></h2>
<p>This blog will share practical guides on using AI to reduce support tickets, building reliable RAG chatbots for websites, and adding AI assistants to documentation without losing source control.</p>
<p>Start with the <a href="https://chattybox.ai/ai-chatbot-for-documentation/">documentation AI chatbot guide</a> or read the <a href="https://chattybox.ai/docs/installation/">installation docs</a> to add ChattyBox to your site.</p>]]></content:encoded>
            <category>AI Chatbots</category>
            <category>Documentation</category>
            <category>Product</category>
        </item>
    </channel>
</rss>