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 initImport 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-elementProps
| Prop | Type | Default | Description |
|---|---|---|---|
| attributes | Record<name, "string" | "number" | "boolean" | "json"> | — | Typed attributes, mapped to camelCase props and properties; bad values become undefined. |
| events | string[] | — | Events the component may emit through emit(); composed, bubbling CustomEvents. Others throw. |
| css | string | — | Stylesheet for the shadow root. |
| maxJsonBytes | number | 16384 | Largest 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.