mf-frame

The host side of an embed: a sandboxed iframe that the embedded app sizes over mf-bridge, and the headers for both apps.

// Host page<MfFrame src="https://agent.example.com/panel" title="Agent panel" maxHeight={900} />// Embedded app (any component that renders inside the frame)useReportHeight(["https://backoffice.example.com"]);// middleware.ts of each appheaders: hostAppHeaders({ nonce, frameOrigins: [process.env.AGENT_ORIGIN!] })          // hostheaders: embeddedAppHeaders({ nonce, hostOrigins: [process.env.BACKOFFICE_ORIGIN!] })  // embedded app

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-frame# pnpm dlx @aedis/cli@0.1.0 add mf-frame · yarn dlx @aedis/cli@0.1.0 add mf-frame · bunx @aedis/cli@0.1.0 add mf-frame

Props

PropTypeDefaultDescription
src / titlestring / string—Absolute http(s) URL; title is required.
sandboxSandboxToken[]["allow-scripts", "allow-forms"]Known tokens only; allow-same-origin is refused when the frame has the host's origin.
allow / referrerPolicystring"" / "strict-origin-when-cross-origin"Permissions policy (empty: no camera, mic, geolocation…) and referrer.
minHeight / maxHeightnumber120 / 4000Bounds for the height the embedded app reports.
onBridge / messages(bridge) => void / specs—The mf-bridge to the embedded app, for its own messages.
useReportHeight(hostOrigins)hook—In the embedded app: reports the document height to the host.
embeddedAppHeaders / hostAppHeaderslib—securityHeaders with frame-ancestors (embedded) or frame-src (host) from configuration.

Security

  • Minimal sandbox; allow-same-origin is refused for a frame on the host's origin, because with allow-scripts it could remove its own sandbox.
  • Empty permissions policy, a referrer policy and a required title by default.
  • The height comes over mf-bridge from the frame's origin only, and is bounded.
  • frame-ancestors on the embedded app and frame-src on the host come from configuration; wildcards and malformed entries are dropped, so neither can become '*'.