HatchedDocs
Guides

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 browser

It'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

  • apiKey in 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.