A support widget that adds nothing to your bundle
It is a script tag. Nothing enters your dependency graph, nothing wraps your component tree, and removing it is deleting two lines.

“Every support tool ends up owning part of the frontend.”
And the honest answer
Usually true, and the reason is the SDK. This is a script tag: nothing enters your dependency graph, nothing wraps your component tree, and there is no provider to thread through. Removing it is deleting two lines and shipping.
The case, in the order it lands
- 01
No package, no provider, no upgrade path
Nothing in package.json means nothing to bump, no peer-dependency conflict, and no version treadmill when the vendor ships a major.
- 02
It loads async and stays out of the way
Never blocking parsing, outside the React tree, with no mount point and nothing to clean up on unmount.
- 03
The public key is meant to be public
Domain locks, per-visitor rate limits and a hard daily cap are what make that safe. You set the ceiling; you do not discover it.
It is a script tag — no npm package, no provider, nothing in the bundle. The public key is domain-locked with per-visitor rate limits and a hard daily cap, and uninstalling is deleting two lines.
Support tools are usually somebody else's architecture in your app
The typical widget ships an SDK, wants a provider at the root, pulls transitive dependencies into your lockfile, and puts you on its release cycle. For something that renders in its own layer and shares no state with your application, that is a lot of coupling to accept.
- Widget SDKs adding measurable weight to the bundle
- Version bumps required for reasons unrelated to your app
- Third-party scripts hurting hydration and Core Web Vitals
- No way to bound what a runaway client costs you
Deliberately decoupled
The widget is an async external script. It does not import into your build, does not participate in hydration, and does not care which framework or router you use. Your bundle size after installing it is exactly what it was before.
- No npm package
- Nothing in your lockfile, nothing to keep on a version treadmill.
- Async, not bundled
- It loads in parallel and never blocks parsing. Defer it further with next/script if you measure closely.
- Framework-agnostic
- React, Vue, Svelte, Angular, or plain HTML — it is the same two lines.
- Removable in one edit
- Delete the snippet. There is no cleanup, no orphaned config, no leftover integration.
Limits you set, not limits you discover
Usage-based tooling is a liability without a ceiling. Domain locks restrict which origins may serve the widget, per-visitor rate limits bound a single client, and a hard daily reply cap bounds the day. All three are set in advance.
- Domain locking
- A leaked key cannot be used to run up your usage from another origin.
- Hard daily caps
- The ceiling is a number you chose, not one you find on an invoice.
An API when you need one
On Agency there is a query and ingest API if you want to drive it programmatically — feed sources from a build step, or query the knowledge base from your own surface rather than through the widget.
It is a script tag, with everything that implies
It runs in the page, so it is subject to your CSP and to whatever else shares the document. If you run a strict policy you will need to allow the widget host. That is the whole integration surface, and it is worth knowing before you start rather than at review.
- Loads asynchronously; it is not in the critical path
- The key is public by design and safe because of the domain lock
- Strict CSP needs the widget host allow-listed
- There is no server-side SDK to run and no webhook you must receive
On Next.js use next/script with afterInteractive rather than a bare tag, or it re-initialises on client-side navigation.

What you will check before installing
Short answers. If yours is not here, the assistant on this page will try it — and tell you honestly if it cannot.
Is there really no npm package?
No, and that is a design decision rather than a gap. The widget renders in its own layer and shares no state with your app, so a package would add coupling and bundle weight without adding capability.
What does it do to Core Web Vitals?
It loads asynchronously, so it never blocks parsing or rendering. The plain snippet is an async script, which can still fetch during the critical window — in Next.js, load it via next/script with the afterInteractive strategy and it stays out of your Largest Contentful Paint entirely.
How do I stop a leaked key costing me money?
Domain locks mean the key only works on origins you listed, and per-visitor rate limits plus a hard daily reply cap bound the damage regardless. The key is a public identifier, so it is designed to be bounded rather than secret.
Keep reading
All solutionsFrom the blog
All posts- EvaluatingChatbase alternatives for teams that need cited answers (2026)Matter Chat, Chatbase, Intercom Fin, Tidio Lyro, DocsBot and Chatling compared on citations, refusal behaviour, handoff and what the entry price meters. Checked on the vendors' own pages, with the test to run on all six.Read
- EvaluatingThe demo is a bad predictor of AI support qualityA polished demo tells you the product can answer questions it was prepared for. The useful evaluation happens at the edges — outside the script, on your content.Read
- EvaluatingHow to shortlist AI support tools without a feature matrixSkip the 40-row comparison spreadsheet. A behaviour-first shortlist — refusal, paraphrase, citation, handoff — ranks vendors on what customers feel.Read
Answer honestly. Capture the rest.
Point Matter Chat at your site and see what it can — and can't — answer. It's honest about both.
No credit card. 2 minute setup.
Every answer cites the source it came from. When there isn't one, it says so — and hands the visitor to you.
Installs on the tools you already run.