> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alakazam.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Embedding

> Drop a world into your site with the @alakazamworld/embed SDK.

Embedding is where a world becomes *programmable* inside your product:
`@alakazamworld/embed` mounts a world in a sandboxed iframe and bridges it to your
page over an origin-validated `postMessage` channel, so you can react to its
events and wire it into your own logic. It's zero-dependency and works with any
framework.

## Install

```bash theme={null}
npm install @alakazamworld/embed
```

Or via a script tag — it auto-mounts any `[data-alakazam-slug]` element:

```html theme={null}
<div data-alakazam-slug="mystical-forest" data-alakazam-token="SESSION_TOKEN"></div>
<script src="https://cdn.alakazam.gg/embed.global.js"></script>
```

## Mount a world

```javascript theme={null}
import { createEmbed } from "@alakazamworld/embed";

const embed = createEmbed({
  container: "#game",
  slug: "mystical-forest",
  token,                       // session token from your server
  theme: { colorPrimary: "#86ffba" },
  onReady:        () => console.log("playing"),
  onChoice:       (c) => console.log("player chose", c),
  onEnding:       (e) => console.log("ending reached", e),
  onSessionEnded: () => console.log("session over"),
});

// later
embed.destroy();
```

## Events

The SDK delivers world events to your callbacks, all over an origin-validated
channel:

| Callback          | Fires when                                                    |
| ----------------- | ------------------------------------------------------------- |
| `onReady`         | the world has booted and is playing                           |
| `onChoice`        | the player makes a choice                                     |
| `onStateEntered`  | the world enters a new state                                  |
| `onEnding`        | an ending is reached                                          |
| `onSessionEnded`  | the session ends                                              |
| `onHeightChanged` | the player's natural height changes (auto-resizes the iframe) |
| `onError`         | something goes wrong                                          |

## Refresh the token

Session tokens are short-lived. Provide `onTokenExpiring` to hand the SDK a
fresh token from your backend — a re-authorization checkpoint that keeps long
sessions alive without interrupting play:

```javascript theme={null}
createEmbed({
  container: "#game",
  slug: "mystical-forest",
  token,
  onTokenExpiring: async () =>
    (await fetch("/api/alakazam-token").then((r) => r.json())).token,
});
```

## Theming

Restyle the player's chrome with a small set of tokens (no raw stylesheet
overrides), then update them live with `setTheme`:

```javascript theme={null}
const embed = createEmbed({ /* … */, theme: { colorPrimary: "#86ffba" } });
embed.setTheme({ colorPrimary: "#ff5cf0", borderRadius: "12px" });
```

## Cross-origin security

<Warning>
  Register the origins you'll embed on in your app's settings, and pass the same
  `origin` when minting the session token.
</Warning>

When you bind a session token to an `origin`, Alakazam:

* sets `Content-Security-Policy: frame-ancestors <origin>` on the embed page, so
  only your site can frame it, and
* stamps the token's `aud` to that origin, so a leaked token can't be replayed
  from another site.

The SDK validates the `postMessage` origin on both ends and never relies on
third-party cookies.
