embed-card
Frameworks

Web Component

Use the same package from Vue, Svelte, Astro, or plain HTML with the custom element export.

Web Component

If the host app is not React-first, register the custom element:

import { registerEmbedCard } from "embed-card/web-component"

registerEmbedCard()

Then use it anywhere HTML is allowed:

<embed-card
  url="https://www.google.com/maps?q=Tokyo+Station&output=embed"
  accent-color="#0f766e"
  radius="26px"
></embed-card>

The shadow attribute is optional (same as theme.shadow in React). Omit it for no drop shadow, or set it to any CSS box-shadow value (for example 0 20px 60px rgba(15, 23, 42, 0.12)).

For fallback link previews (URLs that do not match a built-in provider), the cta-label attribute overrides the default Open original label inside the card. It has no effect on iframe or Reddit embeds.

<embed-card url="https://example.com" cta-label="Visit site"></embed-card>

Styling the shadow tree

The embed surface is a <figure class="root" part="root">. Expose one part for host-page CSS:

PartElement
rootThe card surface root (<figure>)
embed-card::part(root) {
  border-radius: 18px;
}

Older releases exposed additional shadow parts (header, footer, preview); those are removed—style ::part(root) or rely on attributes and CSS variables from Custom Rendering → Theming reference.

Dark mode

The appearance attribute controls the embed surface palette — the same three values as the React theme.appearance prop:

<!-- always dark -->
<embed-card url="..." appearance="dark"></embed-card>

<!-- always light (default) -->
<embed-card url="..." appearance="light"></embed-card>

<!-- follow OS preference; re-renders when prefers-color-scheme changes -->
<embed-card url="..." appearance="system"></embed-card>

When appearance="system" the element subscribes to matchMedia("(prefers-color-scheme: dark)") and re-renders automatically on OS theme changes. The listener is removed in disconnectedCallback so there are no leaks.

Good fit for

  • Vue apps that want a tiny integration surface
  • Svelte or Astro pages with isolated embeds
  • CMS-driven frontends rendering HTML fragments
  • Plain JS projects that still want the package logic

Runnable examples

Starter apps that call registerEmbedCard() and render <embed-card> are in examples/vue-vite, examples/svelte-vite, and examples/vanilla-vite. See Getting Started for how to run or copy them.

Reddit inside the shadow root

For Reddit thread URLs, the custom element shows a skeleton first, then hydrates the shadow tree with the same JSON-driven card as React: it fetches the public .json endpoint and replaces the mount region with markup built in the component (no redditmedia iframe).