> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waniwani.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat embed

> Drop-in chat for any website. The dashboard generates the snippet — you paste it.

The chat embed is a self-contained IIFE bundle that drops the Waniwani chat into any website. It talks directly to `app.waniwani.ai`, so no backend proxy is required on your side.

<Note>
  **Platform feature.** The dashboard generates the embed snippet for your project. [Open app.waniwani.ai](https://app.waniwani.ai) to get yours, or read more about the [Platform](/sdk/platform/overview).
</Note>

The embed mounts **inline** wherever you place a `<div data-waniwani-embed></div>` marker. You control the size by sizing that container with CSS. There is no floating bubble.

## Quick start

1. Open your project on [app.waniwani.ai](https://app.waniwani.ai) and copy the chat embed snippet from the project settings.
2. Paste it into your site's HTML, alongside a mount point where you want the chat to appear:

```html theme={null}
<!-- Where the chat appears, sized by your CSS -->
<div data-waniwani-embed style="height: 600px; max-width: 480px;"></div>

<!-- The <script> tag you copied from the dashboard goes here. -->
```

That's it. The chat mounts inside your marker div via Shadow DOM (so its styles never leak into your page).

The snippet ships pre-wired with your project token, channel ID, and any defaults you configured in the dashboard. **Don't hand-author it** — the channel ID is issued by the Platform and required for the embed to route correctly.

## Sizing

The embed fills its container. Give the `<div data-waniwani-embed>` a definite size via CSS:

```html theme={null}
<!-- Fixed height -->
<div data-waniwani-embed style="height: 600px;"></div>

<!-- Bounded by max-height -->
<div data-waniwani-embed style="max-height: 80vh;"></div>

<!-- Flex column child -->
<div style="display: flex; flex-direction: column; max-height: 800px;">
  <div data-waniwani-embed style="flex: 1 1 auto; min-height: 0;"></div>
</div>
```

If the parent is fully unbounded the chat grows with content. A `ResizeObserver` mirrors the container's `max-height` onto the embed so padding and borders are respected.

## Overriding attributes

The snippet you paste is a starting point. After pasting, you can edit `data-*` attributes on the `<script>` tag to tweak behavior:

| Attribute                    | Type                     | Notes                                                   |
| ---------------------------- | ------------------------ | ------------------------------------------------------- |
| `data-title`                 | string                   | Header title. Defaults to `"Assistant"`.                |
| `data-welcome-message`       | string                   | Greeting shown before the first message.                |
| `data-placeholder`           | string                   | Input field placeholder.                                |
| `data-suggestions`           | string (comma-separated) | Initial suggestion chips.                               |
| `data-enable-thread-history` | boolean                  | Persist threads in IndexedDB. Defaults to `false`.      |
| `data-css`                   | string                   | URL to a custom stylesheet loaded into the shadow root. |
| `data-primary-color`         | string                   | Brand color (bubble, send button).                      |
| `data-background-color`      | string                   | Panel background.                                       |
| `data-text-color`            | string                   | Default text color.                                     |
| `data-font-family`           | string                   | Custom font stack.                                      |

Leave the wiring attributes (`data-token`, `data-channel-id`, `data-api`, the script `src`) as the dashboard generated them.

Full type definitions: [`EmbedConfig`](https://github.com/WaniWani-AI/sdk/blob/main/src/chat/web/embed/config.ts) and [`ChatTheme`](https://github.com/WaniWani-AI/sdk/blob/main/src/chat/web/%40types.ts).

## Programmatic init

For runtime control (computing options dynamically, mounting on demand), drop the `data-token` attribute from the script tag and call `init()` manually. You still need the wiring attributes from a dashboard-issued snippet:

```html theme={null}
<div data-waniwani-embed></div>

<!-- Keep the script src and data-channel-id from the dashboard snippet,
     just remove data-token so the embed doesn't auto-init. -->
<script
  src="https://cdn.jsdelivr.net/npm/@waniwani/sdk@latest/dist/chat/embed.js"
  data-channel-id="..."
  defer
></script>
<script>
  window.addEventListener("DOMContentLoaded", () => {
    window.WaniWani.chat.init({
      token: "wwp_...", // from the dashboard snippet
      welcomeMessage: computeGreetingForUser(),
    });
  });
</script>
```

`init()` returns an instance with `destroy()` and `sendMessage(text)`. You can also call `window.WaniWani.chat.destroy()` and `window.WaniWani.chat.sendMessage("...")` directly on the global.

## Self-hosting the JS bundle

If you'd rather not load from a CDN, pin a specific SDK version and serve the bundled file yourself. The `data-*` attributes still come from the dashboard snippet — you're only swapping where `embed.js` is served from:

```bash theme={null}
bun add @waniwani/sdk
cp node_modules/@waniwani/sdk/dist/chat/embed.js public/waniwani-embed.js
```

Then point the dashboard-issued snippet at your local copy:

```html theme={null}
<div data-waniwani-embed></div>
<script
  src="/waniwani-embed.js"
  data-token="wwp_..."
  data-channel-id="..."
  defer
></script>
```

## How it works

1. The script reads its own `data-*` attributes (token, channel ID, theming, content overrides).
2. On `DOMContentLoaded` (or immediately, if the DOM is already ready), it locates `[data-waniwani-embed]` and mounts the chat inside it via Shadow DOM.
3. The chat calls `app.waniwani.ai/api/mcp/chat` with the project token and streams responses back through Server-Sent Events.
4. Conversation history lives only in memory by default; set `data-enable-thread-history` to persist threads in IndexedDB on the user's device.

No server-side integration on your side. If you want React-component-level control instead of the script tag, see [Chat in React](/sdk/chat/react).
