Drop a Cuppa Studio deck into any web page. The recommended path
is a one-line <iframe> pointing at a share URL —
no install, no build, no CDN. Self-hosted options below.
Every deck has a public share URL (the Share button in
the editor copies it to your clipboard — it looks like
https://cuppa.studio/p/abc123). Take the id after
/p/ and drop it into an iframe:
<iframe
src="https://cuppa.studio/player-frame?share=abc123&autoplay=true&controls=false"
width="800"
height="450"
style="border: none; border-radius: 8px;"
allow="autoplay; fullscreen"
title="My Presentation"
></iframe>
The iframe loads /player-frame on cuppa.studio,
fetches the deck JSON via the share API, and renders the player
in its own document — which means scaling, fonts, and renderers
(Shiki, Mermaid, Chart.js) work the same way they do on
cuppa.studio itself, regardless of the host page's CSS.
| Param | Default | Description |
|---|---|---|
share | — | Share id (the bit after /p/). Required. |
autoplay | false | Auto-advance through slides silently on load. |
autodrive | false | Auto-narrate using the deck's transcript (loads voice + advances slides as it reads). |
controls | true | Show in-iframe controls (play/pause, scene counter, voice button). Set to false for clean preview thumbnails. |
Tip: for small preview thumbnails (under
~500 px wide), the in-iframe controls are hard to use
reliably. The common pattern is to set
autoplay=true&controls=false, wrap the iframe
in an anchor with pointer-events: none on the
iframe, and link to the full share URL in a new tab:
<a
href="https://cuppa.studio/p/abc123"
target="_blank"
rel="noopener"
style="display: block; aspect-ratio: 16/9; position: relative;"
>
<iframe
src="https://cuppa.studio/player-frame?share=abc123&autoplay=true&controls=false"
style="width: 100%; height: 100%; border: 0; pointer-events: none;"
tabindex="-1"
title="Preview"
></iframe>
</a>
If you're linking to a deck that lives on cuppa.studio under
/presentations/<slug>/ (the curated library,
not a user share), swap share=<id> for
src=/presentations/<slug>/. Same query
parameters otherwise.
If you need an embed that works without cuppa.studio — for offline use, an email attachment, a private intranet, or a self-hosted static site — export the deck to a single HTML file with the CLI:
mycuppa export slides.cup --out talk.html The exported HTML bundles the player, the deck, and all assets into one file. It can be:
<iframe
src="https://example.com/my-talk.html"
width="800"
height="450"
style="border: none; border-radius: 8px;"
title="My Presentation"
></iframe>
The iframe accepts postMessage commands from its
parent window, so you can drive scene changes or load decks
dynamically without a query-string round-trip:
const frame = document.querySelector("iframe");
// Load a CupFile object directly
frame.contentWindow.postMessage({
type: "load-cupfile",
cupFile: { manifest, content, theme, timesheet, transcript },
}, "*");
// Jump to a specific scene
frame.contentWindow.postMessage({ type: "go-to-scene", index: 3 }, "*");
// Load a transcript and start voice playback
frame.contentWindow.postMessage({
type: "load-transcript",
transcript,
autoStart: true,
}, "*");
The iframe posts events back to the parent on scene changes,
voice state changes, and layout reports — listen for
scenechange, voice-started,
voice-stopped, and layout-report on
window.message.
Status: experimental. Not published to npm yet. Currently being trialled on cuppatech.com and (planned) mycuppa.io as the staging ground. The iframe path above is production-ready and should be used for any live embed today.
<cuppa-cue> is the planned drop-in
self-hosted embed for sites that want to avoid an iframe
boundary entirely — useful when the host page wants direct
DOM access to the player, deeper styling control, or to drop
the cuppa.studio runtime dependency. We're holding the npm
publish until shadow-DOM scaling and font loading reach
parity with the iframe path across the major browsers we
care about.
<script type="module">
// Planned — not published yet
import "@cuppa-studio/embed";
</script>
<cuppa-cue src="https://cuppa.studio/p/abc123" autoplay></cuppa-cue> Planned attributes:
| Attribute | Description |
|---|---|
src | A share URL (/p/<id>) or a static .cup directory URL. |
autoplay | Start playing immediately on load. |
Planned JavaScript API:
const el = document.querySelector("cuppa-cue");
el.goToScene(0); // Navigate to a scene
el.play(); // Start autoplay
el.pause(); // Pause autoplay
el.getPlayer(); // Access the underlying CuePlayer
el.addEventListener("load", () => { /* ready */ });
el.addEventListener("error", (e) => { console.error(e.detail); });
If you're keen to try the experimental build before npm
publish, the bundle is vendored at
cuppatech.com/embed/cuppa-cue.js. Expect rough
edges until the roadmap clears.