A simple reactivity system for web components

Build lightweight custom elements that browsers & you understand.


  • A robust API for synchronizing your component's UI and properties
  • ~1 kB base class (minified, compressed) with versatile utilities
  • Sensible life-cycle hooks that you understand and remember
  • Use the built-in JSX-like syntax or bring your own custom templating
  • Attach 'side effects' that gets triggered on property value changes

Why use this base class?

Often times, when simple websites need a quick custom element, the best way is still to create one extending from HTMLElement. However, it can quickly reach a point where writing the code from scratch can seem confusing and hard to maintain especially when compared to other projects with more advanced setups.

Also, when coming from frameworks with an easy declarative coding experience (using templates), the default imperative way (e.g., creating instances of elements, manually attaching event handlers, and other DOM manipulations) is a frequent pain point we see.

This project aims to address these with virtually zero tooling required and thin abstractions from vanilla custom element APIs – giving you only the bare minimum code to be productive.

It works on current-day browsers without needing compilers, transpilers, or polyfills.

Here's an interactive custom element:

import { WebComponent, html } from "https://esm.sh/web-component-base";

export class Counter extends WebComponent {
  static props = {
    count: 0
  get template() {
    return html`
      <button onClick=${() => ++this.props.count}>

customElements.define("my-counter", Counter);