Tired of pointless re-renders? Bloated bundles? Chaotic data flow? Laggy UI? Magic abstractions and compiler quirks? Done with frameworks that add complexity instead of removing it?
Miss the vanilla flavor, but still want great DX?
Symbiote.js is here to save you.
Symbiote.js isn't trying to be yet another frontend library. Think of it more like a philosophy for web development that embraces the power of what's already built into your browser.
We believe in using modern, standard web technologies, not reinventing them. Symbiote.js simply adds a touch of modern developer experience (DX) on top of vanilla Custom Elements. You get cool things like reactive data bindings, flexible HTML-based templates, powerful state management, and easily extendible components, all with minimal boilerplate and setup.
Here’s what makes it feel a bit different:
Unlike frameworks that wrap your code in complex abstractions, Symbiote.js works directly with the native DOM API. For you, this means:
We take a refreshingly simple approach to templating:
// Define templates anywhere, client or server:
import html from '@symbiotejs/symbiote/core/html.js';
const myTemplate = html`
<div class="my-component" ${{onclick: 'showBubble'}}>
<h1>{{title}}</h1>
<div>{{content}}</div>
</div>
`;
This is where things get interesting. Symbiote.js has a fresh take on how components talk to each other and manage state:
// Inherited context (^)
html`<button ${{onclick: '^onButtonClicked'}}>Click me!</button>`;
// Shared context (*)
html`<div>{{*sharedProperty}}</div>`;
// Named context (/)
html`<div>{{APP/someProperty}}</div>`;
<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 {
// Initialize state:
init$ = {
count: 0,
increment: () => {
this.$.count++;
},
}
}
// Define template:
MyComponent.template = html`
<h2>{{count}}</h2>
<button ${{onclick: 'increment'}}>Click me!</button>
`;
// Register new tag name:
MyComponent.reg('my-component');
</script>
Use the component anywhere in your HTML:
<my-component></my-component>
This little HTML example has everything you need to get a Symbiote.js app running. While it shows off the basic concepts, you can totally use it with your favorite development tools like TypeScript, bundlers, linters, and all that good stuff.