Skip to main content
Drop a single <script> tag into your site to show live status from your Kōdo status page. The widget respects your page’s brand color, auto-refreshes, and surfaces active incidents inline.

Quick start

<script src="https://kodostatus.com/widget.js"
        data-page="your-page-slug"
        data-style="badge"
        defer></script>
Replace your-page-slug with the slug of a public status page. The script inserts the widget directly after itself (except floating, which attaches to <body>).

Styles

badge — pill indicator

A compact pill with a pulsing dot and status label. Inherits the page’s primary_color when operational; falls back to semantic colors (amber / orange / red) during incidents.
<script src="https://kodostatus.com/widget.js"
        data-page="your-page-slug"
        data-style="badge" defer></script>
Horizontal banner meant for the top of a page or layout.
<script src="https://kodostatus.com/widget.js"
        data-page="your-page-slug"
        data-style="banner" defer></script>

floating — fixed corner pill

Pinned to a corner of the viewport. Use data-position to choose: bottom-right (default), bottom-left, top-right, top-left.
<script src="https://kodostatus.com/widget.js"
        data-page="your-page-slug"
        data-style="floating"
        data-position="bottom-right" defer></script>

incident — live incident banner

Shows only when there is an active incident. Displays severity, phase, time since last update, and the incident title. Great for app-top alert bars that disappear when things are healthy.
<script src="https://kodostatus.com/widget.js"
        data-page="your-page-slug"
        data-style="incident"
        data-hide-when-operational="true" defer></script>
When data-hide-when-operational="true" (recommended), the widget renders nothing while all systems are operational. If the attribute is omitted or false, the widget falls back to a banner style when there is no active incident.

Attributes

AttributeValuesDefaultDescription
data-pagestringrequiredPublic status page slug.
data-stylebadge / banner / floating / incidentbadgeWidget variant.
data-positionbottom-right / bottom-left / top-right / top-leftbottom-rightFloating-only placement.
data-themeauto / light / darkautoTheme preference for subtle shadow / contrast.
data-hide-when-operationaltrue / falsefalseincident style only — hide entirely when no active incidents.

Programmatic API

The widget dispatches a kodo:status-change custom event on window whenever overall status changes between polls:
window.addEventListener('kodo:status-change', (e) => {
  console.log(e.detail);
  // {
  //   slug: 'your-page-slug',
  //   status: 'major_outage',      // new status
  //   previousStatus: 'operational',
  //   activeIncidents: [ { id, title, severity, status, ... } ],
  //   snapshot: { /* full StatusSnapshot */ },
  // }
});
Use this to trigger toast notifications, Sentry breadcrumbs, or in-app banners without rendering the widget itself.

Branding

The widget automatically reads the following from your status page:
  • primary_color — used as the operational background
  • theme_mode — currently influences shadow weight; expanded theming is planned
To change these, edit your status page in the dashboard under Status Pages → your page → Appearance.

Refresh behaviour

The widget connects to a server-sent events stream and receives new snapshots as soon as the server detects a change (within ~5 seconds of the event). If the browser does not support EventSource, or the stream fails before the first snapshot arrives, the widget transparently falls back to polling every 60 seconds. Each SSE connection is capped at ~55 seconds and then gracefully rotated — the client reconnects automatically with no visible flicker.

Server-sent events endpoint

If you want to build your own live widget, subscribe to:
GET https://kodostatus.com/api/public/status/{slug}/stream
The stream emits these named events:
  • snapshot — the full StatusSnapshot JSON, sent on connect and again whenever the snapshot changes
  • reconnect — sent just before the server closes the stream so the client can reconnect for another window
  • error — sent with { "message": "not_found" } if the slug is invalid
Example:
const es = new EventSource(
  'https://kodostatus.com/api/public/status/acme/stream'
);
es.addEventListener('snapshot', (e) => {
  const snap = JSON.parse(e.data);
  console.log(snap.status, snap.activeIncidents);
});

Accessibility

The widget root is rendered with role="status" and aria-live="polite", so screen readers announce status changes without stealing focus. All user-supplied strings (incident titles, etc.) are HTML-escaped.

Public API

The widget is a thin wrapper around this endpoint — you can build your own widget against it:
curl https://kodostatus.com/api/public/status/your-page-slug
Response:
{
  "organization": { "name": "Acme", "slug": "acme" },
  "branding": {
    "primaryColor": "#22c55e",
    "logoUrl": "https://.../logo.png",
    "hideBranding": false,
    "themeMode": "system"
  },
  "status": "operational",
  "services": [
    { "id": "...", "name": "API", "status": "operational", "display_order": 0 }
  ],
  "activeIncidents": [],
  "lastUpdated": "2026-04-14T12:34:56.000Z"
}
CORS is enabled for all origins. Responses are cached at the edge for 30 seconds.

Content Security Policy

If your site uses CSP, allow the widget source and API origin:
script-src 'self' https://kodostatus.com;
connect-src 'self' https://kodostatus.com;