Entregue um produto como um único shell polido, mas construa-o como várias
aplicações pequenas, cada uma com seu time dono de ponta a ponta. O Frame é a
arquitetura de micro-frontend que torna isso possível: uma página hospedeira
compõe aplicações web independentes em uma única experiência, e um SDK tipado
mantém os dois lados conversando — sem nunca compartilhar um bundle. Publicado
como @zomme/frame, é o shell de micro-frontends do
Buntime.
O problema que ele resolve
Dividir um frontend em aplicações independentes normalmente significa abrir mão do isolamento ou da integração. Compartilhe um bundle e a atualização de um time quebra o build de outro; isole tudo em iframes e você perde a comunicação tipada e bidirecional que um produto de verdade exige. O Frame mantém os dois: cada aplicação continua um deploy separado por trás de um iframe, enquanto um canal tipado deixa hospedeira e filha trocarem props, chamarem métodos e trocarem eventos como se fossem uma só aplicação.
Como funciona
flowchart LR host["Host page · z-frame"] -->|"props · theme · apiUrl"| child["Embedded app · frame SDK"] child -->|"events · emit (postMessage)"| host
A hospedeira declara um elemento <z-frame> apontando para uma aplicação filha,
define props, chama métodos e escuta eventos. A filha importa o SDK, se
inicializa, lê suas props (incluindo callbacks) e emite ou escuta de volta para a
hospedeira.
// Página hospedeira
const frame = document.querySelector("z-frame");
frame.apiUrl = "https://api.example.com";
frame.theme = "dark";
frame.onSuccess = user => console.log("criado", user);
frame.addEventListener("ready", () =>
frame.emit("theme-change", { theme: "dark" })
);
frame.addEventListener("user-created", e => console.log(e.detail));
// Aplicação filha
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>
O que você ganha
- Elemento hospedeiro —
<z-frame name src base>: define props (frame.apiUrl,frame.theme,frame.onSuccess), chama métodos (frame.emit('theme-change', {...}), com aliases em camelCase comoframe.themeChange({...})) e escuta eventos (frame.addEventListener('ready', ...), além de customizados como'user-created'). - SDK filho —
@zomme/frame/sdk:await frameSDK.initialize(), leitura deframeSDK.props(incluindo callbacks),frameSDK.emit()/frameSDK.on()eframeSDK.watch([...], changes => {...})para reagir a mudanças de props. - Injeção de base-path — SPAs embarcadas continuam funcionando sob um
sub-path, então uma filha servida em
/adminroteia corretamente sem reescritas por aplicação.
Stack
Um monorepo Bun em TypeScript, com aplicações de exemplo (incluindo Vue) compiladas para bundles estáticos — prova de que a hospedeira permanece agnóstica de framework enquanto cada filha escolhe o seu.
Disponibilidade
- Código: github.com/djalmajr/frame
- Relacionado: Buntime — usa o Frame como shell
Open source sob a licença Apache 2.0.