How to Embed a Smarter Chatbot in an HTML Web Page

Add a Smarter chatbot to any HTML page with one script tag from @smarter.sh/ui-chat: a chat button, an inline chat, options, styling and troubleshooting.

One script tag puts your Smarter chatbot on any HTML page. No build step, no React, no CSS of your own.

Smarter is a platform for building and running AI chatbots. You declare a chatbot, called an LLMClient, in a short YAML manifest that sets its LLM, system prompt, tools, welcome message and look. Smarter runs it. The npm package @smarter.sh/ui-chat is its front end, the same chat window used in the Smarter web console, published so you can put it on your own site.

By the end of this article you will have the following.

  • a chat button in the corner of your page that opens your chatbot in a panel, and
  • optionally, the chat placed inline in the page, for example on a Support page.

The package ships a prebuilt embed script, embed.js, that bundles React and the chat. It renders inside a Shadow DOM, so your site’s styles can’t break the chat, and the chat can’t change your site.

Your HTML page holds one script tag that loads embed.js with data-chatbot set to the LLMClient's url. In the visitor's browser it shows a chat button and loads the chat only on a click, inside a Shadow DOM, keeping the session in a cookie. The deployed LLMClient checks the page's origin against allowedOrigins, sends the name, welcome message and styles, and runs each prompt. The page sets only placement and size; the manifest holds the LLM, prompt, tools and look.

Before you start

You need a deployed LLMClient that allows your page’s origin. The chat calls Smarter straight from your visitors’ browsers, so Smarter has to know your site.

  1. Deploy the LLMClient. Set spec.config.prompt.deployed: true in its manifest. Its url looks like https://<name>.<account-number>.api.<your-smarter-domain>/, or its verified custom domain. This url is the only thing the page needs.
  2. Allow your origin. List every origin that will embed the chat (scheme, host and port must match exactly), including your local test server.
apiVersion: smarter.sh/v1
kind: LLMClient
metadata:
  name: support
  description: Customer support for example.com
  version: 1.0.0
spec:
  config:
    prompt:
      deployed: true
      provider: openai
      defaultModel: gpt-4o-mini
      defaultSystemRole: You are a friendly support agent for example.com. Answer briefly.
      appName: Example Support
      appAssistant: Sam
      appWelcomeMessage: Hi, I'm Sam. How can I help?
      appExamplePrompts:
        - How do I reset my password?
        - What is your return policy?
      allowedOrigins:
        - https://www.example.com
        - http://localhost:8000
  1. Apply it with smarter apply -f llmclient.yaml.
  2. Decide on an api key. A deployed LLMClient without api keys is public, and prompts are charged to its owner. If yours requires a key, the page must carry one, and any visitor can read it. Create a key used only for that site.

Add the chat button

Paste this tag just before </body>, with your LLMClient’s url in data-chatbot.

<script
  src="https://cdn.jsdelivr.net/npm/@smarter.sh/ui-chat@0/dist/embed.js"
  data-chatbot="https://support.3141-5926-5359.api.example.com/"
  async
></script>

That’s the whole integration. A chat button appears in the bottom-right corner. The chat itself loads only when a visitor clicks it, so the tag costs your page almost nothing. The conversation is kept in a cookie and follows the visitor from page to page.

Here is a complete page you can save as index.html and serve locally with python3 -m http.server 8000.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Example Co.</title>
  </head>
  <body>
    <h1>Welcome to Example Co.</h1>
    <p>Questions? Click the chat button in the corner.</p>

    <script
      src="https://cdn.jsdelivr.net/npm/@smarter.sh/ui-chat@0/dist/embed.js"
      data-chatbot="https://support.3141-5926-5359.api.example.com/"
      data-position="bottom-right"
      data-label="Chat with Sam"
      data-color="#14213d"
      async
    ></script>
  </body>
</html>

Open http://localhost:8000, click the button, and you should see your chatbot’s name, welcome message and example prompts, all read from its manifest.

Optionally, put the chat in the page

For a dedicated Support or Help page, place the chat inline with the <smarter-chat> element. The script tag above defines it, so load the script on that page too.

<main>
  <h1>Support</h1>
  <smarter-chat
    chatbot="https://support.3141-5926-5359.api.example.com/"
    height="600px"
  ></smarter-chat>
</main>

