Skip to content
Djalma Jr.
Portfolio

Frame

A micro-frontend architecture that composes independent web apps into one shell, with a typed SDK over Web Components, iframes and postMessage.

View project →

Ship a product as one polished shell, but build it as many small apps that teams own end to end. Frame is the micro-frontend architecture that makes that possible: a host page composes independent web apps into a single experience, and a typed SDK keeps the two sides talking — without ever sharing a bundle. Published as @zomme/frame, it powers the micro-frontend shell in Buntime.

The problem it solves

Splitting a frontend into independent apps usually means giving up isolation or giving up integration. Share a bundle and one team’s upgrade breaks another’s build; isolate everything in iframes and you lose the typed, two-way communication a real product needs. Frame keeps both: each app stays a separate deployable behind an iframe, while a typed channel lets the host and child pass props, call methods and exchange events as if they were one app.

How it works

flowchart LR
  host["Host page · z-frame"] -->|"props · theme · apiUrl"| child["Embedded app · frame SDK"]
  child -->|"events · emit (postMessage)"| host

The host declares a <z-frame> element pointing at a child app, sets props, calls methods and listens for events. The child imports the SDK, initializes, reads its props (including callbacks) and emits or listens back to the host.

// Host page
const frame = document.querySelector("z-frame");
frame.apiUrl = "https://api.example.com";
frame.theme = "dark";
frame.onSuccess = user => console.log("created", user);

frame.addEventListener("ready", () =>
  frame.emit("theme-change", { theme: "dark" })
);
frame.addEventListener("user-created", e => console.log(e.detail));

// Child app
import { frameSDK } from "@zomme/frame/sdk";

await frameSDK.initialize();
frameSDK.props.onSuccess({ id: 1 });
frameSDK.on("theme-change", ({ theme }) => applyTheme(theme));
frameSDK.watch(["apiUrl", "theme"], changes => reconfigure(changes));
frameSDK.emit("user-created", { id: 1 });
<z-frame
  name="admin"
  src="https://apps.example.com/admin"
  base="/admin"
></z-frame>

What you get

Stack

A Bun monorepo in TypeScript, with example apps (including Vue) building to static bundles — proof the host stays framework-agnostic while each child picks its own.

Availability

Open source under the Apache 2.0 license.