-
Notifications
You must be signed in to change notification settings - Fork 236
feat: assistant widget #6754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: assistant widget #6754
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
2de6657
feat: assistant widget
dks333 ba07b1a
fix
dks333 b4eac46
docs: rename Assistant Widget to Mintlify Widget
mintlify[bot] fb39079
docs: shorten widget sidebar title
mintlify[bot] f410cf4
add starter questions + support email
dks333 a49a91c
Merge branch 'sam/assistant-widget' of github.com:mintlify/docs into …
dks333 68834c9
new playground
dks333 f3a103c
update
dks333 c5f1892
fix
dks333 4ff8f02
remove bg
dks333 308f1e4
remove bg
dks333 841df5a
fix
dks333 0bad3a3
update link
dks333 bfc4141
resolve merge conflicts
ethanpalm 19f9fb1
update intro, copy edit
ethanpalm 1301919
add prerequisites and confirmation step
ethanpalm a8bf474
vale warning
ethanpalm 68f0942
fix
dks333 1cfa955
fix
dks333 8ae4c4c
Merge branch 'sam/assistant-widget' of github.com:mintlify/docs into …
dks333 998eac2
fkx
dks333 97568e9
fix
dks333 f16e564
fix
dks333 9583176
live preview
dks333 9b2d208
fix
dks333 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| title: "Widget preview" | ||
| description: "Host page for the live preview in the assistant widget playground." | ||
| keywords: ["assistant", "widget", "preview"] | ||
| mode: "custom" | ||
| noindex: true | ||
| --- | ||
|
|
||
| import { AssistantWidgetPreviewHost } from "/snippets/assistant-widget-preview-host.jsx"; | ||
|
|
||
| <AssistantWidgetPreviewHost /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,260 @@ | ||
| --- | ||
| title: "Mintlify widget" | ||
| sidebarTitle: "Widget" | ||
| description: "Install and configure the Mintlify widget to embed the AI assistant trained on your content in any website or web application." | ||
| keywords: ["assistant", "chat", "embed"] | ||
| mode: "wide" | ||
| --- | ||
|
|
||
| import { AssistantWidgetPlayground } from "/snippets/assistant-widget-playground.jsx"; | ||
|
|
||
| export const WidgetCodeBlock = ({ children, ...props }) => ( | ||
| <CodeBlock {...props}>{children}</CodeBlock> | ||
| ); | ||
|
|
||
| The [assistant](/assistant) answers questions on your Mintlify site. To embed the same capability on another site or web app, use the widget. With the widget, you can give your users access to AI chat trained on your content in your product dashboard, marketing site, support portal, or elsewhere. | ||
|
|
||
| Use the [`@mintlify/assistant-widget`](https://www.npmjs.com/package/@mintlify/assistant-widget) package to add your Mintlify assistant to any website or web application. The hosted package owns its trigger and renders inside a closed Shadow DOM, which prevents your application styles from affecting the widget. | ||
|
|
||
| The only required browser option is the public widget ID. Manage the enabled state, allowed origins, attachments, and bot protection in your dashboard. Set embed-specific starter questions and a support email in the browser configuration. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - A [Pro or Enterprise plan](https://mintlify.com/pricing?ref=assistant). The widget uses the same credits as the assistant. | ||
|
|
||
| ## Enable the widget | ||
|
|
||
| 1. Navigate to your deployment's [Widget](https://app.mintlify.com/settings/deployment/widget) page. | ||
| 2. Enable the widget. | ||
| 3. Add allowed origins where you embed the widget. | ||
| 4. Copy the widget ID. | ||
|
|
||
| ## Install and configure | ||
|
|
||
| Use the playground to configure the presentation, visual options, and observer hooks for your widget. The installation code block updates as you change each option. | ||
|
|
||
| <Info> | ||
| Replace `YOUR_WIDGET_ID` in the generated code with the widget ID from the [Widget](https://app.mintlify.com/settings/deployment/widget) page of your dashboard. | ||
| </Info> | ||
|
|
||
| After you add the generated code to your site, reload the page. Confirm the trigger appears, then click it and send a test question to verify the widget is connected. | ||
|
|
||
| <AssistantWidgetPlayground CodeBlockComponent={WidgetCodeBlock}> | ||
|
|
||
| <Warning> | ||
| Module scripts defer and run in document order. Keep the hosted loader before the initialization block when you install the widget with HTML, or the widget fails to mount. | ||
| </Warning> | ||
|
|
||
| ## Open on initialization | ||
|
|
||
| Set `defaultOpen` to `true` to open the widget immediately after its first mount: | ||
|
|
||
| ```js | ||
| await window.MintlifyAssistant.init({ | ||
| id: "YOUR_WIDGET_ID", | ||
| defaultOpen: true, | ||
| }); | ||
| ``` | ||
|
|
||
| `defaultOpen` defaults to `false` and only applies to the first initialization. Calling `init()` again with the same widget ID and API endpoint does not reopen a widget that a visitor closed. Use `open()` and `close()` to control it after initialization. | ||
|
|
||
| ## Use a custom trigger | ||
|
|
||
| Await `init()` before calling other methods. Keep the built-in trigger or open the configured presentation from any button in your application. | ||
|
|
||
| ```js | ||
| await window.MintlifyAssistant.init({ | ||
| id: "YOUR_WIDGET_ID", | ||
| supportEmail: "hi@mintlify.com", | ||
| starterQuestions: [ | ||
| "How do I get started with Mintlify?", | ||
| "How do I customize my docs?", | ||
| "How do I deploy my docs?", | ||
| ], | ||
| }); | ||
|
|
||
| document.querySelector("#help-button").addEventListener("click", () => { | ||
| void window.MintlifyAssistant.open({ | ||
| source: "help-button", | ||
| focus: true, | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| To open the widget and immediately send a question, call `ask()`: | ||
|
|
||
| ```js | ||
| await window.MintlifyAssistant.ask("How do I authenticate?", { | ||
| source: "authentication-guide", | ||
| open: true, | ||
| focus: true, | ||
| }); | ||
| ``` | ||
|
|
||
| Event metadata and requests include the `source` value, which lets you distinguish built-in interactions from your custom entry points. | ||
|
|
||
| ## Update a mounted widget | ||
|
|
||
| Use `update()` to change appearance, labels, support email, starter questions, or hooks without clearing the current conversation. Only the supplied fields change. | ||
|
|
||
| ```js | ||
| await window.MintlifyAssistant.update({ | ||
| appearance: { | ||
| theme: "dark", | ||
| accent: "#7c3aed", | ||
| }, | ||
| labels: { | ||
| title: "Docs copilot", | ||
| trigger: "Ask docs", | ||
| }, | ||
| supportEmail: "support@example.com", | ||
| starterQuestions: [ | ||
| "How do I get started?", | ||
| "How do I manage my account?", | ||
| ], | ||
| }); | ||
| ``` | ||
|
|
||
| Pass `null` to restore a field or group to its default, remove the support email, or restore an empty starter-question list: | ||
|
|
||
| ```js | ||
| await window.MintlifyAssistant.update({ | ||
| appearance: { | ||
| accent: null, | ||
| }, | ||
| supportEmail: null, | ||
| starterQuestions: null, | ||
| hooks: null, | ||
| }); | ||
| ``` | ||
|
|
||
| Changing `identity` starts a new conversation. Changing the widget ID or API endpoint requires calling `destroy()` before a new `init()`. | ||
|
|
||
| You can supply `supportEmail` and `starterQuestions` during initialization and change them later with `update()`. These values apply to the current embed and do not inherit from your Mintlify dashboard. | ||
|
|
||
| ## Configuration reference | ||
|
|
||
| ### `AssistantConfig` | ||
|
|
||
| Pass this object to `init()`. | ||
|
|
||
| | Option | Type | Description | | ||
| | ------------------ | ----------------------------------------------- | ---------------------------------------------------------------------------- | | ||
| | `id` | string | Public widget ID from the Mintlify dashboard. | | ||
| | `endpoint` | string | Overrides the hosted widget API endpoint. | | ||
| | `identity` | string | Signed end-user identity token. Omit for anonymous visitors. | | ||
| | `nonce` | string | CSP nonce copied to resources created by the widget. | | ||
| | `defaultOpen` | boolean | Opens the widget on its first initialization. The default is `false`. | | ||
| | `appearance` | [`AssistantAppearance`](#assistantappearance) | Visual and presentation overrides. | | ||
| | `labels` | [`AssistantLabels`](#assistantlabels) | Customer-facing text overrides. | | ||
| | `supportEmail` | string | Sets the support address shown in the widget toolbar for this embed. | | ||
| | `starterQuestions` | string[] | Sets up to **three** empty-state prompts for this embed. | | ||
| | `hooks` | [`AssistantHooks`](#assistanthooks) | Event and error observers. | | ||
|
|
||
| ### `AssistantAppearance` | ||
|
|
||
| | Option | Values | Description | | ||
| | -------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | ||
| | `variant` | `widget`, `modal`, `panel` | Controls whether the assistant opens as an anchored popover, centered dialog, or responsive side panel. | | ||
| | `theme` | `light`, `dark`, `system` | Sets the widget color scheme. The default is `system`. | | ||
| | `accent` | CSS color | Sets the color of primary controls. | | ||
| | `radius` | CSS border radius | Sets the panel radius, such as `18px`. | | ||
| | `font` | CSS font family | Uses a font already loaded by your application. The default is bundled Inter. | | ||
| | `side` | `top`, `bottom`, `left`, `right`, `inline-start`, `inline-end` | Positions the built-in trigger on a screen edge. | | ||
| | `align` | `start`, `center`, `end` | Aligns the trigger along its selected edge. | | ||
| | `dismissOnInteractOutside` | boolean | Controls whether pointer or focus interactions outside close the assistant. | | ||
| | `logo` | URL or `{ light, dark }` | Replaces the default Mintlify mark. | | ||
| | `zIndex` | number | Changes the stacking order of the widget host. | | ||
|
|
||
| Arbitrary CSS and neutral-palette overrides are not supported. The closed Shadow DOM protects both your application and the widget from cross-site style regressions. | ||
|
|
||
| ### `AssistantLabels` | ||
|
|
||
| | Option | Values | Description | | ||
| | ------------- | ----------------- | ------------------------------------------------------------------- | | ||
| | `title` | string or `null` | Sets the panel header. The default is `Assistant`. | | ||
| | `trigger` | string or `null` | Sets the compact widget and panel trigger text. | | ||
| | `placeholder` | string or `null` | Sets the composer and modal trigger placeholder. | | ||
| | `disclaimer` | string, `false`, or `null` | Sets the empty-state disclaimer. Pass `false` to hide it. | | ||
| | `suggestions` | string or `null` | Sets the heading above starter questions. The default is `Suggestions`. | | ||
|
|
||
| ### `AssistantHooks` | ||
|
|
||
| ```js | ||
| hooks: { | ||
| event(event) { | ||
| console.log(event.type, event.actor, event.source); | ||
| }, | ||
| error(error) { | ||
| console.error(error.code, error.retryable, error.status); | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| The `event` hook receives lifecycle and interaction metadata for `init`, `open`, `close`, `ask`, `update`, `reset`, `navigate`, and `destroy`. Events do not include question text, identity, session, or CAPTCHA tokens. | ||
|
|
||
| The `error` hook receives a stable `code`, a `retryable` boolean, and an optional HTTP `status`. Exceptions thrown by either hook do not interrupt the widget. | ||
|
|
||
| ### `AssistantOpenOptions` | ||
|
|
||
| Pass this optional object to `open()`. | ||
|
|
||
| | Option | Type | Description | | ||
| | -------- | ------- | -------------------------------------------------------------------- | | ||
| | `source` | string | Customer-defined attribution included in events and requests. | | ||
| | `focus` | boolean | Focuses the composer after opening. The default is `true`. | | ||
|
|
||
| ### `AssistantAskOptions` | ||
|
|
||
| Pass this optional object after the question string in `ask()`. | ||
|
|
||
| | Option | Type | Description | | ||
| | -------- | ------- | -------------------------------------------------------------------- | | ||
| | `source` | string | Customer-defined attribution included in events and requests. | | ||
| | `open` | boolean | Opens the panel before sending. The default is `true`. | | ||
| | `focus` | boolean | Focuses the composer when opening. The default is `true`. | | ||
|
|
||
| ### `AssistantUpdate` | ||
|
|
||
| Pass this object to `update()`. Every field is optional, and `null` restores its default. | ||
|
|
||
| | Option | Type | Description | | ||
| | ------------------ | ------------------------------------------------------- | ----------------------------------------------------------------- | | ||
| | `identity` | string or `null` | Changes the signed identity and starts a new conversation. | | ||
| | `appearance` | [`AssistantAppearance`](#assistantappearance) or `null` | Deep-patches appearance settings. | | ||
| | `labels` | [`AssistantLabels`](#assistantlabels) or `null` | Deep-patches customer-facing text. | | ||
| | `supportEmail` | string or `null` | Changes the support address. Pass `null` to remove it. | | ||
| | `starterQuestions` | string[] or `null` | Changes up to three prompts. Pass `null` to restore an empty list. | | ||
| | `hooks` | [`AssistantHooks`](#assistanthooks) or `null` | Deep-patches event and error observers. | | ||
|
|
||
| ## Browser API | ||
|
|
||
| | Method | Parameter types | Description | | ||
| | ------------------------ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------- | | ||
| | `init(config)` | [`AssistantConfig`](#assistantconfig) | Loads and mounts the widget. This is the readiness promise for every other method. | | ||
| | `open(options)` | [`AssistantOpenOptions`](#assistantopenoptions) | Opens the configured presentation. | | ||
| | `close()` | — | Closes the widget. | | ||
| | `ask(question, options)` | string, [`AssistantAskOptions`](#assistantaskoptions) | Opens the widget if requested and sends a question. | | ||
| | `update(config)` | [`AssistantUpdate`](#assistantupdate) | Deep-patches mutable identity, appearance, copy, and observer settings. | | ||
| | `reset()` | — | Starts a fresh conversation. | | ||
| | `destroy()` | — | Removes the widget and releases its browser resources. | | ||
|
|
||
| Conversation snapshots remain private to the widget. Each method resolves to `void`. | ||
|
|
||
| ## Content Security Policy | ||
|
|
||
| If your site uses a Content Security Policy, allow the origins required by your enabled widget features: | ||
|
|
||
| | Directive | Source | Required for | | ||
| | -------------------------------------------- | ----------------------------------- | --------------------------- | | ||
| | `script-src` | `https://cdn.jsdelivr.net` | Widget loader and runtime | | ||
| | `connect-src` | `https://api.mintlify.com` | Widget API | | ||
| | `style-src` | `https://cdn.jsdelivr.net` | Widget style sheet | | ||
| | `font-src` | `https://cdn.jsdelivr.net` | Optional bundled Inter font | | ||
| | `script-src`, `connect-src`, and `frame-src` | `https://challenges.cloudflare.com` | Turnstile bot protection | | ||
| | `script-src` | `https://js.hcaptcha.com` | hCaptcha bot protection | | ||
| | `connect-src` and `frame-src` | `https://*.hcaptcha.com` | hCaptcha bot protection | | ||
|
|
||
| A strict `script-src` policy must still authorize both the loader and initialization script. Passing `nonce` to `init()` propagates it only to resources the widget creates after initialization. | ||
|
|
||
| </AssistantWidgetPlayground> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| @media (min-width: 1024px) { | ||
| html[data-current-path="/assistant/widget"] #content-area { | ||
| position: relative; | ||
| max-width: 1800px !important; | ||
| margin-inline: auto; | ||
| /* Percentage padding resolves against the parent, so cap it at half of the 1800px max-width */ | ||
| padding-right: calc(min(50%, 900px) + 1rem); | ||
| } | ||
|
|
||
| html[data-current-path="/assistant/widget"] #content { | ||
| position: static; | ||
| } | ||
|
|
||
| html[data-current-path="/assistant/widget"] [data-assistant-preview] { | ||
| position: absolute; | ||
| inset: 0 1.5rem 0 auto; | ||
| width: calc(50% - 2.5rem); | ||
| } | ||
| } | ||
|
|
||
| html[data-current-path="/assistant/widget"] | ||
| div:has(> iframe[title="Live Assistant Widget preview"]) { | ||
| min-height: 0; | ||
| flex: 1 1 0%; | ||
| } | ||
|
|
||
| html[data-current-path="/assistant/widget"] | ||
| iframe[title="Live Assistant Widget preview"] { | ||
| height: 100%; | ||
| } | ||
|
|
||
| /* The widget playground embeds /assistant/widget-preview in its preview | ||
| iframe. The suffix match keeps localized paths covered. Hide every piece of | ||
| docs chrome so only the widget renders, and keep the document transparent | ||
| so the playground card provides the visible frame. */ | ||
| html[data-current-path$="/assistant/widget-preview"] #navbar, | ||
| html[data-current-path$="/assistant/widget-preview"] #navbar-transition, | ||
| html[data-current-path$="/assistant/widget-preview"] #mobile-nav, | ||
| html[data-current-path$="/assistant/widget-preview"] #banner, | ||
| html[data-current-path$="/assistant/widget-preview"] #sidebar, | ||
| html[data-current-path$="/assistant/widget-preview"] #footer, | ||
| html[data-current-path$="/assistant/widget-preview"] #assistant-entry, | ||
| html[data-current-path$="/assistant/widget-preview"] #assistant-entry-mobile, | ||
| html[data-current-path$="/assistant/widget-preview"] [aria-label="Preview Widget"], | ||
| html[data-current-path$="/assistant/widget-preview"] [aria-label="Preview Widget Menu"] { | ||
| display: none !important; | ||
| } | ||
|
|
||
| html[data-current-path$="/assistant/widget-preview"], | ||
| html[data-current-path$="/assistant/widget-preview"] body { | ||
| width: 100%; | ||
| height: 100%; | ||
| margin: 0; | ||
| overflow: hidden !important; | ||
| background: transparent !important; | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Locale paths miss playground layout
Medium Severity
Playground layout rules use an exact
data-current-path="/assistant/widget"match, so localized paths like/es/assistant/widgetnever get the side-by-side layout or iframe sizing. The widget-preview rules in the same file already use a suffix match specifically to cover locales, and the playground JS also parses locale segments.Reviewed by Cursor Bugbot for commit 9b2d208. Configure here.