
Symbiote.js
A friendly DX-focused extension for native Custom Elements.
Documentation Code Playground npm GitHub Community So, what's the big idea?
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:
It’s a Pure DOM Extension
Unlike frameworks that wrap your code in complex abstractions, Symbiote.js works directly with the native DOM API. For you, this means:
- No black boxes: What you write is what the browser runs. Simple as that.
- Native speed: It leverages the browser's own optimizations, so things are fast.
- No framework lock-in: It plays nicely with any other web technology you want to use.
- Feather-light: At only ~6kb (br/gzip), it won't weigh your pages down.
- Zero dependencies: It’s all built on native web platform features.
- Straightforward DOM interaction: Symbiote components are real DOM elements, so you can interact with them just like any other.
- The classic trio: Just HTML, CSS, and JavaScript. Everything you need for solid, enterprise-ready work.
Simple HTML String Templates
We take a refreshingly simple approach to templating:
- Just HTML: Use standard tags and attributes with a simple syntax for reactivity.
- Plays well with others: Works with any templating system or server-side tech you throw at it.
- Loosely Coupled: Define your templates when and wherever it makes sense in your workflow.
- Ready for SSR: A perfect fit for server-side rendering and static site generation.
- Integrates with anything: Easily use it with React, Vue, Angular, or any other framework.
- Built to scale: Powerful enough for even the most complex applications.
import html from '@symbiotejs/symbiote/core/html.js';
const myTemplate = html`
<div class="my-component" ${{onclick: 'showBubble'}}>
<h1>{{title}}</h1>
<div>{{content}}</div>
</div>
`;
DOM-Based Data Context
This is where things get interesting. Symbiote.js has a fresh take on how components talk to each other and manage state:
- Natural data flow: It uses the DOM structure itself as a natural way to create data context.
- Compose with ease: Components can share data just by their position in the DOM tree.
- CSS-like cascade: Properties can be inherited from parent components, much like CSS styles.
- Loosely coupled state: Components can share state without being tightly connected.
- Powerful named contexts: Create app-wide data sources that any component can tap into by name.
html`<button ${{onclick: '^onButtonClicked'}}>Click me!</button>`;
html`<div>{{*sharedProperty}}</div>`;
html`<div>{{APP/someProperty}}</div>`;
Where It Really Shines
- Building reach multipart widgets
- Crafting complex interactive components
- Micro-frontend architectures
- Creating reusable component libraries
- High-performance web apps
- Framework-agnostic solutions
- Meta-applications
- JamStack / Hybrid sites
The Core Goodness
- Loosely Coupled Architecture
- Ultralight: Just ~6kb (br/gzip)
- Wickedly Fast: Thanks to native DOM performance
- Memory Savvy: No wasteful immutable data structures
- Enterprise-Ready: Fully CSP compliant
- Type-Safe: Comes with full TypeScript support
- Developer-Friendly: Built on intuitive ideas
- Plays Well Everywhere: Works with any stack
- Tidy: Cleans up after itself automatically
- Modern to the Core: Native ESM support
- Open Source: MIT licensed, of course!
Give It a Spin
<script type="importmap">
{
"imports": {
"@symbiotejs/symbiote": "https://esm.run/@symbiotejs/symbiote"
}
}
</script>
<script type="module">
import Symbiote, { html, css } from '@symbiotejs/symbiote';
export class MyComponent extends Symbiote {
init$ = {
count: 0,
increment: () => {
this.$.count++;
},
}
}
MyComponent.template = html`
<h2>{{count}}</h2>
<button ${{onclick: 'increment'}}>Click me!</button>
`;
MyComponent.rootStyles = css`
my-component {
color: #f00;
}
`;
MyComponent.reg('my-component');
</script>
<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.
Want to Learn More?
npm Documentation Live Code Playground GitHub Community Discussions 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
25.01.2024
Symbiote VS Lit
David and Goliath: differences, pros and cons...
18.01.2024
Symbiote.js 2.x
The new major version is released. Let's see what's new...
RND-PRO.com © 2025