Witbitz docs HomeTrustAll docs

Embed a Space — one line, and the drop-in doesn't cost you the encryption

Status: live. The host-side SDK is served at https://witbitz.chat/embed.js; the iframe seam ships in the Spaces app. Live demo → witbitz.chat/demo: talk to an embedded AI and it calls the page's own set_site_color tool to restyle the site — your app's functions become the agent's tools. A simpler read-only event-log demo (the bridge events, no host tools) is at /site/embed-demo.html. Cross-origin, browser-verified.

The one-liner

<script src="https://witbitz.chat/embed.js"></script>
<witbitz-space link="https://witbitz.chat/space#<your link>"></witbitz-space>

or drive it from script:

const space = Witbitz.embed('#slot', { link })
space.on('message', m => …)   // someone posted (metadata only)
space.on('turn',    t => …)   // an agent turn finished
space.signIn(token)           // owner-gated rooms: admit the user at their tier

Witbitz.embed(target, opts) returns a controller: on(type, cb) / off, signIn(token), navigate(to), setTheme(theme), destroy(), and iframe. <witbitz-space> re-exposes it as el.space.

Why it's an iframe — and why that's the point

That one line mounts a cross-origin iframe on the Spaces origin, not inline DOM in your page. That isn't a limitation to apologize for — it's what keeps the guarantees true when a Space is embedded:

So a drop-in embed does not cost you the encryption — the part that touches your users' content still runs only in verified code, in a context your page can't see.

The bridge (host ⇄ Space)

The only channel across an origin boundary is window.postMessage. The SDK layers a small, origin-checked protocol (JSON-RPC 2.0) on it. It is a narrow capability seam, not shared memory — the host can do exactly these things:

Direction Message Meaning
Space → host ready the Space handshaked; the bridge is open
Space → host message someone posted — metadata only ({id, self, sys}), never content
Space → host turn an agent turn finished
Space → host member a member event
Space → host resize content height changed (auto-sizes the iframe)
host → Space signIn hand in an owner IdP token / signed grant
host → Space navigate / theme deep-link / theme within limits

Discipline that makes the seam safe: origin-checked both directions (the Space only accepts control from the one validated embedder; the host trusts only the Spaces origin), nothing is posted to '*', and the room key never crosses the bridge — it rides the iframe's URL fragment, client-side, and is never sent to a server. Sign-in is a verified token, not a trust-me flag: it's checked against the room's sealed allow-list and resolved to a tier (see the owner rule).

One honesty note: the app that embeds a room necessarily holds that room's link, so it holds that room's key — the isolation doesn't hide the embedded room from the embedder. What it protects is (a) the platform-wide guarantee that Witbitz can't read content, and (b) the room from your page's other scripts and trackers.

Who may embed — two gates

Embedding is off by default (frame-ancestors 'self'). Turning it on is two layers, deliberately:

So the browser stops any non-registered origin from framing at all; the owner policy narrows it to this owner's origins per room. Fail-closed.

Orthogonal to what the Space is

The embed is transport + isolation. Whether the client is trustworthy code is a separate axis — the attested client; admission and tiers are the owner rule. They compose: an embedded Space is still content-blind, still owner-governed, still verifiable.

One line: witbitz.chat/embed.js drops a real, isolated, content-blind Space into any page, talks to it over a narrow origin-checked bridge that never carries your plaintext, and lets the room's owner decide who may embed it.

Machine-readable source: embed.md · every doc in one fetch: llms-full.txt (HTML) · ← tools-widgets · async-spaces