Skip to content

Getting started

Here’s the entire development loop — write a component, run the dev server, click around, edit, see it update — in forty seconds:

Animated coding session: a counter component is typed line by line into an editor, npm run dev starts in a terminal and the localhost link is clicked, the running app is clicked in a browser, then back in the editor a computed class is added — selecting "btn" and typing a bound {cls} hole — and the browser shows the button change color at the fifth click

Everything in that session is the whole story: plain TypeScript + JSX, your existing dev server (Vite here — anything that does JSX works), and a browser. No framework CLI, no compiler plugin, no devtools extension required.

Terminal window
npm install kerfjs

Point your tsconfig.json at kerf’s JSX runtime:

{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "kerfjs"
}
}

And write the counter from the animation:

import { signal, mount, delegate } from 'kerfjs';
const count = signal(0);
const root = document.getElementById('app')!;
mount(root, () => (
<button class="btn" data-action="inc">
Clicked {count} times
</button>
));
delegate(root, 'click', '[data-action="inc"]', () => count.value++);

Three things to notice, because they’re the whole mental model:

  • {count} is the signal itself, not count.value. That makes it a bound hole — a click updates that one text node directly, with no render re-run. Values bind; structure re-renders. (The edit in the animation does the same for an attribute: class={cls} binds a computed that flips the button’s look at the fifth click.)
  • mount() re-runs the render only when a signal it read changes. This render reads nothing, so it runs exactly once.
  • delegate() is one listener on the root, dispatched by selector — no per-element handlers, nothing to unbind when the DOM changes.
  • Overview — what kerf is, the architecture in one diagram.
  • Reactivity — signals, computeds, effects, and fine-grained bindings.
  • Examples — seven complete apps, from TodoMVC to a no-build poll served as raw source.
  • Coming from another framework? — side-by-side translations from React, Vue, Svelte, and more.

Prefer no build step at all? The html tagged template gives you identical semantics from a plain <script type="module"> — see the live-poll example, whose running source is exactly what its author wrote.