add live chat to a site built with lovable, bolt or v0

You built the site by describing it, so add the chat the same way. This guide gives you a prompt for Lovable, Bolt or v0, shows where the snippet should end up in the code they generate, and how to check on the published site that it loads nothing before a click.
what these builders generate
The three tools look alike from the chat box, but they write different kinds of projects, and that decides where one script tag goes:
- Lovable generates a Vite + React app. There is an
index.htmlat the root of the project; that’s the page every route renders into. - Bolt generates whatever you asked for. Most projects are Vite apps with an
index.html; some are Next.js, Astro or plain HTML (the plain HTML guide covers that last one). - v0 generates Next.js with the app router. The shared page is
app/layout.tsx.
The chat needs one tag on every page. In a single-page app that means index.html. In Next.js it means the root layout. Nowhere else.
before you start: the domain
Spookat ties a site to its domain. The chat connects only from that domain and its subdomains, which is one of the reasons nobody can copy your snippet onto their own site.
For builders this matters, because your project lives on several addresses:
- the preview inside the builder, on the builder’s own domain
- the published address the builder gives you, usually a subdomain of theirs
- your custom domain, if you connected one
Register the site under the address visitors will use. If that’s a custom domain, use it; its www and other subdomains are included. If you publish on the builder’s subdomain, register that full subdomain, not the builder’s main domain. In the builder’s preview, the launcher shows, but the chat won’t connect. Test on the published site.
the prompt
You need your site key first. In the Spookat dashboard, add the site with the right domain; the install page shows the snippet. Then paste this into the builder’s chat, with your key in place of YOUR_SITE_KEY:
Add this live chat script to every page of the site. It must be exactly one tag, loaded once, right before the closing </body> tag of the shared HTML (index.html in a Vite app, the root layout in Next.js). Keep the async attribute. Do not wrap it in a React component, do not add it to individual pages, do not preload anything.
<script src="https://cdn.spookat.com/s/YOUR_SITE_KEY.js" async></script>
The prompt is that specific on purpose. Builders like to be helpful, and “add a chat widget” can turn into a new React component, a floating button of their own, or the tag pasted into five pages. One tag in one place is all Spookat needs: the launcher draws its own button.
the look, in the same prompt
The widget’s look is set in the Spookat dashboard and travels inside the launcher, so the builder doesn’t need to know about it. If you’d rather keep it in the code, add a second line to the prompt:
Above that script, add: <script>window.Spookat = { style: "clean", accent: "#2F6FEB", side: "right" };</script>
There are 8 styles. accent is your brand color as hex; the text on it is picked for contrast. The docs list every key.
where it should end up
Open the code view and check. For a Vite app (Lovable, most Bolt projects), index.html should end like this:
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script src="https://cdn.spookat.com/s/YOUR_SITE_KEY.js" async></script>
</body>
</html>
For Next.js (v0, some Bolt projects), app/layout.tsx gets the tag inside <body>, after {children}:
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<script src="https://cdn.spookat.com/s/YOUR_SITE_KEY.js" async></script>
</body>
</html>
);
}
If the builder used next/script instead, that’s fine too, with strategy="afterInteractive" or "lazyOnload". What you don’t want to see:
- the tag inside a page component, like
Home.tsxorapp/page.tsx: the chat would only exist on that page - a
useEffectthat creates the script element: it works, but it’s more code for the same tag - a chat button or panel the builder drew itself: delete it, Spookat brings its own
If it went wrong, say so in one sentence: “Remove the chat code you added and put only the script tag in index.html.” Builders fix this kind of thing well when the instruction is concrete.
publish, then check
Publish the site and open the published address in a private window. Open DevTools:
- Network, tick “Disable cache”, reload, and type
spookatinto the filter. You should see one request: the launcher fromcdn.spookat.com, around 2 kb. Two, both fromcdn.spookat.com, if your code sets a style inwindow.Spookatthat isn’t the one you published. Nothing toapi.spookat.com. - Application, cookies and local storage: nothing from Spookat.
- Click the launcher. The panel loads from the CDN. Write a test message. With Slack or Discord connected, it shows up there; reply and watch it arrive in the widget.
If the launcher doesn’t appear at all, the tag didn’t make it into the published build. Check the code view again. If the launcher appears but the chat can’t connect, the domain in the dashboard doesn’t match the address you’re on.
The pillar guide explains each of these checks in more detail.
connect the replies
The chat should reach you where you already are. Connect Slack or Discord in the dashboard, pick a channel, and every visitor gets their own thread. The Slack guide and the Discord guide cover the details.
why not let the builder make a chat
You could ask for one. The builder will make a nice panel with a text box in minutes. Then the questions start: where do the messages go, who gets notified, how does the reply reach a visitor who closed the tab, what happens with spam, who keeps it running. That’s a server, a database, a Slack integration and an email pipeline, and none of it is the product you were building.
Spookat is one tag, costs $4.99 a month per site on starter, and the trial is 14 days with no card.
if you use claude code or cursor instead
Export the project to a repo and let a coding agent do it with the Spookat MCP server. It can also match the widget to your site’s colors and set it up without you copying keys. The Claude Code guide walks through that.
match the look to a generated site
Builders tend to produce a recognisable style: a clean sans-serif, soft shadows, rounded cards, one accent color. The widget should look like it belongs there, not like a sticker from another site.
- Style. For the typical generated look, start with
cleanorsoft. If your site is darker and more technical, tryterminal. If you gave it a bold, flat look,brutalorswiss. You can switch in the dashboard and see each one in a live preview before you publish. - Accent. Use the same hex as your buttons. The builder usually has it in its Tailwind config or a CSS variable; ask it “what is the primary color’s hex?”
- Font.
systemdownloads nothing and matches most generated sites closely enough. If your site uses a specific font and we host it, pick it; it loads only after the click. - Side. If the builder placed a floating button of its own (a back-to-top arrow, a cookie settings icon) in the bottom right, put the launcher on the left.
what your visitors see
A small button in the corner, in your colors. Nothing else happens until they click it. Then the panel opens with your greeting, and a line that a human answers. They type, and the message lands in your Slack or Discord thread, or in our inbox and its phone app. If they leave before you reply, they can leave an email; on pro the reply follows them there. The widget speaks their browser’s language, one of 12, unless you set one.
after the builder regenerates
Builders rewrite files. A big change to the layout (“make it a dashboard”, “switch to dark mode”) can quietly drop the tag from index.html or the root layout. After a large regeneration, open the published site and check that the launcher is still there. If it’s gone, the same prompt puts it back.
more than one project
Builders make it cheap to start a second and a third site. In Spookat each one is its own site, with its own key, domain, look and channel, so a chat never lands in the wrong project’s thread. The first site in an account pays the full price; every other site in the same account that you pay for through Spookat is 30% off, on every plan. Several sites can share one Slack or Discord channel if the same people answer them all, but the card shows only the page path, not which site a chat came from. Give each site its own channel if you need to tell them apart.
checklist
- The site is registered under the address visitors use.
- One tag,
async, inindex.htmlor the root layout. - No chat button or component the builder made itself.
- Tested on the published site, not the preview.
- One request before a click (two, both from
cdn.spookat.com, if your code sets a style you didn’t publish), no cookies. - Slack or Discord connected.
Describe it, publish it, check it. Then answer the first question from a thread.