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 sandboxes intentionally present the same interface. Their framework code is different; the component contract and user experience are not.
A visual primitive with optional speech ports
Orbz owns visual expression and provides an optional talk flow with browser and OpenAI-compatible speech adapters. Your application owns the decision and security boundaries that give that expression meaning:
- when voice starts or stops and how the visitor opts in
- microphone permission, audio capture, and speech recognition
- voice-engine selection, protected speech endpoints, and credentials
- 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 and, when needed, explicitly starts the configured talk runtime; 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, public CSS variables, or framework-specific component adapters.
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 optional react-types entry
adds JSX typing without introducing a React wrapper or runtime adapter.
Read SSR and hydration for the recommended patterns.
Repositories follow the public boundaries
The Orbz package, this documentation site, and the Orbz Sandbox are independent
projects. The Sandbox applications consume @neongate-ai/orbz@0.3.1 from npm;
neither the Docs nor the Sandbox imports a sibling package workspace or private
source path.
Each sandbox can be deployed as an independent Vercel project. A microfrontend
shell can consume the same package. The durable boundary is the published
package and the <orb-z> contract—not a shared repository layout.
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.