The element defaults to inline mode and fills 100% of its container’s width. On that page, load the script without data-chatbot, so it defines the element but adds no floating button.

Two schematic pages side by side. On the left, in launcher mode, the script tag with data-chatbot adds a chat button in the bottom-right corner that opens a 400px by 600px chat panel. On the right, in inline mode, a Support page holds the smarter-chat element, which fills its container's width at the height you set, such as 600px.
<script src="https://cdn.jsdelivr.net/npm/@smarter.sh/ui-chat@0/dist/embed.js" async></script>

Options

Only chatbot is required. Each option works as an attribute on <smarter-chat>, a data- attribute on the script tag, or a camelCase property of window.SmarterChatConfig.

OptionDefaultWhat it does
chatbot(required)The deployed LLMClient’s url
api-keyA Smarter api key, only if the LLMClient requires one; visible in the page
modelauncher (script), inline (element)Floating button, or in the page
positionbottom-rightbottom-right or bottom-left
openfalseStart with the panel open
labelChatThe button’s accessible name
color#ff5733The button’s color
width, height400px, 600pxPanel size, any css length
languagethe page’sen, es, fr or pt-br
targetScript and config only, a css selector to render inline into

The full list, including z-index, cookie and debug options, is in the package README.

Customizing the chat

Change the chat’s look in the LLMClient’s manifest, not in your page. Apply a new manifest and every page that embeds the chatbot picks it up on the next chat session, with no redeploy of your site.

spec:
  config:
    styles:
      appLogoUrl: https://cdn.example.com/logo.png
      googleFont: Nunito
      borderRadius: 0.7em
      conversationHeader: { backgroundColor: "#14213d", color: "#ffffff" }
      outgoingMessage: { backgroundColor: "#fca311", color: "#14213d" }
      buttons: { color: "#fca311" }

Your page controls only placement and size (the options above). For the rest, the launcher exposes CSS parts.

smarter-chat::part(launcher) { box-shadow: 0 4px 12px rgb(0 0 0 / 0.25); }
smarter-chat::part(panel) { border-radius: 12px; }

Your own buttons can drive the launcher too.

<button onclick="SmarterChat.open()">Talk to support</button>

SmarterChat.close() and SmarterChat.toggle() also exist, and the element fires a smarter-chat-toggle event with event.detail.open.

No script attributes? Use SmarterChatConfig

Some tools, such as tag managers, add script tags for you. Set the options as a global before the script loads.

<script>
  window.SmarterChatConfig = {
    chatbot: "https://support.3141-5926-5359.api.example.com/",
    position: "bottom-left",
  };
</script>
<script src="https://cdn.jsdelivr.net/npm/@smarter.sh/ui-chat@0/dist/embed.js" async></script>

Pinning or self-hosting the script

@0 follows the latest 0.x release. To review changes before your visitors see them, pin an exact version, such as @smarter.sh/ui-chat@0.36.10. To serve the script from your own site, copy dist/embed.js and the dist/embed/ folder together (for example from npm pack @smarter.sh/ui-chat); the folder holds Mermaid and KaTeX fonts, loaded only when an answer has a diagram or math.

Building a React app instead?

Install the package (npm install @smarter.sh/ui-chat) and render the SmarterChat component directly, with react and react-dom 19 as peers.

import { SmarterChat } from "@smarter.sh/ui-chat";
import "@smarter.sh/ui-chat/dist/ui-chat.css";
import "katex/dist/katex.min.css";

export function Support() {
  return (
    <div style={{ height: 600 }}>
      <SmarterChat apiUrl="https://support.3141-5926-5359.api.example.com/" />
    </div>
  );
}

The chat fills its parent’s height, so give the parent one.

Troubleshooting

SymptomLikely cause and fix
No chat button appearsdata-chatbot is missing or isn’t an http(s) url. Add data-debug="true" and check the browser console.
The chat says it isn’t available, or the console shows “blocked by CORS policy”Your page’s origin isn’t in allowedOrigins. Scheme, host and port must match exactly, so http://localhost:8000 and http://127.0.0.1:8000 are different origins. Re-apply the manifest.
401 or 403 errorsThe LLMClient requires an api key. Add data-api-key, using a key made for this site.
The chat is a thin stripAn inline chat fills its height. Set height on <smarter-chat>.
Equations show as plain text (React only)Import katex/dist/katex.min.css. The embed script handles this itself.

Next steps

Sources