After creating a Widget ID, click “Show” button to open the configuration panel. This allows you to customize your widget’s appearance and behavior with a live preview that shows exactly how it will look on your website.
The configuration panel includes:
Button Text: Customize the text displayed on the widget button
Theme: Choose between Light, Dark, or Auto (syncs with your website’s theme)
Window Mode: Select Sidebar or Floating display mode
Button Color & Shimmer: Customize the button’s primary color and shimmer effect
Margins: Adjust the button’s position from the bottom and right edges
Tooltip: Add an optional tooltip with customizable position
Icon URL & Custom Name: Override the default Guru icon and name
The Live Preview on the right side shows your widget in real-time as you make changes. You can interact with the preview to test the widget’s functionality before deploying it to your website.Once you’re satisfied with the configuration, copy the generated widget script from the “Widget Script” section.
If you’re using AI coding assistants like Cursor, Claude Code, or similar tools, click the “Show Prompt” button next to “Using Cursor, Claude Code, or AI assistants?” to get a ready-to-use prompt.
This prompt includes:
Instructions to detect your website’s framework (Next.js, Docusaurus, MkDocs, etc.)
Guidance to check framework-specific setup from Gurubase docs
Your widget script with all configured options
Simply copy the prompt and paste it into your AI assistant to get framework-specific integration instructions tailored to your project.
Light mode toggle. Possible values are "light", "dark", "auto". Auto mode syncs the widget theme with the website’s theme
"dark"
data-window-mode
Display mode for the chat window. Options: "sidebar", "floating"
"sidebar"
data-bg-color
Primary color
Fetched from Gurubase
data-shimmer-color
Color for the animated shimmer effect on example questions. Accepts hex color values (e.g., “#0000FF”). If not set, uses data-bg-color. Falls back to red if neither is available.
Uses data-bg-color or red fallback
data-icon-url
Custom logo URL
Fetched from Gurubase
data-name
Custom name
Fetched from Gurubase
data-base-url
URL to your Gurubase backend. Only for self-hosted Gurubase (Enterprise plan).
Self-hosted installations are exclusively available under the Enterprise plan. To request access, contact us at [email protected].If you’re using self-hosted Gurubase, you must set the Gurubase instance URL using the data-base-url attribute. The default URL of Self-hosted Gurubase instance is http://localhost:8029/api/.
The widget exposes the following functions via window.chatWidget:
switchTheme(lightMode = null)Sync the theme of the widget with your website’s theme. Accepts an optional lightMode parameter:
switchTheme(): Toggle the theme
switchTheme(true): Force light mode
switchTheme(false): Force dark mode
Example: window.chatWidget.switchTheme(true);See the MkDocs example for theme syncing implementation.
destroy()Remove the widget from the DOM and clean up all event listeners. Useful for SPAs where you want to conditionally show/hide the widget based on the current route.Example: window.chatWidget.destroy();See Path-Based Widget Loading for a complete example.
You can display custom example questions in your widget to help guide users on what they can ask. These questions appear when users open the widget, providing helpful prompts to get started.
To configure example questions:
Go to your Guru’s settings page
Scroll to Advanced Settings
Add up to 3 example questions (100 characters max each)
Save your changes
When users click an example question in the widget, it populates the input field so they can submit it directly or modify it first.
If you want to load the widget only on specific paths (e.g., only on /docs/ pages), you can use a conditional loading approach. This is especially useful for Single Page Applications (SPAs) where you need to handle client-side navigation.The following script can be adapted to any SPA framework (Docusaurus, Next.js, Remix, etc.):
Copy
(function() { var widgetInitialized = false; function isDocsPath(pathname) { return pathname === '/docs' || pathname.startsWith('/docs/'); } function initWidget() { if (widgetInitialized) return; // Only show on /docs pages - modify this path as needed if (!isDocsPath(window.location.pathname)) return; var existingScript = document.getElementById('guru-widget-id'); if (existingScript) return; var script = document.createElement('script'); script.src = "https://widget.gurubase.io/widget.latest.min.js"; script.setAttribute("data-widget-id", "YOUR_WIDGET_ID"); script.setAttribute("data-text", "Ask AI"); script.setAttribute("data-margins", '{"bottom": "20px", "right": "20px"}'); script.setAttribute("data-light-mode", "auto"); script.setAttribute("data-overlap-content", "true"); script.defer = true; script.id = "guru-widget-id"; document.body.appendChild(script); widgetInitialized = true; } function destroyWidget() { if (!widgetInitialized) return; // Use widget's destroy method if available if (window.chatWidget && typeof window.chatWidget.destroy === 'function') { window.chatWidget.destroy(); } // Remove the script tag var script = document.getElementById('guru-widget-id'); if (script) script.remove(); // Remove widget instance if (window.chatWidget) delete window.chatWidget; if (window.ChatWidget) delete window.ChatWidget; // Remove all widget-related DOM elements ['#guru-widget-id', '#gurubase-chat-widget-container'].forEach(function(selector) { try { document.querySelectorAll(selector).forEach(function(el) { el.remove(); }); } catch (e) {} }); widgetInitialized = false; } function handleRouteChange() { if (isDocsPath(window.location.pathname)) { initWidget(); } else { destroyWidget(); } } function setup() { // Check on initial page load handleRouteChange(); // Hook into History API for SPA client-side navigation var originalPushState = history.pushState; history.pushState = function() { originalPushState.apply(this, arguments); setTimeout(handleRouteChange, 0); }; var originalReplaceState = history.replaceState; history.replaceState = function() { originalReplaceState.apply(this, arguments); setTimeout(handleRouteChange, 0); }; // Handle browser back/forward buttons window.addEventListener('popstate', function() { setTimeout(handleRouteChange, 0); }); } // Wait for DOM to be ready before accessing document.body if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', setup); } else { setup(); }})();
Key points:
The isDocsPath() helper matches both /docs and /docs/* paths (modify this function to match your desired paths)
The initWidget() function checks the current path before loading the widget
The destroyWidget() function cleans up all widget-related DOM elements when navigating away
History API hooks (pushState, replaceState, popstate) handle SPA navigation
Docusaurus Plugin Example
For Docusaurus, you can wrap this in a plugin. Create plugins/gurubase-widget.js:
Copy
module.exports = (_context) => ({ name: "docusaurus-plugin-gurubase-widget", injectHtmlTags() { return { postBodyTags: [ { tagName: "script", innerHTML: ` (function() { var widgetInitialized = false; function isDocsPath(pathname) { return pathname === '/docs' || pathname.startsWith('/docs/'); } function initWidget() { if (widgetInitialized) return; if (!isDocsPath(window.location.pathname)) return; var existingScript = document.getElementById('guru-widget-id'); if (existingScript) return; var script = document.createElement('script'); script.src = "https://widget.gurubase.io/widget.latest.min.js"; script.setAttribute("data-widget-id", "YOUR_WIDGET_ID"); script.setAttribute("data-light-mode", "auto"); script.setAttribute("data-overlap-content", "true"); script.defer = true; script.id = "guru-widget-id"; document.body.appendChild(script); widgetInitialized = true; } function destroyWidget() { if (!widgetInitialized) return; if (window.chatWidget && typeof window.chatWidget.destroy === 'function') { window.chatWidget.destroy(); } var script = document.getElementById('guru-widget-id'); if (script) script.remove(); if (window.chatWidget) delete window.chatWidget; if (window.ChatWidget) delete window.ChatWidget; ['#guru-widget-id', '#gurubase-chat-widget-container'].forEach(function(selector) { try { document.querySelectorAll(selector).forEach(function(el) { el.remove(); }); } catch (e) {} }); widgetInitialized = false; } function handleRouteChange() { if (isDocsPath(window.location.pathname)) { initWidget(); } else { destroyWidget(); } } handleRouteChange(); var originalPushState = history.pushState; history.pushState = function() { originalPushState.apply(this, arguments); setTimeout(handleRouteChange, 0); }; var originalReplaceState = history.replaceState; history.replaceState = function() { originalReplaceState.apply(this, arguments); setTimeout(handleRouteChange, 0); }; window.addEventListener('popstate', function() { setTimeout(handleRouteChange, 0); }); })(); `, }, ], }; },});
To add the Gurubase widget to your Archbee documentation:
Go to Space Settings > Custom Code
Under the “Include Headers” text area, paste the Gurubase widget script that you received from the Gurubase platform:
For security reasons, scripts are only included on a custom domain in Archbee. Make sure you have set up a custom domain for your documentation to use the widget.
To add the Gurubase widget to your Mintlify documentation with automatic theme syncing, create a JavaScript file (e.g., gurubase.js) in your docs content folder with the following content:
Copy
// Customize widget settingsconst widgetSettings = { widgetId: "YOUR_WIDGET_ID", // Replace with your Widget ID from https://app.gurubase.io/my-gurus overlapContent: true, // Optional configurations: // text: "Ask AI", // margins: { bottom: "20px", right: "20px" }, // lightMode: "auto", // bgColor: "#000000",};function initGurubaseWidget() { // Guard against double initialization if (document.getElementById('guru-widget-id')) return; // Load the Gurubase widget const guruScript = document.createElement("script"); guruScript.src = "https://widget.gurubase.io/widget.latest.min.js"; guruScript.defer = true; guruScript.id = "guru-widget-id"; // Add widget settings as data attributes Object.entries(widgetSettings).forEach(([key, value]) => { const dataKey = `data-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`; const dataValue = typeof value === 'object' ? JSON.stringify(value) : value; guruScript.setAttribute(dataKey, dataValue); }); // Initialize theme handling guruScript.addEventListener('load', () => { const initWidget = setInterval(() => { if (window.chatWidget?.switchTheme) { clearInterval(initWidget); // Handle theme changes const syncTheme = () => { const isDark = document.documentElement.classList.contains('dark'); window.chatWidget.switchTheme(!isDark); }; // Watch for theme changes new MutationObserver(syncTheme).observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); // Set initial theme syncTheme(); } }, 1000); // Stop checking after 20 seconds setTimeout(() => clearInterval(initWidget), 20000); }); document.body.appendChild(guruScript);}// Wait for DOM to be ready before accessing document.bodyif (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initGurubaseWidget);} else { initGurubaseWidget();}
Any .js file in your Mintlify content directory is automatically included on every page - no additional configuration needed. The widget will automatically sync its theme (light/dark) with your Mintlify documentation.
For themes with dark mode support (like Furo or PyData), add theme syncing to automatically match the widget theme with your documentation.Using static JS file (_static/gurubase-widget.js):
Important: Choose only ONE of the following approaches. Using both will cause the widget to load twice since both methods add a script with the same id='guru-widget-id'.
Check domain configuration: Ensure your Widget ID was created for the exact domain where you’re testing. Remember that www.example.com and example.com are different domains.
Check for JavaScript errors: Open your browser’s developer console (F12) and look for any errors.
Verify script loading: Check the Network tab to ensure widget.latest.min.js loads successfully.
Check for ad blockers: Some ad blockers may prevent the widget from loading.
Widget appears twice
This usually happens when the widget script is included multiple times. Common causes:
Using both the config approach AND component approach (e.g., in Astro/Starlight)
Script included in both layout template and page template
SPA navigation re-initializing without proper cleanup
Solution: Ensure you only use ONE method to add the widget, and check that document.getElementById('guru-widget-id') guard is in place.
Theme not syncing with website
Ensure you’re using data-light-mode="auto" for automatic detection
For custom theme sync, verify your MutationObserver is watching the correct element and attribute
Check that window.chatWidget.switchTheme() is being called after the widget loads
Widget not working on localhost
Create a separate Widget ID for your local development URL (e.g., http://localhost:3000 or http://localhost:* for any port).