USE CASE
HTML AI support chat widget
Add Deacon to a plain HTML site with one script tag above the closing body tag. It answers visitors from your pages and says when it doesn’t know.
Published
Deacon is an AI support chat for a site made of plain HTML files. It takes one script tag, with nothing to build and no server of your own. It answers what visitors type from the pages you’ve published, quickly. Where your pages have no answer, it owns up to not knowing and leaves a box for the visitor’s email. If they leave it, an email reaches you with the question, unless you happen to be in Deacon’s dashboard already, and anything you reply from there turns up in the visitor’s chat. There’s a free plan of 50 answers a month, with no card to enter and no end date.
This page is for hand-written HTML and for static site generators, and it’s also plain Markdown for a coding agent. A site built on a framework has its own page, for Next.js, Vite and React, Nuxt, Astro, SvelteKit, Laravel or Docusaurus.
Before the first paste
Create your Deacon account, and Install hands you the snippet with your own pk_ key already in its data-key. Your domain must be on Install’s list for the chat to show, and the one you gave at sign-up already is, www and subdomains included. If the same files are also published at owner.github.io, list that as well. You download nothing and install nothing.
Rather not edit the files yourself? On Install, choose My own code if it asks what the site runs on, then Copy the prompt. Claude Code, Cursor or Codex, working in your site’s folder, adds the code and checks it’s live.
One tag per page
Each page that should show the chat gets the snippet just before </body>. In a page like this one, the <script> line is all you add.
<!-- every page, or your generator's base template -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Your site</title>
</head>
<body>
<!-- your page -->
<script src="https://heydeacon.com/widget/v1/loader.js" data-key="pk_your_widget_key" async></script>
</body>
</html>
async is why the tag doesn’t hold up the page. MDN’s script reference, read on 25 October 2026, says an async script is fetched “in parallel to parsing” and run “as soon as it is available”.
With hand-written files, every page needs its own copy, and a search across the folder for loader.js shows any you missed. Hugo, Jekyll, Eleventy and other generators wrap pages in a base template, so one copy there reaches the whole site. For a Jekyll theme on GitHub Pages, this guide walks through overriding the theme’s layout.
Testing before you publish
A page opened straight from disk has no web address for Deacon to recognise, so serve the folder instead. Python’s built-in server does it, and its documentation says python3 -m http.server listens on port 8000 by default.
- In the site’s folder, run
python3 -m http.serverand openhttp://localhost:8000. On that first visit the chat stays hidden, as localhost isn’t listed. - Install, in Deacon’s dashboard, now shows “Found the code on localhost:8000”. One click lists it.
- Reload. The button, called Help unless you renamed it in Appearance, shows in the corner. Ask something your pages answer, which costs nothing on localhost.
- With the chat open, follow a link. The next page loads in full, and the chat opens again on it with the conversation still there.
Then upload the files. Install shows Deacon as live on your domain, with the time it was last seen. An agent can check the same thing without a browser. In the answer, latest is the address that last loaded Deacon and refused a development address it kept off, and Deacon’s install guide covers the rest.
curl -s "https://heydeacon.com/api/widget/seen?k=pk_your_widget_key"
A button of your own
To open Deacon from your own link or button, such as Help in your menu, hide its button in Appearance and call Deacon.open().
<!-- anywhere on a page that has the tag -->
<button onclick="Deacon.open()">Ask a question</button>
Deacon.close() and Deacon.toggle() exist too, from the moment the script has run.
Pages behind a login
If a server builds your pages and knows who’s logged in, print their details above the tag, filled in from the session and escaped for a script. Their name then appears on the conversation, and they get a one-tap reply instead of typing an address. Deacon treats it as a label it doesn’t verify, and the AI never sees it.
<!-- above the tag, only for someone logged in, filled in with their details -->
<script>
window.deaconUser = {
id: 'u_123',
email: 'ana@studio.com',
name: 'Ana Ruiz',
};
</script>
On a page where nobody is logged in, such as the one log-out lands on, print <script>window.deaconUser = null;</script> instead, so the next person on that computer starts fresh. Deacon’s install guide has this block written for Next.js and Rails, and the Laravel page has it for Laravel.
What you’ll learn from your visitors
On a static site, a visitor with a question usually has nowhere to ask it. With Deacon they ask, and you read what they asked. Questions Deacon couldn’t answer wait in the dashboard for you to answer once with Answer this, and Topics counts the people behind each subject, so you can see which page to write next.
HTML questions
One page shows the chat and another doesn’t. Why?
The second page most likely lacks the tag, so search the folder for loader.js. If it has the tag, its console will have a line from [Deacon]. “isn’t in your allowed domains” means that page lives on an address you haven’t listed, “Unknown widget key” that its data-key differs from Install’s, and “could not start” is followed by the error that stopped it. A page where the button shows but the chat opens empty, with a line saying the chat frame “did not load”, is under a Content Security Policy without https://heydeacon.com in frame-src.
Can the tag go in the head instead?
Yes. Deacon’s script runs from <head> as well, and loads in the background either way. Install’s steps put it above </body>, so this page does too.
Do I need a server or an API key?
No. Deacon runs on its own servers, and the key in the tag is public on purpose. Every visitor’s browser reads it, and the widget only appears on the domains you list.
Try it on your own documentation
Add your help pages, ask it the question you know your docs cannot answer, and watch it say so.
The free plan covers 50 answers a month on one seat, and the paid plans are on the pricing page.
Free plan, no card.
READ NEXT
How to add a chatbot to your website in 4 steps
How to add a chatbot to your website in four steps, where its script tag goes on each builder and framework, and how to tell it who’s logged in.
Adding an AI chatbot to a GitHub Pages site
Why a static GitHub Pages site needs a hosted chatbot, where its script tag goes on a Jekyll, plain HTML or Actions-built site, and what the options cost.
Free AI chatbots for a website, and their limits
The free AI chatbot plans for a website, what each one gives you, what your visitors see when it runs out, and the catches in the small print.