Skip to content

amritk/mini

Repository files navigation

mini

A deliberately tiny signals UI runtime. Real nodes, created once, mutated forever by signals — no virtual DOM, no diffing, no re-render.

status  license  deps  vibe coded


What is mini?

A UI runtime small enough to read in an afternoon, built on alien-signals. It ships in two shapes:

Package What it renders to
@amritk/mini The DOM. Reactive bindings, keyed lists, static-template cloning, and a compilerless JSX runtime.
@amritk/mini-native Whatever a pluggable Host puts in front of it — a native view tree (Lynx), the DOM as a preview target, or plain objects.

Both are compilerless: there is no custom build step, just the standard react-jsx transform pointed at the package's own runtime.

The one idea

JSX builds a real node once. Signals mutate it forever. Nothing diffs.

const Counter = () => {
  const count = signal(0)
  return (
    <button onclick={() => count(count() + 1)}>
      {() => `clicked ${count()} times`}
    </button>
  )
}

The component function runs a single time. The <button> is created once and never rebuilt; only the text node inside it is ever written to again.

The reactivity rule

Nothing analyses your expressions, so reactivity is decided by value shape at runtime:

  • A function-valued attribute, child, or show is reactive.
  • Any other value is static — applied once, never again.

Signals are zero-argument functions, so passing one without calling it is already a live binding:

<button disabled={streaming}>      {/* reactive — tracks forever    */}
<button disabled={streaming()}>    {/* STATIC — frozen at creation! */}

That second line is the one real footgun, so it is guarded three ways: live in the editor and dev server through @amritk/mini/vite, in this repo's CI through bun run check:reactivity, and in your own CI through the same plugin.

The cap is the design

There is no virtual DOM, no diffing, and no re-render — and that is a commitment, not a roadmap item. It buys two things:

  • The . entry stays tiny and flat. Every feature only some apps need lives on its own subpath with its own module graph, so importing /router pulls in none of /forms. A size-budget test and an import-boundary test hold that line in CI, per package.
  • Porting is one file. The hard part of a React-style native framework is the reconciler; there is none here to port. A new target for @amritk/mini-native means implementing one Host — about 15 functions — and nothing else.

If a feature seems to be missing, the correct next step is usually a bigger framework (Preact, Solid), not a new helper here.

Quick start

npm install @amritk/mini
# or: pnpm add / yarn add / bun add
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@amritk/mini"
  }
}
import { mount, signal } from '@amritk/mini'

mount(document.body, Counter)

Full API, subpath modules, and the native runtime's host contract are in the package READMEs:

  • @amritk/mini — DOM bindings, list, template, and the /router /flow /forms /query /hot /vite subpaths.
  • @amritk/mini-native — the Host contract, the native element vocabulary, and the three shipped hosts.

For AI agents & LLMs

Each package ships an AI.md next to its README.md: a mental model, a minimal runnable example, and the gotchas most likely to trip up a model. The repo root carries llms.txt (a curated index, per llmstxt.org) and llms-full.txt (every AI.md inlined, for pasting into context).

Editing the repo rather than consuming it? Start at AGENTS.md, then the per-package AGENTS.md for the invariants that package cannot break.

Requirements

  • Consumers: any ES2022 runtime. @amritk/mini needs a DOM; @amritk/mini-native needs only a host.
  • Development: Bun ≥ 1.1.

Development

bun install
bun run test                # every package's tests
bun run check               # biome lint + format
bun run check:reactivity    # the called-signal footgun guard
bun run types:check         # both packages, both of mini-native's passes
bun run build               # build both packages
bun run test:dist           # load and drive the built artifacts (needs a build)

See CONTRIBUTING.md for the full workflow, and .claude/architecture.md for how the two packages relate.

Pre-alpha. Breaking changes can land in any 0.x release; they ride a minor bump.

Related

@amritk/mini/forms can validate against a JSON Schema through @amritk/runtime-validators, an optional peer published from the mjst repo, where both packages used to live.

License

MIT

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages