Widget script tag
The Cortex widget is a single auto-initializing <script> tag. It mounts a floating launcher into a fresh <div> it appends to <body>, with all UI inside an open shadow root so host-page CSS can’t bleed in.
Canonical snippet
<script
src="https://cdn.cortexlayer.dev/widget.v1.js"
integrity="sha384-ldmdUZIvmluHqHci9bid79TfpkEZHPf9ge/I1tXZsz7V9FlWQ8G37ULLBvIjLZLi"
crossorigin="anonymous"
data-cortex-widget
data-api-base="https://api.cortexlayer.dev"
data-agent-id="00000000-0000-0000-0000-000000000000"
data-session-token="cs_REPLACE_ME"
></script>
integrity is generated at docs build time from the live bundle on the CDN — copy this verbatim into your page.
Required attributes
| Attribute | Description |
|---|---|
src | The CDN URL. Pinned per major version (widget.v1.js); we serve it Cache-Control: immutable for one year. |
integrity | The bundle’s sha384 hash. The browser refuses to execute a non-matching bundle (defense against CDN compromise). |
crossorigin | Must be "anonymous" for integrity to take effect. |
data-cortex-widget | Marker attribute the widget’s auto-init scans for. No value needed. |
data-api-base | Cortex API origin. https://api.cortexlayer.dev in production. |
data-agent-id | The agent’s id (UUID) returned by POST /v1/agents. |
data-session-token | A short-lived session token from POST /v1/widget/session. Mint it server-side and inject into the page. |
Optional attributes
| Attribute | Default | Description |
|---|---|---|
data-accent | brand blue | Any CSS color. Drives the launcher background, send button, and user-bubble accents. |
data-position | bottom-right | One of bottom-right, bottom-left, top-right, top-left. |
data-greeting | (empty) | Shown when the panel first opens with an empty conversation. No greeting renders if unset. |
data-placeholder | (localized) | Composer input placeholder text. Defaults to the active locale’s catalog (Write a message… in English). |
data-launcher-icon | chat | One of chat, bubble, message, headset, sparkle. Picks the SVG inside the launcher button. |
data-launcher-style | filled | One of filled (today), outline (transparent fill + accent border), soft (accent-tinted fill, no border). |
data-offset-x | 16px | CSS length (px / rem / em / vh / vw / %) — distance from the anchored corner on the X axis. |
data-offset-y | 16px | CSS length (px / rem / em / vh / vw / %) — distance from the anchored corner on the Y axis. |
data-locale | en | BCP-47-like tag. Shipping locales: en, pt-BR, es, fr, de. See Localization. |
Examples
Dark accent, bottom-left launcher:
<script
src="https://cdn.cortexlayer.dev/widget.v1.js"
integrity="sha384-ldmdUZIvmluHqHci9bid79TfpkEZHPf9ge/I1tXZsz7V9FlWQ8G37ULLBvIjLZLi"
crossorigin="anonymous"
data-cortex-widget
data-api-base="https://api.cortexlayer.dev"
data-agent-id="00000000-0000-0000-0000-000000000000"
data-session-token="cs_REPLACE_ME"
data-accent="#1a1a1a"
data-position="bottom-left"
></script>
Brand accent with a custom greeting and placeholder. The canonical snippet only renders data-accent and data-position — append the other data-* overrides by hand on your own <script> tag (escape quotes per HTML rules):
<script src="https://cdn.cortexlayer.dev/widget.v1.js" integrity="sha384-..." crossorigin="anonymous" data-cortex-widget data-api-base="https://api.cortexlayer.dev" data-agent-id="<your-agent-uuid>" data-session-token="cs_..." data-accent="#7c3aed" data-greeting="Welcome to ACME — how can we help?" data-placeholder="Type your question…"></script>Outlined launcher matching a host page’s existing chat dock — transparent fill, accent border, accent-stroked icon. Pair data-launcher-style="outline" with the slimmer data-launcher-icon="bubble" for a flat-design look:
<script src="https://cdn.cortexlayer.dev/widget.v1.js" integrity="sha384-..." crossorigin="anonymous" data-cortex-widget data-api-base="https://api.cortexlayer.dev" data-agent-id="<your-agent-uuid>" data-session-token="cs_..." data-accent="#1a5555" data-position="top-right" data-launcher-icon="bubble" data-launcher-style="outline" data-offset-x="32px" data-offset-y="24px" data-locale="pt-BR"></script>Localization
The widget ships bundled message catalogs for five locales. Set data-locale to localize every user-facing string the widget renders — launcher / panel aria-labels, the send button, the input placeholder fallback, error bubbles, and the typing indicator. AI responses themselves are multilingual via the model regardless of data-locale.
| Locale tag | Language |
|---|---|
en | English (default) |
pt-BR | Portuguese (Brazil) |
es | Spanish |
fr | French |
de | German |
Fallback chain. Resolution is case-insensitive and walks the chain: exact tag → region alias (pt-PT → pt-BR) → base language strip (es-MX → es) → English. Unknown tags silently render in English; there’s no boot-time error to surface to your users.
Adding a locale. Open an issue (or a PR) with the catalog filled in — see packages/widget/src/i18n.ts for the keys. Adding one locale is a single-file change.
<script src="https://cdn.cortexlayer.dev/widget.v1.js" integrity="sha384-..." crossorigin="anonymous" data-cortex-widget data-api-base="https://api.cortexlayer.dev" data-agent-id="<your-agent-uuid>" data-session-token="cs_..." data-locale="pt-BR"></script>CSP requirements
The widget runs under any reasonably strict CSP. Your script-src needs to allow the CDN origin and the bundle’s hash:
script-src 'self' https://cdn.cortexlayer.dev 'sha384-...';connect-src https://api.cortexlayer.dev;img-src data: https:;'sha384-...' is the same hash from the integrity attribute. With 'strict-dynamic' set, the hash alone is enough — https://cdn.cortexlayer.dev becomes optional.
Programmatic init
If auto-init doesn’t fit (SPAs that mount on route change, conditional rendering), import the widget instead:
import { initCortexWidget } from '@cortex/widget';
const handle = initCortexWidget({ apiBase: 'https://api.cortexlayer.dev', agentId: '<agent-uuid>', sessionToken: 'cs_...', accent: '#7c3aed',});
// Rotate the session token before it expires — preserves the active// conversation in memory (App stays mounted, only the auth header swaps).handle.setSessionToken('cs_newtoken...');
// On logout / route teardown.handle.destroy();initCortexWidget returns a MountHandle:
| Method | Description |
|---|---|
setSessionToken(token: string) | Hot-swap the session token used by subsequent chat() calls. The App stays mounted, so the open conversation, message history, and conversationId in memory are preserved. Format-validated; an invalid token logs a warning and the previous token stays in effect. |
destroy() | Tear down: unmounts the Preact tree, removes the floating host from <body>. Use on logout or full SPA route changes — calling on token refresh would lose the in-flight conversation. |
Calling initCortexWidget again replaces the previous floating mount: the prior host is removed before the new one mounts. For session token rotation (the common case), prefer setSessionToken — it preserves the conversation in memory while swapping auth.