Put a message on your website.
A banner, a notice, a sign-up box, a what’s-new panel. Design it here, paste one line into your site, and it appears.
No account needed to start. Free to keep one.
You decide when it shows up
Pick one and try it on the window below. These are real — not a video.
What that one is, underneath — the whole widget, written out. No code in it anywhere.
{
"version": 2,
"name": "Announcement bar",
"kind": "banner",
"theme": {
"fontFamily": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
"accent": {
"hex": "#ffffff",
"alpha": 1
},
"surface": {
"hex": "#1D1D1F",
"alpha": 1
},
"text": {
"hex": "#ffffff",
"alpha": 1
},
"muted": {
"hex": "#6b7280",
"alpha": 1
},
"radius": 14,
"fontSize": 13,
"gap": 8,
"scheme": "auto"
},
"surface": {
"mode": "bar",
"position": "top",
"mount": "",
"width": 360,
"offset": 0,
"backdropBlur": 0,
"backdrop": false,
"dismissible": true,
"animation": {
"preset": "fade",
"durationMs": 200
},
"css": ""
},
"trigger": {
"on": "load",
"delayMs": 0,
"scrollPercent": 50,
"selector": "",
"frequency": "always"
},
"screens": [
{
"id": "main",
"blocks": [
{
"id": "row",
"type": "group",
"direction": "row",
"align": "center",
"justify": "center",
"gap": 12,
"children": [
{
"id": "tag",
"type": "icon",
"name": "tag",
"size": 16,
"label": ""
},
{
"id": "copy",
"type": "text",
"role": "body",
"text": "Free delivery on everything this week.",
"format": "plain"
}
]
}
]
}
],
"start": "main"
}A real page running the same file your site would. Nothing it does leaves your browser.
Three steps
Design it
Change the words, the colours, where it sits.
Paste one line
Once, anywhere on your site. Never again.
Watch it work
Views, clicks, replies. Off again in a click.
<script async src="https://kestero.com/widget.js" data-key="your-key"></script>Squarespace, Shopify, WordPress, or plain HTML.
Start from one of these
Each one opens the editor with a working example in it.
Announce something
A strip across the top of every page.
Collect emails
A box that asks, and keeps the answers.
Point at something new
A card in the corner with a button.
Show what changed
A bell, and a panel of your updates behind it.
Ask a question
One question, a few answers, and the replies waiting.
Walk someone through setup
One step per screen, until they are done.
Or start with a blank one. 8 in total.
Safe to put on your site
You are putting somebody else’s code on your site. Four straight answers.
It will not slow your site down
It loads in the background. If we went down, your site would not notice.
It cannot break your design
Sealed off both ways. Your CSS cannot reach in; nothing in it reaches out.
No cookies. No tracking.
Nothing to consent to. The only thing we store is what someone types into your form.
It works for everyone
Keyboard, screen reader, reduced motion. One click checks yours and records the answer.
If you have to get this signed off — the record every widget carries, and how each claim is known.
Every widget is saved as plain data with no code in it, which means a program can read a widget and work out what it is able to do. One does. The two cards below are real records it produced, from two real widgets, while this page was rendering — the first is the widget you scrolled past, the second is the same widget with one image added from somebody else’s server.
The widget above
What this widget does not do
- No custom code
- No custom CSS
- No third-party requests
- Not checked for accessibility since it was last edited
Worked out from the saved widget itself every time this page loads, not recorded once and trusted afterwards.
The same widget, with one image from another host
What this widget does not do
- No custom code
- No custom CSS
- Loads from another host — images.example.com
- Not checked for accessibility since it was last edited
Worked out from the saved widget itself every time this page loads, not recorded once and trusted afterwards.
Neither is written down anywhere on this page — which is why the second one is allowed to be worse than the first, and why it is. Both were computed by the same function the API runs on every save and every read, lib/schemas/widget-guarantee.ts.
Look at the last line of each. Neither widget has been checked for accessibility, and both say so plainly rather than staying quiet about it. A badge that could only ever come out green would not be worth reading, and a reviewer would be right not to.
What the embedded file does
All of this is true by reading one file, which is the point of it being one file.
- PropertyNo third-party code in it — no import, no require, nothing bundled
- PropertyNothing that arrives over the network is ever assigned to innerHTML; the two assignments in the file both take icon markup defined in the file
- PropertyRenders in a shadow root under :host { all: initial }, so the host stylesheet cannot reach it and it cannot reach the host
- UnrepresentableA link can only be http, https or mailto — a javascript: URL is refused by the schema, so no stored widget contains one
- Enforced at saveCustom CSS is parsed, scoped into the widget's own subtree, and refused if it fixes itself over the host page or fetches from a host that is not ours
- Enforced at savePer-project domain allow-list, so a scraped embed key renders nowhere else
What is checked for accessibility
A check, not a promise. The product cannot guarantee what someone draws with it, so what it offers is the check and the date it ran.
- Checked per widgetaxe-core runs against the exact spec, in both colour schemes, inside the real shadow root — and the result is stamped with that spec's fingerprint, so it stops applying the moment the widget is edited
- UnrepresentableAn image without alt text and an input without a label are not storable specs
- PropertyA text block's role decides the heading level the renderer emits, so restyling a block cannot change what it announces itself to be
- TestedFocus moves into a modal and returns on close, Escape closes unless the spec says the widget cannot be dismissed, and a closed widget leaves the DOM rather than hiding in the tab order — 89 tests drive the real renderer in a browser environment
- Propertyprefers-reduced-motion is read by the renderer, and the animation the spec asked for does not run
What is stored about a visitor
One thing, and only because you asked for it.
- PropertyNo cookies, so nothing to consent to
- PropertyNo visitor table and no fingerprint. How often a widget comes back, and which changelog posts have been read, are timestamps in the visitor's own localStorage
- PropertyWhat a visitor types into a form you built is stored, and that is the whole of it. It is stored because your widget asked a question — nothing is collected that a visitor did not type
- SettingRecording the page and recording the referrer are each switchable off, independently
- DeploymentData at rest in the EU — the database is in AWS eu-west-1
Measured, not estimated
- widget.js — 16.1 KB gzipped
- Zero dependencies
- No cookies, no visitor row
- axe-checked per widget
- Data stored in the EU
Each of those has a command beside it in the repository that produces it, and a test that fails when it stops being true. The first column above is checkable without asking us anything — read the file your visitors would run.
One price, or none
Keeping one is free. Pay only for the second.
Free
Free
One widget, on one site, for as long as you like.
- One saved widget
- Every block, colour and trigger — nothing is held back
- Describe what you want and have it drafted for you
- Views, clicks and form replies, per widget
- The accessibility check, and the record it writes
Pro
$19/month
For running more than one thing at a time.
- Everything in Free
- As many widgets as you want
- Across as many sites as you want
- Email support, answered by the person who built it
Free does not expire and asks for no card. Pro is billed monthly through Stripe and cancels in one click, on Stripe’s own page. Cancelling deletes nothing and switches nothing off.
Need an invoice, a DPA or a signed security questionnaire? Talk to us.
Go and make one
The editor opens now — no account, no email, nothing to fill in. Decide afterwards whether you want to keep what you made.
Open the editor