Quickstart
Embed via a `<script>` tag
One CDN script, one div, one `mountPod` call. Works in any page you control.
The smallest viable embed
<div id="pod"></div>
<script src="https://cdn.jsdelivr.net/npm/@gemmapod/embed@0.1.0/dist/gemmapod-shim.iife.js"></script>
<script>
GemmaPod.mountPod(document.getElementById("pod"), {
name: "Hello",
persona: "Friendly demo agent.",
systemPrompt: "Be terse.",
model: "gemma4:e4b",
transport: {
dartc: {
signalUrl: "wss://signal.gemmapod.com/signal",
podId: "your-pod-id",
},
fallback: { model: "onnx-community/gemma-4-E2B-it-ONNX" },
},
});
</script>That's the whole demo. Open the page; chat with the agent. If the configured Host is online you get DARTC over WebRTC; if not, the visitor sees a fallback panel and can opt into in-browser WebGPU Gemma 4.
Runnable version in the repo →
What mountPod returns
const { runtime, destroy } = await GemmaPod.mountPod(el, config, options?);runtime— theGemmaPodRuntimeinstance. Use it to subscribe to events, drive chat from code, or observe state.destroy()— call on unmount / route change. Closes the transport, removes the Preact widget, tears down the fallback panel.
Useful options
GemmaPod.mountPod(el, config, {
ui: "chat", // default. "none" = headless, host renders UI.
fallbackUi: "default", // default if transport.fallback is set. "none" = no panel.
fallbackPlacement: "before",// where the panel mounts relative to el. "before" | "after" | "prepend".
fallbackMountParent: someEl // used with ui: "none" + fallbackUi: "default".
});See mountPod reference for every
option.
Subscribe to events
const { runtime } = await GemmaPod.mountPod(el, config);
runtime.events.on("transport.ready", (e) =>
console.log("connected via", e.transport),
);
runtime.events.on("transport.fallback", (e) =>
console.warn("falling back:", e.reason),
);
runtime.events.on("ui.event", ({ event }) => {
// Every signed gemmapod.ui.event arrives here, regardless of transport.
// STATE_SNAPSHOT, TEXT_MESSAGE_*, TOOL_CALL_*, CUSTOM, etc.
console.log(event.type, event);
});Production checklist
- Pin the version — replace
@0.1.0with whatever tag you tested. - Add Subresource Integrity (see embedding cookbook).
- Set a strict CSP on the host page. The shim needs
'wasm-unsafe-eval'for the WASM core and'unsafe-inline'for the inlined boot snippet; everything else can be locked down. - Point
signalUrlat your own broker — either self-hosted or the publicsignal.gemmapod.com. - Call
destroy()on route change in SPAs.