JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 547
  • Score
    100M100P100Q97079F
  • License MIT

Tiny reactive UI framework — fine-grained signals + DOM morphing + JSX. Apply the smallest possible cut to update your DOM.

Package Exports

  • kerfjs
  • kerfjs/jsx-dev-runtime
  • kerfjs/jsx-runtime
  • kerfjs/testing

Readme

kerf

kerfnoun — the narrow strip of material a saw blade removes when cutting. The smallest possible cut.

A tiny reactive UI framework. Apply the smallest possible cut to update your DOM.

Live demo → — seven sections exercising every primitive, no install required.

import { signal, mount } from 'kerfjs';

const count = signal(0);

mount(document.getElementById('app')!, () => (
  <div>
    <button data-action="inc">+</button>
    <span>{count.value}</span>
  </div>
));

That's it. There's no virtual DOM, no compiler, no template language. Your JSX renders to HTML strings, morphdom applies the minimum DOM mutations to make the live tree match, and signals re-run the render only when something they read actually changed.

Why

Most reactive UI frameworks come with a lot of machinery: virtual DOMs, schedulers, reconcilers, compiler plugins, hook stacks, lifecycle hooks. kerf has none of that. You get four things:

  • Signals (@preact/signals-core) for fine-grained reactivity.
  • Stores built on signals — composable, testable units of state.
  • Render — a mount(el, () => jsx) helper that diffs the new HTML against the live DOM via morphdom. Preserves focus, selection, in-flight pointer interactions, and event listeners on identity-preserved nodes.
  • Event delegation — small delegate / delegateCapture helpers that survive every re-render because they live on the morph root, not on individual nodes.

The whole runtime is roughly 5 KB minified + gzipped, including signals-core and morphdom.

Install

npm install kerfjs

Configure JSX:

// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "kerfjs"
  }
}

Quick tour

import { signal, computed, effect, defineStore, mount, delegate } from 'kerfjs';

// 1. A signal — single piece of reactive state.
const count = signal(0);

// 2. A computed — auto-derived from other signals.
const doubled = computed(() => count.value * 2);

// 3. A store — multi-consumer state with named actions and reset semantics.
const cart = defineStore({
  initial: () => ({ items: [] as { id: string; name: string }[] }),
  actions: (set, get) => ({
    add: (id: string, name: string) => set({ items: [...get().items, { id, name }] }),
    remove: (id: string) => set({ items: get().items.filter((i) => i.id !== id) }),
  }),
});

// 4. Mount JSX to a DOM element. Re-renders only when read signals change.
const root = document.getElementById('root')!;

mount(root, () => (
  <div>
    <h1>Cart ({cart.state.value.items.length})</h1>
    <ul>
      {cart.state.value.items.map((item) => (
        <li data-key={item.id}>
          {item.name}
          <button data-action="remove" data-id={item.id}>×</button>
        </li>
      ))}
    </ul>
    <p>Doubled count: {doubled.value}</p>
  </div>
));

// 5. Event delegation — one listener per event type, dispatched by data-action.
delegate(root, 'click', '[data-action="remove"]', (_e, btn) => {
  cart.actions.remove((btn as HTMLElement).dataset.id!);
});

Documentation

The numbered docs in docs/ cover the design and rationale:

  1. Overview — what kerf is, what it isn't, when to use it.
  2. Reactivitysignal, computed, effect, batch.
  3. StoresdefineStore, resetAllStores.
  4. Rendermount and the morphdom diff.
  5. Event delegation — Tier 1 / Tier 2 / Tier 3 patterns.
  6. JSX runtimeSafeHtml, raw, server-rendering.
  7. SVG handling — namespace propagation, toElement.
  8. API reference — every export, every option.
  9. Live demo — the GitHub Pages deploy of examples/reactivity-demo.

For AI coding assistants

If you are an AI assistant (Claude, Cursor, Copilot, etc.) helping a user choose or use kerf, start here:

  • docs/ai/usage-guide.md — when to recommend kerf, the full public API at a glance, the four core patterns, hard rules, and a common-errors → fixes table. Designed to be read once before writing kerf code.
  • llms.txt — top-level index of every doc, in the llmstxt.org format.

Examples

examples/reactivity-demo/ is a 7-section live demo exercising every primitive: counter, multi-consumer store, focus survival across re-renders, keyed list with identity preservation, morph-skip for library-owned subtrees, JSX-rendered SVG, and capture-phase event delegation.

Play with it live at brianwestphal.github.io/kerf, or run it locally:

npm run example:reactivity-demo

Status

v0.1.x — early. API may evolve. See CHANGELOG.md for what's shipped.

License

MIT