Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Privacy-first social content embed with click-to-activate. Supports Bluesky, Mastodon, X, Instagram, and YouTube via a provider registry.
A privacy-first social content embed component. Click-to-activate by default — no third-party scripts or network requests execute until the user clicks the embed card. Supports Bluesky, Mastodon, X, Instagram, and YouTube out of the box, with an extensible provider registry for custom platforms.
The inner fallback content (typically an <a>) renders without JavaScript, is indexable by search engines, and remains accessible to all users.
Auto-detected from bsky.app URLs. Uses oEmbed — no third-party script injected.
<social-embed url="https://bsky.app/profile/bsky.app/post/3lb55bvibcs2w"> <a href="https://bsky.app/profile/bsky.app/post/3lb55bvibcs2w">View post on Bluesky</a></social-embed>
Auto-detected from @user/id URL patterns. Parses the instance hostname from the URL and fetches oEmbed from the correct server.
<social-embed url="https://mastodon.social/@Mastodon/109838793196353548"> <a href="https://mastodon.social/@Mastodon/109838793196353548">View post on Mastodon</a></social-embed>
Auto-detected from x.com or twitter.com status URLs. Loads the X widgets script on activation.
<social-embed url="https://x.com/github/status/1234567890"> <a href="https://x.com/github/status/1234567890">View post on X</a></social-embed>
Automatically delegates to <youtube-player>. The YouTube provider sets delegatesActivation: true, so social-embed skips its own click gate — youtube-player handles its own facade pattern (thumbnail + play button). One click, not two.
<social-embed url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"> <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Watch on YouTube</a></social-embed>
Use provider to bypass auto-detection when the URL pattern is ambiguous.
<social-embed provider="mastodon" url="https://mastodon.social/@user/12345"> <a href="https://mastodon.social/@user/12345">View post on Mastodon</a></social-embed>
Control when the embed loads with activate.
| Value | Behaviour |
|---|---|
click (default) | User must click the idle card to trigger loading |
visible | Loads when scrolled into viewport (IntersectionObserver with 200px margin) |
eager | Loads immediately on page load |
<social-embed url="https://bsky.app/profile/user/post/3abc" activate="visible"> <a href="https://bsky.app/profile/user/post/3abc">View post on Bluesky</a></social-embed>
Pass theme="dark" to hint to providers that support themed embeds. The default auto reads prefers-color-scheme.
<social-embed url="https://x.com/user/status/123" theme="dark"> <a href="https://x.com/user/status/123">View post on X</a></social-embed>
Wrap in a <figure> with <figcaption> for semantic context.
<figure> <social-embed url="https://bsky.app/profile/user/post/3abc"> <a href="https://bsky.app/profile/user/post/3abc">View post on Bluesky</a> </social-embed> <figcaption>A post about the new CSS features.</figcaption></figure>
| Attribute | Required | Type | Default | Description |
|---|---|---|---|---|
url | Yes | string | — | URL of content to embed |
provider | — | string | — | Explicit provider key. If omitted, auto-detection runs. |
theme | — | string | auto | light, dark, or auto (reads prefers-color-scheme) |
activate | — | string | click | click, visible, or eager |
| Attribute | Values | Description |
|---|---|---|
state | idle, loading, loaded, error, unsupported | Current lifecycle state (read-only) |
| State | When | Visual |
|---|---|---|
idle | Before activation trigger | Bordered card with pointer cursor |
loading | Provider render() called | Skeleton pulse animation |
loaded | render() resolved | Embed content displayed |
error | render() rejected | Error border, fallback link restored |
unsupported | No provider matched | Fallback link only (no error treatment) |
| Key | Mechanism | Notes |
|---|---|---|
bluesky | oEmbed fetch | No third-party script. Most private option. |
mastodon | oEmbed fetch | Instance URL parsed automatically. |
x | Script injection | Loads platform.x.com/widgets.js. Respects theme. |
instagram | Script injection | Loads instagram.com/embed.js. |
youtube | Delegates to <youtube-player> | No double click — youtube-player handles its own facade. |
Register a custom provider with SocialEmbed.register():
import { SocialEmbed, loadScript, fetchOEmbed } from './social-embed/logic.js'; SocialEmbed.register('my-platform', { canHandle(url) { return url.includes('my-platform.example'); }, async render(host, url, { theme }) { const data = await fetchOEmbed('https://my-platform.example/oembed', url); host.innerHTML = data.html; }});
| Scenario | Behaviour |
|---|---|
| No JS | Fallback <a> link visible and clickable |
| JS + click-to-activate | Styled card with pointer cursor, loads on click |
JS + activate="visible" | Loads when scrolled near viewport |
JS + activate="eager" | Loads immediately |
| Error during render | Fallback content restored, error state styled |
<a> provides a meaningful link for all users regardless of JS staterole="button" and tabindex="0" for keyboard accessprefers-reduced-motion<youtube-player> which uses youtube-nocookie.com<youtube-player> — Standalone YouTube embed with facade pattern<share-wc> — Social sharing buttons