<!-- Source: https://docs.squirro.com/en/latest/technical/neo/dev-guide/embedding-chat/add-chat.html -->
# Add the Chat to Your Page

This page covers the second step of embedding Neo chat: adding the chat to your page, checking it, and matching it to your site. It assumes a running proxy, as described on the [Set Up the Proxy](set-up-proxy.md#neo-extensions-embedding-chat-proxy) page.

## With a Script Tag

For a page without a build step, the SDK is a single JavaScript file, `neo-sdk.js`. To host it yourself, copy `dist/embed/neo-sdk.js` and `dist/embed/neo-sdk.js.LICENSE.txt` from the package on the proxy server to one folder of your site, together with `THIRD-PARTY-NOTICES.md` from the root of the package. The licenses of the bundled packages require both license files to go wherever the script goes.

Alternatively, load the script from a public npm CDN, such as jsDelivr, with an exact version and the `integrity` hash of the file, so that the CDN can never serve your readers a different file. Set `crossorigin="anonymous"` on the tag, without which the browser blocks the script. The `docs/script-tag.md` file in the package shows the tag.

Then add the script and the element to your page:

```html
<script src="/assets/neo-sdk.js" defer></script>

<neo-chat base-url="/api/chat" project-id="YOUR_PROJECT_ID" auth="anonymous"></neo-chat>
```

`neo-sdk.js` is about 689 kB gzipped and includes the search and document widgets. With `defer`, it does not block your page.

`base-url` is the address of your proxy plus its mount path, never your Squirro instance. For a proxy on another origin, give the full URL, such as `https://chat-proxy.example.com/api/chat`. `auth="anonymous"` tells the chat to fetch its tokens from the proxy.

An inline `<neo-chat>` needs a height:

```css
neo-chat {
  display: block;
  height: 600px;
}
```

Besides `base-url`, `project-id`, and `auth`, the element takes attributes for its layout, theme, page context, links, and welcome. For every attribute, see the Element Attributes section of the [Configuration Reference](configuration-reference.md#neo-extensions-embedding-chat-configuration) page.

Set anything that markup cannot express, such as functions and nested objects, as a property of the element. The element reads its configuration once, when it starts, and ignores later changes. A tag in your HTML starts once the HTML has loaded, so a script right after the tag is in time, whether `neo-sdk.js` loads with `defer` or not:

```html
<script src="/assets/neo-sdk.js" defer></script>
<neo-chat id="chat" base-url="/api/chat" project-id="YOUR_PROJECT_ID" auth="token"></neo-chat>
<script>
  const chat = document.getElementById('chat');
  chat.getToken = () => fetch('/my-session-token').then((response) => response.text());
  chat.theme = { primary: '#0f766e', mode: 'auto', dark: { primary: '#2dd4bf' } };
</script>
```

An element that you create from a script starts once you add it to the page, so set its properties before you add it.

If your framework manages the DOM itself, use `NeoSdk.mount` on an element that you already have. It takes the same options as the React setup in the next section, and returns `{ sdk, unmount }`:

```javascript
const { sdk, unmount } = NeoSdk.mount(document.getElementById('chat-host'), {
  baseUrl: '/api/chat',
  projectId: 'YOUR_PROJECT_ID',
  auth: 'anonymous',
});
```

The chat renders inside a shadow root. The CSS of your page cannot restyle it by accident, and the styles of the chat cannot leak onto your page.

## With React

Install the package, import its stylesheet once, and wrap the chat in its provider:

```jsx
import '@squirro/neo-sdk/styles.css';
import { initNeoSdk, NeoChat, NeoSdkProvider } from '@squirro/neo-sdk';

// Once, outside render.
const sdk = initNeoSdk({
  baseUrl: '/api/chat',
  projectId: 'YOUR_PROJECT_ID',
  auth: 'anonymous',
});

export function HelpPanel() {
  return (
    <NeoSdkProvider sdk={sdk}>
      <NeoChat className="h-full" />
    </NeoSdkProvider>
  );
}
```

To install the package, run `npm install @squirro/neo-sdk@~0.1` in the folder of your React app. The components need `react` and `react-dom` 19.3.0 or later, and `@tanstack/react-query` 5.103.2 or later. npm also installs the other libraries that the core expects, such as `react-router-dom` 7, `zustand` 5, and `lucide-react` 0.525, and reports a conflict if your app uses a version outside the range that the core accepts. The `docs/installing.md` file in the package covers the TypeScript settings and the development server setup. The stylesheet is scoped to the chat: it does not reset or restyle anything else on your page.

## Signing Readers In

`auth` says how the page gets the token that it sends to the proxy:

| `auth` | The page | Pair it with |
| --- | --- | --- |
| `anonymous` | Fetches a token from the `/token` route of the proxy. | `anonymous(...)` on the proxy. |
| `token` | Calls your `getToken()` and sends what it returns. | `bearerSession(verify)` on the proxy. |
| `none` | Sends no token. | A proxy that checks something else, such as a same-origin session cookie or a network allowlist. |

For the values that `getToken` can return, see the Options section of the [Configuration Reference](configuration-reference.md#neo-extensions-embedding-chat-configuration) page.

A session cookie reaches the proxy only when the proxy is on the same origin as your page. For a proxy on another origin, use `token` or `anonymous`.

## Check the Chat

Open your page, and ask a question that your documents answer. The answer appears as it is written, with citations to the documents. Open a cited PDF document. With `NUTRIENT_LICENSE_KEY` set, it shows without an evaluation watermark. If the chat shows an error instead, see the [Troubleshooting](troubleshooting.md#neo-extensions-embedding-chat-troubleshooting) page.

## Match Your Site

### Colors and Fonts

With no theme, the chat uses a neutral gray palette in light mode, and the font of your page. Set `theme` to match your brand:

```javascript
theme: {
  primary: '#0f766e',
  radius: '6px',
  mode: 'auto',
  dark: { primary: '#2dd4bf', background: '#111827' },
}
```

For the color keys of the theme, see the Theme Keys section of the [Configuration Reference](configuration-reference.md#neo-extensions-embedding-chat-configuration) page. The theme also takes the following options:

- `mode`

  `light`, the default, `dark`, or `auto`, which follows the system setting of the reader.
- `dark`

  The same color keys, for dark mode only. A brand `primary` chosen for a light page is usually too dark on a dark one, so set a lighter `dark.primary`, with a contrast ratio of 4.5:1 or more against `dark.background`.
- `fontFamily` and `fontSize`

  Override the font inherited from your page. The chat never loads a font itself.
- `preset`

  `squirro` uses the Squirro palette instead of the neutral one.

On a script-tag page, you can also write the theme as JSON inside the element:

```html
<neo-chat base-url="/api/chat" project-id="YOUR_PROJECT_ID" auth="anonymous">
  <script type="application/json">
    { "primary": "#0f766e", "radius": "6px", "mode": "auto", "dark": { "primary": "#2dd4bf" } }
  </script>
</neo-chat>
```

### Inline or Floating

**Inline** is the default. The chat fills the box that you give it, like any other part of your page.

**Floating** adds a launcher button in a corner of the window, which opens the chat as a panel above your page:

```javascript
layout: {
  mode: 'floating',
  position: 'bottom-right', // or 'bottom-left'
  launcherLabel: 'Ask the docs',
  panelSubtitle: 'Answers from our documentation', // optional line under the title
  panelWidth: '420px',
  panelHeight: '70vh',
  defaultOpen: false, // true shows the panel open when the page loads
}
```

Open and close the panel from your own code with `sdk.open()` and `sdk.close()`. For where `sdk` comes from, see the Ask from Your Own Buttons section of the [Connecting the Chat to Your Page](connect-chat.md#neo-extensions-embedding-chat-connect) page.

### Welcome the Reader

Until the first question, the chat shows a welcome: a heading, a line under it, and any questions that you suggest, which the reader sends with one click. Set `welcome` to change it:

```javascript
welcome: {
  title: 'Ask the Northwind docs',
  message: 'Answers link to the docs pages.',
  suggestions: ['Where do I set up webhooks?', 'How do I authenticate?'],
}
```

The chat shows up to four suggestions and sends a clicked one as if the reader had typed it.

On a script-tag page, set the `welcome-title`, `welcome-message`, and `welcome-suggestions` attributes instead, with the questions separated by `|`.

In React, `<NeoChat welcome={{ ... }} />` sets the welcome for one chat, and takes precedence over `welcome` in `initNeoSdk()`. `welcomeContent` replaces the welcome with your own content instead.
