Put AI chat in your product.
One script tag.
PLAI.chat drops into any website or web app as a chat bubble, a docked side panel, or an inline panel. Your visitors get free AI models with no signup. You get no build step, no npm package, and no cookies added to your page.
Opens a short form right here — no account, no sales call. Prefer email? Use the support form instead.
The chat bubble in the corner of this page is the widget itself. Go on, ask it something.
Try Free · Get a key · Want unlimited chat (fair use)? plai Plus €4.99/mo →
<script src="https://plai.chat/embed.js"
data-key="YOUR_KEY"
data-mode="bubble" defer></script>
Shadow-root launcher, cross-origin iframe, no cookies on your domain.
Build your snippet — and run it right here
Pick the options, hit Run on this page, and the widget re-mounts live in the mode you chose. The snippet below is exactly what you paste into your own HTML.
The demo key above is locked to plai.chat — copying it to another domain will not work, which is exactly the protection your own key gets.
What your visitors get
A full AI chat, not a scripted FAQ bot. The same engine that runs plai.chat, on the free model chain for now: streaming answers, markdown, code blocks, Mermaid diagrams and live HTML previews.
No signup for visitors
Anonymous chat on the free model chain, gated by a Cloudflare Turnstile bot check. No account, no email, no password — nothing between the visitor and their first question.
No cookies on your page
The widget sets nothing on your domain. The visitor session is a bearer token inside the iframe's own partitioned storage, and conversations stay in the visitor's browser.
Cannot break your CSS
The launcher lives in a closed shadow root and the chat is a cross-origin iframe. Total isolation both ways — your styles stay yours, ours stay ours.
Mobile handled
Under 640px the panel goes fullscreen and the layout switches to the mobile design automatically. Nothing for you to configure.
A small JS API
plai.open(), close(), toggle(), destroy() and an on() event hook — so your own button can open the chat.
Nothing to build
One script tag. No npm package, no bundler, no framework requirement, no server component on your side. It works on WordPress, Webflow, Next.js and hand-written HTML alike.
Three layouts, one snippet
Change data-mode and nothing else. Everything above the fold in the builder writes it for you.
| Mode | What it does | Use it for |
|---|---|---|
bubble | A round launcher in the bottom-right corner. Clicking it opens a panel that overlays the page; your content never moves. | Marketing sites, documentation, support pages. The default. |
dock | A column pinned to the right edge that pushes your page content aside, with a drag handle to resize. The width is remembered per site. | A permanent assistant inside a SaaS app, next to the user's work. |
inline | Mounts into an element you supply via data-target. No launcher, no overlay, no push — it is simply part of your layout. | A help centre page, a landing page section, an in-app tab. |
You stay in control
An embed key is public by design — it ships in your page source, so anyone can read it. That is why it is not treated as a secret: it is bound to an origin allowlist instead.
- Origin allowlist, enforced twice. The browser gets a
Content-Security-Policy: frame-ancestorsheader naming your domains, and the server independently refuses to serve the widget, mint a session, or answer a message when it can see the framing site is not on the list. Copying your key to another domain gets a 403, not a working widget. - Bot protection is on by default. Every visitor session passes a Cloudflare Turnstile challenge before a single message reaches a model.
- Free chain by default. Widget traffic runs on free-tier models, so a scraper finding your key cannot run up a bill.
- Instant kill switch. Ask us to pause a key and it stops resolving within a minute — existing sessions included, not just new ones.
The widget also cannot read your page. It is a cross-origin iframe: no access to your DOM, your localStorage, or your users' session with your app. Everything that crosses that boundary is an explicit message we document.
Privacy and GDPR, in plain terms
When you embed the widget, you are the controller of your visitors' data and we are your processor. We publish a standard Article 28 Data Processing Agreement covering exactly that, including the sub-processor list and a 30-day notice on any change to it. A countersigned copy is available on request.
- Conversations are not stored on our servers — they live in the visitor's browser.
- We process the message content, the page URL and title, the embedding origin, the visitor's IP for abuse prevention, and a short-lived random session id. That is the whole list, and it is written down in the privacy policy.
- Every embedded widget carries a visible Powered by plai.chat label, so your visitors always know who is answering.
What ships today — and what is next
We would rather tell you the boundary than have you discover it after launch.
| Capability | Status |
|---|---|
| Bubble, dock and inline layouts | live |
| Anonymous visitor chat, free model chain | live |
| Per-key origin allowlist, server-enforced | live |
| Markdown, code, Mermaid diagrams, HTML preview | live |
open() / close() / toggle() / events | live |
| Sign-in inside the widget, and moving a chat into the full app | in development |
| Custom system prompt, your colours, your greeting | in development |
| Page awareness — the assistant knows which page it is on | in development |
| Owner-paid usage with a hard monthly budget and auto-pause | in development |
| Tools your page registers, executed in the visitor's own session | planned |
| Restricting the widget to your own logged-in users with a signed identity you issue | planned |
Keys are issued by hand right now, which means you get a short conversation with us instead of a signup form — and we set the allowlist, layout and defaults up for you. Two ways to start it: (a small form, opens in place) or the support form. Either way, tell us the domain you want the widget on.
Questions developers actually ask
How do I add an AI chat widget to my website?
Paste one script tag into your HTML: <script src="https://plai.chat/embed.js" data-key="YOUR_KEY" data-mode="bubble" defer></script>. The loader renders a launcher in a shadow root and loads the chat itself in a cross-origin iframe served from plai.chat. There is no build step, no npm package and no framework requirement — it works on any site that can include a script tag.
Do my visitors have to sign up to use the chat?
No. Visitors chat anonymously on the free model chain, gated by a Cloudflare Turnstile bot check and a per-IP rate limit. There is no account, no email and no password.
Does the widget set cookies on my website?
No. The widget sets no cookies on the host page at all. A cross-site iframe never receives SameSite=Lax cookies anyway, so the visitor session is a bearer token held inside the iframe's own partitioned storage. Conversations are stored in the visitor's browser, not on PLAI.chat servers.
Can someone copy my embed key and use it on their own site?
The key is public by design — it ships in your page source — so it is bound to an origin allowlist instead of kept secret. Every key names the exact origins allowed to frame it. The browser enforces this through a Content-Security-Policy frame-ancestors header, and the server independently refuses to serve the widget document, mint a session, or answer a message for a framing origin that is not on the list.
How much does the AI chat widget cost?
Widget traffic runs on the free model chain, so it costs the website owner nothing today. The widget is anonymous-only for now: sign-in inside the widget, which would let visitors use premium models from their own PLAI.chat account (pay per use), is in development, and so are owner-paid embeds with a hard monthly budget cap and auto-pause.
Will the widget break my page layout or CSS?
No. The launcher lives in a closed shadow root, so your CSS cannot reach it and its styles cannot leak into your page. The chat itself is a cross-origin iframe, which is a total style and script boundary in both directions: the host page cannot read the conversation, and the widget cannot read the host page's DOM.
Which layout should I choose — bubble, dock or inline?
Bubble is the familiar corner launcher that overlays the page; use it on marketing sites and documentation. Dock pins a column to the right edge and pushes your content aside, which suits a permanent assistant inside a SaaS app. Inline mounts the chat into an element you supply, for a help centre or a landing page section.
Will it slow my page down?
The loader is about 8 KB gzipped with no dependencies, served with a defer attribute so it never
blocks rendering. The chat iframe itself is created only when the widget is opened — in bubble mode a visitor
who never clicks pays for one small script and nothing else.
What if my page has a strict Content-Security-Policy?
You will need https://plai.chat in your script-src and frame-src.
The launcher also adds a small stylesheet inside its shadow root, so a strict style-src must
allow inline styles ('unsafe-inline'); without that the launcher renders unstyled. No inline
scripts and no unsafe-eval are needed.
Can I open the chat from my own button?
Yes: window.plai.open() once the loader has run, for example from a click handler. To queue
calls before it loads, declare window.plai = window.plai || []; and push method names such as
plai.push('open'); the loader runs that queue when it boots.
Which models does it use?
The free chain, which rotates as better free-tier models appear — see the model list. The widget is anonymous-only for now; signing in inside the widget to use premium models from your own account is in development.
Is there a rate limit?
Yes, and it is currently per IP address, which can be tight behind a corporate NAT where an entire office shares one address. Per-key and per-visitor limits are in development. Tell us before launch if you expect that traffic shape, so we can plan it with you.
Can I use it inside a customer-facing SaaS app?
That is the case it was designed for — dock mode exists for it. Restricting the widget to your own logged-in users, using a signed identity you issue, is on the roadmap above.
How do I get a key?
Two routes, both go to the same inbox: , or use the support form. Tell us the domain (or domains) you want it on — we create the key, set the allowlist, and send you back the finished snippet.