Embeds
An embed is a component: a file in app/components/ that takes the embed's ID as a typed prop and renders the provider's frame or card. A page links it and uses it like any other component.
A YouTube component
app/components/youtube.html renders a lazy-loaded YouTube frame from a video ID:
<template component="x-youtube">
<defs>
<prop name="video" type="string" required>The video's ID, the part after watch?v= in a YouTube URL.</prop>
<prop name="label" type="string" default="YouTube video">The frame's accessible title.</prop>
</defs>
<iframe from:src="concat('https://www.youtube-nocookie.com/embed/', $video)" from:title="$label"
loading="lazy" referrerpolicy="strict-origin-when-cross-origin"
allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
<style>:host { display: block; inline-size: 100%; aspect-ratio: 16 / 9; margin-block: 1rem; border: 0; }</style>
</template>videois a required string prop, andlabelan optional one.from:srcbuilds the frame's URL onyoutube-nocookie.com, YouTube's privacy-enhanced mode.from:titlegives the frame its accessible name fromlabel, which a page sets to the video's title.loading="lazy"loads the frame as it nears the viewport.- The frame is the template's one root element, so
:hoststyles it.
Using it in a page
Link the component once, then write the element on its own line:
<link rel="component" href="@/app/components/youtube.html">
<x-youtube video="aqz-KE-bpKQ" label="Big Buck Bunny"></x-youtube>Other providers
A component for another provider has the same shape: its props hold the embed's IDs, and from:src builds the provider's frame URL.
| Provider | Frame URL |
|---|---|
| Vimeo | https://player.vimeo.com/video/<video> |
| CodePen | https://codepen.io/<user>/embed/<pen> |
| StackBlitz | https://stackblitz.com/edit/<project>?embed=1 |
| CodeSandbox | https://codesandbox.io/embed/<sandbox> |