I'm a big fan of Lit and Shoelace (I've even donated to Shoelace — seriously, go check it out if you haven't — and consider donating to them, I have). They just didn't cover everything I needed for my projects, so I started building my own.
What started as a handful of components turned into Snice — a web component framework and a library of 130+ components built with it. The framework handles rendering, reactivity, styling, event handling, and routing — but everything is modular. You pick what you need. Just want the components? Use those by themselves. Just want the rendering engine? Go for it. Don't need routing? Don't import it. The components are what I built on top of it for my own projects.
Both are free, MIT licensed, no commercial agenda. Just sharing what I needed.
The framework
Snice is built on TC39 standard decorators — the ones actually shipping in TypeScript 5.0+ and browsers, not the legacy experimental ones. Components extend HTMLElement directly, no base class required.
import { element, property, render, styles, html, css } from 'snice';
@element('user-card')
class UserCard extends HTMLElement {
@property() name = '';
@property() role = '';
@render()
template() {
return html`
<div class="card">
<h3>${this.name}</h3>
<span>${this.role}</span>
</div>
`;
}
@styles()
css() {
return css`:host { display: block; padding: 1rem; }`;
}
}
The @render decorator sets up differential rendering — it patches only the DOM nodes that actually changed. No virtual DOM.
The full decorator API:
-
@element('tag-name')— registers a custom element -
@property()— reactive properties synced with HTML attributes -
@render()— differential rendering withhtmltagged templates -
@styles()— scoped CSS via Shadow DOM -
@on('click', '.btn')— declarative event handling -
@request/@respond— async generator-based component communication -
@context— router-aware context sharing
For full apps, there's built-in hash/pushstate routing with @page, @layout, and @controller decorators. No external router needed.
The components
130+ components built with the framework above. The range goes from everyday UI (buttons, inputs, modals, tabs) to things you'd normally need separate libraries for (data tables, charts, kanban boards, a terminal emulator).
Here's the bird's eye view:
Every component supports light and dark mode, CSS custom property theming, and works as a single HTML element — no framework required.
Categories
Everyday UI: Button, input, select, checkbox, radio, switch, slider, tabs, accordion, modal, drawer, toast, tooltip, popover, badge, avatar, breadcrumbs, pagination, stepper, skeleton...
Data visualization: Charts, sparklines, gauges, heatmaps, treemaps, candlestick, sankey, waterfall
Project tools: Gantt charts, kanban boards, timelines, approval flows, activity feeds
Rich data: Spreadsheets, data tables with sorting/filtering/pagination, org charts
Media: Music player, video player, camera, audio recorder, PDF viewer
Utilities: QR code generator/reader, color picker, terminal emulator, markdown renderer, code block with syntax highlighting
Use it anywhere
Use the framework to build your own components, use the pre-built ones, or both. Each piece stands on its own — there's no all-or-nothing buy-in.
Drop a script tag — no bundler needed:
<script src="https://cdn.snice.dev/runtime/snice-runtime.min.js"></script>
<script src="https://cdn.snice.dev/components/snice-button.min.js"></script>
<snice-button variant="primary">Click me</snice-button>
Or install via npm:
npm install snice
Works with React, Vue, Angular, Svelte, Astro, plain HTML — anything that renders to the DOM.
There's no paid tier, no pro plan, no upsell. I built these for my own projects and I'm sharing them because the web component ecosystem can always use more options.
I'd love to hear what you think — what's useful, what's missing, what could be better. Keep it constructive.

Top comments (0)