Widget integration
Drop a Hatched widget into any page with a script tag and a data attribute.
Widgets are the presentation layer: small, self-contained UI pieces that render the buddy state directly in your product. They live in a Shadow DOM so your CSS can't leak in and theirs can't leak out.
The short version
<script src="https://cdn.hatched.com/widget/v1/loader.min.js" defer></script>
<div
data-hatched-widget="buddy"
data-hatched-token="WIDGET_SESSION_TOKEN"
></div>The loader finds every element with data-hatched-widget, downloads the
right widget bundle on demand, and mounts it.
Getting a token
Secret key (server-side only)Widgets authenticate with widget session tokens, not your secret API key. Mint one on your server:
import { HatchedClient } from '@hatched/sdk-js';
const hatched = new HatchedClient({
apiKey: process.env.HATCHED_API_KEY!,
});
const session = await hatched.widgetSessions.create({
buddyId: 'bdy_abc',
userId: 'user_42',
scopes: ['buddy:read', 'buddy:interact', 'marketplace:read'],
ttlSeconds: 60 * 15,
});
// pass session.token to the browserIt's bound to a specific buddy + user + scope set and expires after
ttlSeconds.
Read-only embeds
If you only need to display a buddy without interactions, mint a read-only embed token — it's cheaper and carries a narrower scope:
const embed = await hatched.embedTokens.create({
buddyId: 'bdy_abc',
userId: 'user_42',
ttlSeconds: 60 * 60,
});Available widgets
- buddy — the animated companion
- badges — the earned badges shelf
- streak — the current streak counter
- leaderboard — rank list
- marketplace — item browser
- celebrate — one-shot celebration overlay
- login — sign-in surface (when using Hatched auth)
Each widget has its own data-attribute reference — see Widget reference.
Theming
Widgets read a small set of theme attributes:
<div
data-hatched-widget="buddy"
data-hatched-token="..."
data-hatched-theme="light" <!-- or "dark" or "auto" -->
data-hatched-size="md" <!-- sm | md | lg -->
data-hatched-lang="en"
></div>Colour tokens follow the customer's brand kit configured in the dashboard.
If you need per-page overrides, set data-hatched-accent="#FF6B4A" and
we'll bridge it into the Shadow DOM.
Interactions
Interactive widgets (buddy, marketplace) need the appropriate session scopes. The minimum for a user buying a marketplace item:
scopes: ['buddy:read', 'buddy:interact', 'marketplace:read', 'marketplace:purchase']A scope check that fails returns a user-visible error without corrupting state. See the widget reference for the full scope list.
Common pitfalls
apiKeyin browser bundle — never pass your secret key to the browser. The SDK throws on browser construction; mint a session token server-side instead. See Auth model.- Token already expired — if the user lingers on the page longer than
ttlSeconds, re-mint on focus or via SSR on each navigation. - Wrong buddy id — session tokens are scoped to a single
buddyId; if you switch buddies, mint a new session.