Solarite: no build, no signals, just simplicity
Solarite is a small library for writing native web components. Write a class, change your data, and call `render()`. Solarite updates only the DOM that changed.
import h, {Solarite} from './dist/Solarite.min.js';
class ShoppingList extends Solarite {
items = [
{name: 'Apples'},
{name: 'Bananas'},
{name: 'Carrots'}];
add() {
this.items.push({name: ''});
this.render();
}
render() {
h(this)`
<shopping-list oninput=${this.render}>
<h3>Today’s essentials</h3>
${this.items.map(item => h`
<label>
<input type="checkbox" checked=${[item, 'done']}>
<input value=${[item, 'name']}>
</label>`
)}
<button onclick=${this.add}>+ Add an item</button>
<pre>${JSON.stringify(this.items)}</pre>
</shopping-list>`;
}
}
document.body.append(new ShoppingList());
What it does
Plain data, explicit render
Nothing to declare or wrap. Change an object or an array, then render.
``` this.items.push(newItem); this.render(); ``` Explicit rendering
Two-way binding
Set an input's value to `[object, 'property']` and the two stay in sync.
`<input value=${[item, 'name']}>`Two-way binding
Scoped CSS, no shadow DOM
A component's `<style>` applies only to it, and page styles still reach inside.
``` <style> :host input { color: navy } </style> ``` Scoped styles
Objects as attributes
A child component's constructor receives the actual object, not a string.
``` <user-card user=${user}>
constructor({user}) { … } ``` Child components
Direct DOM access
`data-id` elements become properties. Your DOM edits are kept.
``` <div data-id="chart"></div>
this.chart.append(canvas); ``` Element references
No proxies
Objects are never wrapped, so `console.log` shows your real data.
``` console.log(this.items); // [{name: 'Apples'}, …] ``` How rendering works
Standard custom elements
They work in plain HTML pages and inside other frameworks.
``` <my-timer mins="5"></my-timer>
constructor(args={}) {...} ``` Web components
Optional JSX and TypeScript
Type definitions are included. JSX needs a build step; nothing else does.
``` // tsconfig.json "jsx": "react-jsx", "jsxImportSource": "solarite" ``` JSX
Size and speed
Solarite scores 1.08 in the js-framework-benchmark, where hand-written vanilla JavaScript scores 1.02. This is faster than nearly every other framework.
**12.7 KB**
Minified + Brotli
**Zero**
Runtime dependencies
1. Vanilla JS hand-written, no library**1.02** 2. Mikado 0.8.400**1.06** 3. Solarite 0.8.0**1.08** 4. Solid 1.9.3**1.13** 5. Inferno 8.2.2**1.14** 6. Svelte 5.42.1**1.17** 7. Lit 3.2.0**1.30** 8. Vue 3.5.39**1.32** 9. Angular CF, no Zone · 22.0.0**1.55** 10. React hooks · 19.2.0**1.58** 11. Preact hooks · 10.29.8**1.59** 12. Ember 7.3.0-alpha.5**2.06** 13. Alpine 3.14.7**3.07**
Select entries from the Sep 21, 2026 Krausest JS Framework Benchmark, **smaller is better.**
Solarite Is Not:
A framework
It renders components. Routing, fetching, and stores are yours to choose, or to skip.
Server-side rendering
Could be added later if there's demand.
Automatic
If you change data and don't call `render()`, the page doesn't update. That's the price of choosing when rendering happens.
1.0 yet
Possible API changes before 1.0.
A big team
One maintainer, MIT licensed, with a small surface that is easy to read and to fork.
Why I wrote it
Several years ago I went looking for something simpler than the big JavaScript UI frameworks. I didn't want a build environment or a wait for compilation, and I didn't want to wrap my data in signals before I could use it. What I wanted was class-based components that pass arguments to their children through the constructor, scoped styles and two-way binding without the limits of shadow DOM, and a library I could import anywhere rather than a whole framework. Nothing I found did all of that, so I wrote Solarite.
-- Eric Frost
Install
`import h, {Solarite} from 'https://cdn.jsdelivr.net/npm/solarite@0.9.0/dist/Solarite.min.js';`
The examples in the documentation are live, so you can edit them right in the page.