Skip to content

Reactive UI,
no re-renders.

A Qwrk component runs once and returns real DOM. When a state changes, only the text or attribute that reads it is updated.

npm create qwrk-app@latest

Qwrk 0.4 is in beta: npm i qwrk@next qwrk-vite@next Try the beta

Counter.tsx
import { state } from "qwrk";function Counter() {  const count = state(0);  return (    <button onClick={() => count.value++}>      clicked {count} times    </button>  );}
localhost:5173

Features

Under the hood.

A small runtime keeps track of state. The compiler turns your JSX into plain DOM code at build time.

Updates touch one node

Changing a state re-runs the bindings that read it. If one text node shows count, that text node is all that changes.

As low as 2.9 KB

A counter app, runtime included, is 2.9 KB gzipped when built with esbuild and the Qwrk plugin.

Components run once

A component is a function that returns DOM nodes. Qwrk calls it once, and bindings handle every change after that.

JSX becomes templates

The compiler turns static JSX into a <template> and copies it with cloneNode(true). Only the dynamic parts get a binding.

Batched writes

Wrap several writes in batch() and derives, the DOM and effects update once, after the last write.

Keyed lists

Render lists with .map(). Rows are keyed by item, so a sort moves the existing DOM nodes instead of rebuilding them.

TypeScript, Vite, esbuild

Types ship with the package. There are plugins for Vite and esbuild, and .svg files import as components.

Create an app.

create-qwrk-app sets up a Vite project with the compiler configured. Pick JavaScript or TypeScript, then run the commands it prints.

$ npm create qwrk-app@latest my-app$ cd my-app$ npm install$ npm run dev   ➜  Local:   http://localhost:5173/