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

# Add a search bar to your marketing site

> Let anonymous visitors ask questions about your public data, from a static HTML site. No server code, about 15 minutes.

In this tutorial, you add an assistant to a two-page static site. The home page gets a search bar in its hero. The pricing page gets a chat bubble. Visitors ask in plain language and get answers from the data you chose to make public. You will:

* choose what anonymous visitors may ask about,
* put the bar and the bubble on your pages, with two HTML tags each,
* check what visitors can and cannot see,
* allow Concatflow in a Content Security Policy.

There is no build step and no server code. Any host that serves HTML works.

## Before you start

You need an assistant that is **published**, with its **Isolation** signed. You also need Node 18 or later, only to serve the pages on your laptop.

## 1. Choose what visitors may ask about

The public door answers anyone, without a login. It only reads the tables you put in its scope, and only tables that hold no customer data.

1. In the [Concatflow dashboard](https://app.concatflow.com), open your assistant, then **Isolation**. A table can enter the public scope only if it is marked as a shared reference, visible to all customers: a product catalogue, a price list, your branches.
2. Open **Doors**. Turn the **public door** on.
3. Click **Edit the public scope**. Tick the shared tables visitors may ask about. Tables holding customer data cannot be ticked: they only go through the per-user door.
4. Set **Rate per visitor**. 60 questions per hour is the default.

## 2. Allow your origins

In **Doors → Allowed origins**, add the origin you will test from:

```text theme={"system"}
http://localhost:8000
```

The assistant only answers pages served from an allowed origin. An origin is a scheme, a host and a port: `http://localhost:8000` and `http://127.0.0.1:8000` are two different origins. You add your production origins in step 8.

## 3. Copy your site token

In **Doors**, the public door shows its **Page code**. Copy the site token from it: it starts with `st_`.

The site token is public. It is meant to sit in your HTML, like a Stripe publishable key. It only opens the public door, from your allowed origins.

## 4. Put the bar in your hero

Create a folder for the site, and an `index.html` in it. Replace `st_YOUR_SITE_TOKEN` with your token.

```html index.html theme={"system"}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Acme</title>
    <style>
      body { margin: 0; font-family: system-ui, sans-serif; color: #1a1a19; background: #fbfaf7; }
      nav { display: flex; gap: 24px; padding: 20px 32px; }
      .hero { max-width: 640px; margin: 80px auto; padding: 0 24px; text-align: center; }
      .hero h1 { font-size: 40px; margin: 0 0 12px; }
      .hero p { color: #5f5e5a; margin: 0 0 32px; }
    </style>
  </head>
  <body>
    <nav><strong>Acme</strong> <a href="/">Home</a> <a href="/pricing.html">Pricing</a></nav>
    <section class="hero">
      <h1>Everything about our offers</h1>
      <p>Ask a question in plain language.</p>
      <concatflow-assistant
        site-token="st_YOUR_SITE_TOKEN"
        launcher="bar"
        placeholder="Ask about our offers, prices, branches…"
        accent="#c2410c"
        theme="light"
      ></concatflow-assistant>
    </section>
    <script src="https://app.concatflow.com/widget.js"></script>
  </body>
</html>
```

The bar renders where `<concatflow-assistant>` is written, and fills the width of its container: here, the hero's 640px. The script can sit at the end of the body. It defines the element when it loads.

* `placeholder` is the text in the empty bar. Set it: the default is in French.
* `accent` colours the bar's magnifier and focus ring. The colours inside the assistant come from the dashboard's **Appearance** tab.
* `theme="light"` matches a light site. Without it, the assistant uses the dashboard's theme.

![A home page hero with a search bar under the heading](https://mintcdn.com/concatflow/xCmphOUeinyoVnFX/images/tutorials/marketing-site/home-bar.png?fit=max\&auto=format\&n=xCmphOUeinyoVnFX\&q=85\&s=05760b5e19a440babedf67410e60ff22)

The bar in the hero, with your placeholder and accent.

## 5. Put the bubble on your other pages

On pages without a natural place for a search field, use the bubble. Leave out `launcher`:

```html pricing.html theme={"system"}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Pricing · Acme</title>
    <style>
      body { margin: 0; font-family: system-ui, sans-serif; color: #1a1a19; background: #fbfaf7; }
      nav { display: flex; gap: 24px; padding: 20px 32px; }
      main { max-width: 640px; margin: 80px auto; padding: 0 24px; }
    </style>
  </head>
  <body>
    <nav><strong>Acme</strong> <a href="/">Home</a> <a href="/pricing.html">Pricing</a></nav>
    <main>
      <h1>Pricing</h1>
      <p>Questions about a plan? Ask the assistant in the corner.</p>
    </main>
    <concatflow-assistant site-token="st_YOUR_SITE_TOKEN" theme="light"></concatflow-assistant>
    <script src="https://app.concatflow.com/widget.js"></script>
  </body>
</html>
```

The bubble sits 20px from the bottom-right corner, wherever the element is written. A click opens a panel above it. The panel's input shows the **Prompt** of the dashboard's **Appearance** tab: write it in your site's language.

## 6. Run it

From the site's folder:

```bash theme={"system"}
npx serve --listen 8000
```

Open [http://localhost:8000](http://localhost:8000). Click the bar, or press <kbd>⌘</kbd> <kbd>K</kbd> (<kbd>Ctrl</kbd> <kbd>K</kbd> on Windows and Linux). Ask a question about one of the tables you ticked, such as "Which offers do you have?". The answer unfolds under the bar, with a table or a list when the answer needs one. Press <kbd>Esc</kbd> to fold it.

![The bar with the question Which offers do you have, and an answer with a list and a table of offers](https://mintcdn.com/concatflow/xCmphOUeinyoVnFX/images/tutorials/marketing-site/home-answer.png?fit=max\&auto=format\&n=xCmphOUeinyoVnFX\&q=85\&s=ef94f2a2a244e83b8ef0331b455336a6)

The answer unfolds under the bar. The table comes straight from your database.

Then open **Pricing** and click the bubble.

![The pricing page with the chat panel open, showing a table of branches](https://mintcdn.com/concatflow/xCmphOUeinyoVnFX/images/tutorials/marketing-site/pricing-bubble.png?fit=max\&auto=format\&n=xCmphOUeinyoVnFX\&q=85\&s=52bc5f691eea3f6e29a591d37d9e7f89)

The bubble opens a panel in the corner.

> [!TIP]
>
> No answer? Your page's origin is probably not allowed. In the browser console, `location.origin` must match an entry of **Allowed origins** exactly. Nothing shows at all? The console names the problem: a missing `site-token`, or a blocked script.

## 7. Check what visitors cannot see

Ask about something outside the scope, such as a customer's account or order. The assistant answers that it cannot see that data: on the public door, customer tables are not even in the model's view.

![The bar with a question about a customer's balance, and an answer saying the assistant has no access to it](https://mintcdn.com/concatflow/xCmphOUeinyoVnFX/images/tutorials/marketing-site/home-out-of-scope.png?fit=max\&auto=format\&n=xCmphOUeinyoVnFX\&q=85\&s=cc30dbe2bb740d546bfac00a7a3a44d1)

Outside the public scope, the assistant says it has no access.

A few more things to know about the public door:

* **Every visitor is anonymous.** Concatflow keeps no conversation after the visit. A visitor coming back starts fresh.
* **Each question is charged to your workspace.** Visitors never sign in and never pay. The **Limits** tab caps your monthly spend.
* **Visitors have limits too.** A visitor can ask up to **Rate per visitor** questions per hour, and 20 questions per visit. When a limit is reached, the assistant answers with a short message instead. That reply costs nothing.

## 8. Allow Concatflow in your CSP

If your site sends a `Content-Security-Policy`, allow the Concatflow origin for scripts and frames. In a static site, a `<meta>` tag at the top of `<head>` works too:

```html theme={"system"}
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self' https://app.concatflow.com; frame-src https://app.concatflow.com; style-src 'self' 'unsafe-inline'"
/>
```

* `script-src` loads `widget.js`. `frame-src` loads the assistant, which runs in an iframe.
* `style-src` needs `'unsafe-inline'`: the bar's styles are inline, and so are this page's.
* Your page never calls the Concatflow API, so `connect-src` needs nothing.

Add the tag to both pages and reload. The bar and the bubble work as before. See [Content Security Policy](https://docs.concatflow.com/guides/csp.md) for the details.

## 9. Go live

1. Deploy the folder to your host.
2. In **Doors → Allowed origins**, add every origin your pages are served from. `https://example.com` and `https://www.example.com` are two origins: add both if both serve the site.
3. Remove `http://localhost:8000`.
4. Check the caps in **Limits**.

Then run the [Go-live checklist](https://docs.concatflow.com/guides/go-live.md).

## What you built

| File | Has |
| - | - |
| `index.html` | The search bar in the hero, with your placeholder and accent. |
| `pricing.html` | The chat bubble in the corner. |

Each page holds your public site token and loads `widget.js`. Nothing else: no key, no server, no build.

## Next steps

> **[Per-customer assistant in Next.js](https://docs.concatflow.com/tutorials/nextjs-per-customer.md)**
>
> Answer each logged-in customer about their own data.

> **[Bar or bubble](https://docs.concatflow.com/guides/bar-or-bubble.md)**
>
> The ⌘K bar, and what each launcher does.

> **[Appearance](https://docs.concatflow.com/guides/appearance.md)**
>
> Theme, accent colour and placeholder.

> **[\<concatflow-assistant>](https://docs.concatflow.com/reference/embed/element.md)**
>
> Every attribute of the element.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.