Skip to content

Embedding a topo

Drop a TopoKit topo into your own page with a single <iframe>. Optionally pass your license key as a URL parameter to render without the Unlicensed watermark.

Basic iframe

Once you've created a topo at topokit.io/play and have a share URL like https://topokit.io/t/abc123, embed it with the ?embed flag for a chrome-less view (no nav, no edit button, no "Made with TopoKit" pill — just the canvas):

example.html

The embed view renders dark by default. The topo's stored theme / layout still apply — ?embed only strips the surrounding page chrome.

Bring your own license

By default an iframed topo renders with the "Unlicensed" watermark, because the SDK is loaded from topokit.io and there's no license attached. To suppress the watermark on your site, pass your license key via the URL:

Recommended: URL fragment

Put the license after # in the iframe URL. Fragments are never sent to the server, never appear in our access logs, and aren't captured by typical web analytics — only the browser sees them.

example.html

Also supported: query parameter

For convenience the SDK also accepts ?license=tk_.... The fragment form wins if both are present. Anything in the query string is visible to the server and to anyone with access to logs — prefer the fragment form unless you have a reason not to.

example.html

How the domain check works

A TopoKit license is bound to one or more domain patterns at mint time (e.g. customer.com, *.customer.com). When the SDK runs in an iframe on your page, it validates the license against your page's origin, not topokit.io:

  • Chromium, Edge, Safari — the SDK reads window.location.ancestorOrigins[0], which is the immediate parent's origin. Browser-supplied, can't be spoofed by the iframe.
  • Firefox — falls back to document.referrer, which carries your page's origin by default (the standard strict-origin-when-cross-origin policy).
  • If neither signal is usable (e.g. your page sets Referrer-Policy: no-referrer on Firefox), the SDK fails closed and shows the watermark. This is intentional: otherwise any site that stripped its own referrer could pretend to be an authorized embedder.

A practical consequence: a leaked license is far less dangerous than a typical API token. Even if your tk_... token ends up in someone else's browser history or referrer log, it only suppresses the watermark on the domains it was minted for — not on theirs.

Don't strip your own referrer

If your site is served to any Firefox users, don't ship a Referrer-Policy: no-referrer header or meta tag — the SDK won't be able to identify the parent origin and will fall back to the watermark. The browser default already gives us enough:

default policy (good)

don't do this

Chromium and Safari are unaffected by this — they use ancestorOrigins, which doesn't care about referrer policy.

Security model

The license is a signed Ed25519 token containing the domain patterns it's valid for. Verification is fully offline — the SDK doesn't phone home, and there's no central license server to compromise. The license key itself is treated as bearer-style on the wire, but constrained to its bound domains: an attacker who lifts your license from an analytics log and iframes a topo on attacker.com will get ancestorOrigins[0] = "attacker.com", which won't match the domain patterns in the token, and the watermark stays on.

If you still want to rotate after a suspected leak, mint a new key with your TopoKit plan and update the URL.

Alternative: self-host the SDK

Embedding via iframe is the fastest path, but you can also call the SDK directly from your own page. In that case the license check uses your page's own hostname (the standard top-frame case) — no ancestorOrigins indirection. See Getting Started for the GraphKit.create() API.

Known limits

  • Programmatic license attach is currently URL-only. Embedders pass the license at iframe-src time. A postMessage-based flow (parent attaches license after the iframe loads) isn't shipped yet.