The philosophy behind Orbz
Orbz starts with a deliberately small idea: an assistant’s visual presence should not have to be rebuilt every time the surrounding application changes framework.
The browser already has a shared component model. Orbz uses it. The native
<orb-z> element exposes the same states, appearance controls, and motion
controls in plain HTML, Vue, Svelte, Angular, React, Next.js, or a mixed
microfrontend page.
One contract, many hosts
Framework integrations usually drift. A React wrapper gains a feature that the Vue component does not have; an Angular implementation chooses different defaults; the plain JavaScript version is forgotten. Orbz keeps one native implementation and lets frameworks bind to its public attributes and properties.
That gives every host the same vocabulary:
- five assistant states:
idle,listening,thinking,speaking,asleep - one
presetattribute or five custom color attributes size,speed,paused,elevated, andreduced-motionplay(),pause(), andrestart()methods
The six examples intentionally present the same interface. Their framework code is different; the component contract and user experience are not.
A visual primitive, not an assistant SDK
Orbz owns visual expression. Your application owns everything that gives that expression meaning:
- microphone permission and audio capture
- speech recognition and synthesis
- model requests, tool calls, and streaming
- turn-taking, cancellation, errors, and retries
- transcripts, buttons, labels, and other semantic UI
This boundary keeps the package useful with any voice vendor, AI SDK, state manager, or backend. An application translates its domain events into one of the five Orbz states; Orbz renders the corresponding presence.
See Building a voice assistant for a practical state mapping.
Strict by design
The supported surface is intentionally attribute-driven. Orbz does not expose
Shadow DOM parts or public CSS variables, and the React adapter does not accept
className, style, children, or a forwarded ref.
Strictness serves three purposes:
- Portability. The same configuration means the same thing in every host.
- Stability. Internal layers and animation details can evolve without becoming accidental public APIs.
- Consistency. Product teams customize the intended tokens instead of replacing the component one selector at a time.
When a product needs a distinct visual identity, it can choose a built-in preset or provide the five documented colors. When it needs different semantics or interaction, those belong in the application around the orb.
Isolation is an implementation promise
Each instance creates a closed Shadow DOM. Its markup, styles, and animation layers are private. Page CSS cannot reach in and rewrite them, and Orbz does not leak its internal selectors into the page.
Closed does not mean inaccessible. Orbz is a decorative visual primitive, so the internal graphic is hidden from assistive technology. The host application provides an accessible label or, preferably, nearby live status text that describes the assistant’s current state.
Server-safe, browser-native
The package can be imported during server rendering without evaluating an
HTMLElement subclass at module scope. Registration is guarded and
idempotent: on a server it is a no-op, and in a browser it defines orb-z only
when the tag is not already registered.
This makes the native element compatible with server-rendered shells while preserving a browser-native runtime. The server can emit the element; the client upgrades it when Orbz is registered. The React entry adds a strict Client Component adapter for React and Next.js projects that prefer JSX props.
Read SSR and hydration for the recommended patterns.
Repository layout is not the runtime architecture
The Orbz repository uses workspace tooling to develop the package and its examples together. That does not make consumers part of a monorepo and does not make the examples part of the published package.
Each showcase can be deployed as an independent Vercel project and consume
@neongate-ai/orbz from npm. A microfrontend shell can do the same. The durable
boundary is the published package and the <orb-z> contract—not the repository
folder structure.
The test for a new feature
Before extending the public surface, ask:
- Is this a visual concern shared by every framework?
- Can it be expressed as a small, serializable attribute or typed property?
- Can its behavior stay deterministic across native HTML and adapters?
- Does it preserve the closed, strict component boundary?
- Can applications still provide accessible meaning outside the orb?
If the answer is no, the feature probably belongs in the host application. A small contract is not a limitation; it is what lets one component remain one component everywhere.