Skip to Content
GuidesMicrofrontends

Orbz in microfrontends

A web component is a useful microfrontend boundary because its runtime contract belongs to the browser rather than to one framework. Orbz can be rendered by a Vue remote, updated by an Angular shell, and replaced later by a React surface without changing the tag or its attributes.

Orbz is intentionally a leaf visual component, not a routing system or a complete microfrontend platform. Use your existing composition strategy for navigation, data, identity, and deployment. Use orb-z as the shared assistant presence at the edge of those systems.

The shared contract

The most durable integration is platform-level markup:

<orb-z state="idle" size="18rem" preset="neongate" reduced-motion="system" ></orb-z>

The shell or remote updates public properties when domain state changes:

import type { OrbzElement, OrbzState } from "@neongate-ai/orbz"; export function renderAssistantState(state: OrbzState) { const orb = document.querySelector<OrbzElement>("orb-z"); if (orb) orb.state = state; }

No framework object crosses the boundary. The contract is strings, numbers, boolean attributes, and three methods.

Choose who registers the element

There are three practical models.

1. The shell registers Orbz

The application shell imports the browser entry once:

import "@neongate-ai/orbz/browser";

Remotes only render <orb-z>. This minimizes duplicate package code and gives the shell explicit ownership of the version. It is the clearest default when the shell already owns global design primitives.

2. Each remote imports the same pinned version

Every remote can depend on and import Orbz independently. Registration is idempotent, so later imports see the existing orb-z definition instead of defining it again.

Coordinate an exact package version across deployments. The Custom Elements registry cannot replace an already-defined tag: the first version registered on the page wins. Version skew can therefore make behavior depend on remote load order even though registration itself does not throw.

3. Share Orbz through your bundler or import map

Module Federation, an import map, or another runtime sharing mechanism can provide one package instance. This can reduce duplicate bytes, but it is an optimization—not a requirement of Orbz. Keep the version rule explicit even when tooling marks the package as a singleton.

Keep ownership clear

Choose one owner for each responsibility:

ConcernRecommended owner
Registering orb-zShell, or a coordinated shared dependency
Voice session and model callsAssistant feature or platform service
Mapping domain state to Orbz stateFeature that owns the session
Orb size and presetSurface that owns layout and brand context
Status text and controlsThe rendering remote
Orbz animation and internal stylesOrbz itself

Avoid having multiple remotes write to the same element. A shared service can publish assistant domain state, but the remote that renders the orb should be the only code that maps and applies that state.

Communicate domain state, not DOM instructions

A weak contract publishes commands such as “set the orb to purple” or “pause layer three.” That leaks presentation into the platform bus.

A stronger contract publishes meaningful application state:

type AssistantStatus = | { phase: "ready" } | { phase: "capturing" } | { phase: "processing" } | { phase: "playing" } | { phase: "offline" } | { phase: "error"; message: string };

The rendering remote maps capturing to listening, processing to thinking, and so on. Errors remain real text and actions rather than becoming an undocumented animation.

Independent deployments

Repository structure and deployment structure are separate choices. A shared repository may make local orchestration convenient, while each example or microfrontend remains an independent Vercel project. Conversely, unrelated repositories can consume the same npm version and render an identical orb.

For an independently deployed surface:

  1. add @neongate-ai/orbz to that application’s own dependencies;
  2. pin or centrally govern the allowed version;
  3. import /browser in a browser entry, or /react in a React Client Component;
  4. expose assistant state through the application’s existing data contract;
  5. deploy without importing Orbz source or another example application.

The live Vanilla , React , Vue , Svelte , Angular , and Next.js  showcases demonstrate six independent hosts using the same component surface.

Failure and fallback behavior

Before registration, an unknown custom element remains valid inert HTML. This is a useful progressive boundary: surrounding labels and controls can still render while the component bundle loads.

Design the host so that the assistant is understandable without the animation:

<div role="status" aria-live="polite"> <orb-z state="thinking"></orb-z> <span>Assistant is preparing a response</span> </div>

If a remote fails to load, the text still communicates state. If Orbz registers later, the element upgrades in place.

Microfrontend checklist

  • Use the npm package as the boundary; do not import src/ from another app.
  • Coordinate one exact Orbz version across concurrently loaded remotes.
  • Register in one known place when practical.
  • Keep one writer for each rendered orb.
  • Publish domain state over the application bus, not internal visual details.
  • Keep status text and controls outside the closed Shadow DOM.
  • Test host upgrades with reduced motion and with JavaScript delayed.
  • Treat the tag name and documented attributes as the stable integration API.
Last updated on