mf-element

Turns a React component into a Web Component, for embeds that need tighter integration with the host page than an iframe gives.

defineMfElement<{ agentName?: string; config?: Config }>("agent-panel", AgentPanel, {  attributes: { "agent-name": "string", config: "json" },  events: ["approve"],  css: builtTailwindCss,});// Host page<agent-panel agent-name="Avalo"></agent-panel>panel.addEventListener("approve", (e) => approve(e.detail));

Installation

Once per app, set up Aedis UI. The CLI verifies the signed release before writing anything and pins every dependency:

npx @aedis/cli@0.1.0 init

Import the theme once in your global CSS, after Tailwind:

app/globals.css
@import "tailwindcss";@import "./styles/aedis-theme.css";

Then add the component:

npx @aedis/cli@0.1.0 add mf-element# pnpm dlx @aedis/cli@0.1.0 add mf-element · yarn dlx @aedis/cli@0.1.0 add mf-element · bunx @aedis/cli@0.1.0 add mf-element

Props

PropTypeDefaultDescription
attributesRecord<name, "string" | "number" | "boolean" | "json">—Typed attributes, mapped to camelCase props and properties; bad values become undefined.
eventsstring[]—Events the component may emit through emit(); composed, bubbling CustomEvents. Others throw.
cssstring—Stylesheet for the shadow root.
maxJsonBytesnumber16384Largest JSON attribute accepted.
el.props = { … }property—For values that are not attributes, like objects and callbacks.

Security

  • Trade-off: the element's code runs in the host page's origin. Every script on that page can reach what it holds, so never hand it a token unless the host accepts that risk; prefer an iframe (mf-frame) when the two apps should not trust each other.
  • The host's CSP must allow the element's origin in script-src (and connect-src for its API).
  • Shadow DOM isolates CSS both ways; it is not a security boundary.
  • Attributes are parsed by type with a size limit for JSON, and only declared events leave the element.