# Web Components (/docs/modules/web-components)

`@aiconnect/elements` is the interface modules as custom elements, in one script that holds React, the modules and their styles. A page with no build step loads it with a script tag and writes `<aiconnect-chat>` or `<aiconnect-search>` where the module goes. Each element reads your tools from your MCP server.

## Load the script [#load-the-script]

```html
<script src="/aiconnect-elements.js" defer></script>
```

<Callout type="warn">
The package is not published on npm yet, so no CDN serves the script. Build a checkout of the AI Connect repository with `npm run build` and host `packages/elements/dist/aiconnect-elements.js` with your site's files, next to its source map. The script is about 720 KB, 216 KB compressed with gzip.
</Callout>

The script defines both elements once, however many times the page includes it, and every element of the page shares one connection to the visitor's AI. Elements written before the script loads come alive when it does.

## Write the elements [#write-the-elements]

```html title="A page of the bookshop"
<header>
  <b>Bookshop</b>
  <aiconnect-chat variant="panel" mcp="/api/mcp" launcher-label="Ask the shop"
    system="You recommend books from this site's catalog. Always search the catalog before recommending."
    tool-labels='{"search_books": "Searching the catalog"}'></aiconnect-chat>
</header>
<main>
  <h1>Books for every mood</h1>
  <aiconnect-search mcp="/api/mcp"
    system="You answer questions about this bookshop's catalog. Always search the catalog first."
    suggestions='["A calm book for tonight", "Something funny"]'></aiconnect-search>
</main>
<aiconnect-chat variant="popup" mcp="/api/mcp"
  system="You recommend books from this site's catalog."></aiconnect-chat>
```

The demo of the AI Connect repository serves this page with every form at `/elements.html`.

## `<aiconnect-chat>` [#aiconnect-chat]

| Attribute | What it sets |
| --- | --- |
| `variant` | The form: `inline` (the default), `panel`, `popup` or `page`. |
| `system` | The instructions the visitor's model gets before the first question. |
| `mcp` | The address of your MCP server, such as `/api/mcp`. |
| `heading` | The module's heading. It is not `title`, which would show as the browser's tooltip over the element. |
| `intro` | The heading of an empty conversation. |
| `placeholder` | The question box's placeholder. |
| `suggestions` | Questions the visitor sends with one click, as a JSON array of strings. |
| `tool-labels` | A plain name per tool, as a JSON object from tool name to label. |
| `locale` | `en` (the default), `fr` or `he`. Hebrew lays the module out right to left. |
| `open` | Present while a panel, popup or full page is open. Set it or remove it to open or close one; the element updates it when the visitor does. |
| `hide-launcher` | Hides the module's own button, for a page that opens it from its own. |
| `launcher-label` | The text of the module's own button. |

A JSON attribute that does not parse is reported in the console and left out.

The element also has:

- `open`, `show()` and `hide()`, which read and set the `open` attribute.
- `tools`, a property for a page without an MCP server: any object with `listTools` and `callTool`, as the [React quickstart](/docs/quickstart/react#try-it-without-a-server) shows.
- an `aiconnect-toggle` event each time the visitor opens or closes it, with `detail.open`.

```html
<button type="button" id="ask">Ask our assistant</button>
<aiconnect-chat id="assistant" variant="popup" hide-launcher mcp="/api/mcp" system="..."></aiconnect-chat>
<script>
  document.querySelector('#ask').addEventListener('click', () => document.querySelector('#assistant').show());
</script>
```

## `<aiconnect-search>` [#aiconnect-search]

The [search bar](/docs/modules/search). It takes `system`, `mcp`, `placeholder`, `suggestions`, `tool-labels` and `locale`, and the `tools` property.

## Theming [#theming]

Each element draws its module inside its own shadow root, so your page's styles for `p`, `button` or `input` do not reach it. The `--aic-*` tokens do: the script adds their default values first in the page's head, and the values your stylesheet sets on `:root`, on an ancestor or on the element itself win and reach the module.

```css
:root {
  --aic-font: 'Montserrat', sans-serif;
  --aic-accent: #6f6754;
  --aic-radius: 18px;
}
```

`data-aic-theme="dark"` on `<html>`, on an ancestor or on the element gives the dark palette, and `data-aic-theme="auto"` follows the system setting. The [modules' tokens](/docs/modules#theming-the-modules) and the [theming guide](/docs/guides/theming) list them all.

## WordPress [#wordpress]

Upload `aiconnect-elements.js` to your theme or to the media library, load it in your theme's header, and add a Custom HTML block where the module goes:

```html title="Custom HTML block"
<aiconnect-chat mcp="https://your-site.example/wp-json/your-plugin/mcp"
  heading="Ask our recipes" system="You answer from this site's recipes. Search them before you answer."
  suggestions='["A quick dinner tonight", "Something vegetarian"]'></aiconnect-chat>
```

The MCP server is the part your site still provides: a route that serves your content as tools, as the [MCP guide](/docs/guides/mcp-tools) describes.
