Symbiote.js

Symbiote.js

Why does Symbiote.js exist?

Runtime Agnostic Templates (RAT) are the main reason. In Symbiote.js, a template is an HTML string that describes markup and named bindings. It is independent of a component instance, render function, runtime, and templating tool. You can define, customize, compose, render, and reuse it at any point in the application lifecycle, on the client or the server.

RAT keeps UI structure, data bindings, and actions declarative across client rendering, SSR, SSG, and hybrid rendering. Symbiote.js can also work beside other frameworks and expose UI capabilities to agents. It requires no virtual DOM, proprietary template syntax, or mandatory build step.

RAT: Runtime Agnostic Templates

Documentation Code Examples npm GitHub Community

Why Symbiote.js?

Symbiote.js extends native Custom Elements with reactive data bindings, portable HTML templates, state contexts, routing, and SSR. It works directly with standard browser APIs, keeps boilerplate small, and does not require a build step.

Three design choices set it apart from most UI libraries:

1. Runtime Agnostic Templates

Many component libraries bind a template to a render function, compiler, or component instance. Symbiote.js templates remain plain HTML strings with named binding metadata. The component and its data context are resolved later, when the template is rendered or hydrated. That separation makes templates portable across runtimes and rendering strategies.

  • Write templates with standard tags and attributes, plus a compact binding syntax for reactivity.
  • Use output from the html helper, plain HTML strings, external template modules, or document-level <template> elements.
  • Let the html helper turn JavaScript binding objects into HTML binding attributes.
  • Reuse the same template on the client, on the server, or in a static generation pipeline.
  • Combine templates with any server-side template system or UI framework, including React, Vue, and Angular.
  • Replace or customize a template without moving it into component logic or restructuring the rest of the application.

2. Direct extension of the DOM

Symbiote.js uses the native DOM API instead of placing a virtual DOM, JSX compiler, or proprietary component format between your code and the browser.

  • Symbiote components are Custom Elements, so you can inspect and control them like any other DOM node.
  • Reactive state changes update bound DOM properties directly and use the browser's own optimizations.
  • Direct DOM access remains available when declarative bindings are not enough.
  • The library has zero dependencies and adds little runtime weight.
  • Standard HTML, CSS, and JavaScript remain the application foundation, which avoids framework lock-in.
  • You can extend the application base class with project-specific features.

3. App-wide state without prop drilling

Symbiote.js uses the document structure as a data-flow graph. A component can connect to local state, its nearest owning ancestor, a shared group, or a named global context through the same binding syntax.

  • Reactive bindings connect template values and action handlers to local or external data contexts.
  • DOM ancestry can model data flow without prop drilling or wrapper components.
  • Shared contexts group components in the same way a name attribute groups native radio buttons.
  • Named contexts provide app-wide data sources. Namespace bindings such as APP/user give any component or template explicit access to them.
  • Components can share state while remaining loosely coupled.
  • The same state interface resolves values in browser and Node.js environments, so isomorphic components do not need separate state logic.
  • The underlying pub/sub primitives support data flows of any complexity.

More built-in features

Itemize API

Render dynamic lists from reactive data:

<div itemize="users">
  <template>
    <span>{{name}}</span> -- <span>{{role}}</span>
    <button ${{onclick: '^removeUser'}}>Remove</button>
  </template>
</div>
  • Update the source data and Symbiote.js updates the rendered list efficiently.
  • Each item becomes a component connected to the corresponding data context.
  • Use the item-tag attribute to render items with a dedicated component.
  • CSS transitions animate removed items without additional JavaScript.
  • Nest lists to represent structured data.
  • Enable keyed updates for efficient reordering and fewer DOM mutations.

Server-side rendering

Use the same component implementation on the server and the client. The SSR class generates complete or streamed markup. In the browser, isoMode = true hydrates existing server-rendered content or renders the template from scratch. SSR output handles both Light DOM styles and Declarative Shadow DOM.

SSR: one component for server and client

Built-in SPA router

The built-in router provides client-side navigation without another dependency:

  • Define path-based routes with :param extraction.
  • Add route guards for authentication and access control.
  • Load route components lazily.
  • Bind route data directly in templates through a named routing context.

CSS-driven animations

The animateOut helper manages exit transitions without JavaScript animation code. It sets a [leaving] attribute, waits for the CSS transitionend event, and then removes the element. The Itemize API uses the same behavior for list removals.

Security

  • Template writes support Trusted Types through a named 'symbiote' policy when the API is available.
  • Symbiote.js works with strict Content Security Policy headers.

Agentic web and TypeScript

Built-in WebMCP support lets an application expose its current UI state and actions as browser-native tools for agents.

TypeScript support

Symbiote.js combines JSDoc declarations with *.d.ts files for complex and global types. JavaScript projects get static type analysis without mandatory transpilation, while TypeScript and mixed codebases can use the same source modules without extra setup.

Ecosystem

Shadow DOM is optional, so Symbiote components can share a page with other libraries and CSS frameworks. Three.js, D3, Chart.js, and CSS utility libraries work through their usual APIs without framework adapters, wrapper components, or compatibility layers.

For teams that want a project scaffold, JSDA-Kit can create a Symbiote.js project in under a minute. It works as a static site generator for JAMstack sites or as a lightweight framework for dynamic applications. The toolkit includes SSR, esbuild bundling, automatic import maps, and a CLI that needs no configuration.

Where Symbiote.js fits

  • Rich multipart widgets and complex interactive components
  • Microfrontend architectures
  • Reusable component libraries
  • High-performance web applications
  • Framework-agnostic solutions
  • Meta-applications
  • JAMstack and hybrid sites
  • AI-ready applications

Try it

<script type="importmap">
  {
    "imports": {
      "@symbiotejs/symbiote": "https://esm.run/@symbiotejs/symbiote"
    }
  }
</script>

<script type="module">
  import Symbiote, { html } from '@symbiotejs/symbiote';

  export class MyComponent extends Symbiote {
    count: 0,
    onIncrement() {
      this.$.count++;
    }
  }

  // Define template:
  MyComponent.template = html`
    <h2>{{count}}</h2>
    <button ${{onclick: 'onIncrement'}}>Click me!</button>
  `;

  // Register new tag name:
  MyComponent.reg('my-component');
</script>

Use the component anywhere in your HTML:
<my-component></my-component>

Save this example as HTML and open it in a browser. It works without installation, build tools, or a local server. TypeScript, bundlers, and linters remain available when your project needs them.

Live code playground



More examples

Learn more

Documentation npm GitHub Community
26.08.2026
Agentic EAM
The future of Enterprise Asset Management
06.07.2026
JSDA-Kit 1.6.x -- What's New?
Features for Richer Static Output
03.06.2026
Symbiote.js & WebMCP
The important part of modern web usability
28.05.2026
Symbiote.js v3.7.x
What's new?
03.05.2026
Symbiote VS Lit
David and Goliath: differences, pros and cons...
11.12.2025
JSDA is very simple
A new, simple, but powerful way to build modern web applications.
28.09.2024
It was really possible?
Symbiote.js as an answer to many questions
17.09.2024
Smart HTML-tags
Simple recipe with the Artificial Intelligence
18.01.2024
Symbiote.js 2.x
Next generation of Symbiote.js is released. Let's see what's new...
RND-PRO.com © 2026 | Built with JSDA-Kit