Skip to content

Latest commit

 

History

1,904 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ivue — Infinite Vue

Plain classes. Full reactivity.
Infinite scalability. One kilobyte.

npm version npm downloads build status 100% test coverage 1.1 kB gzipped MIT license

Docs · Getting Started · The Standard · Examples · Benchmarks · Blog · Community


ivue builds Vue 3 reactivity out of plain TypeScript classes. Real inheritance, real encapsulation, real polymorphism — on ordinary objects, with nothing paid until first access. The whole engine is 1.1 kB gzipped with zero dependencies.

npm i ivue vue
import { Reactive } from 'ivue';
import { ref } from 'vue';

class $Counter {
  get count() {
    return ref(0)
  }
  get double() {
    return this.count.value * 2 // plain getter — derives on read
  }
  increment() {
    this.count.value++
  }
}

export namespace Counter {
  export const $Class = $Counter; // raw — children `extends` this
  export let Class = Reactive($Class); // reactive — you `new` this
  export type Instance = typeof Class.Instance; // the unwrapping-surface type
}
<script setup lang="ts">
import { Counter } from './Counter';

const counter = new Counter.Class();

// the state destructure — every Ref the template touches, unwrapped uniformly
const { count } = counter;
</script>

<template>
  <button @click="counter.increment()">{{ count }} · double {{ counter.double }}</button>
</template>

Full walkthrough: Getting Started.

Built for humans and AI

ivue ships with a Standard Operating Manual — the complete authoring standard as annotated templates, rules, and a review checklist. It reads as documentation and works as a drop-in skill for AI coding agents, so generated code follows the same standard your team writes:

npx ivue skill        # installs .claude/skills/ivue/SKILL.md, version-locked
npx ivue skill --all  # + Codex/Cursor/Copilot where already in use

Agents holding the Standard have derived correct patterns its own author never wrote — the manual is a generator, not a catalog. The wider argument: Reactive framework for the AI era.

Why classes, why now

  • Native class API — extends, super, getters, setters, private fields. Real inheritance, encapsulation and polymorphism, all reactive.
  • Zero-cost creation — instances are plain objects. A million of them take 22 ms — 6 to 132× faster than the alternatives.
  • One kilobyte — 1.1 kB gzipped, zero dependencies, 100% test coverage. Stripped to the load-bearing core — an API you can hold in your head.
  • Store or ViewModel — the same class serves as a global store, a component ViewModel, or a domain model. One mental model everywhere.
  • Composition API, fully compatible — composables plug in through $-getters. The entire Vue ecosystem works inside your classes.
  • TypeScript first — writable ref-getters, fully typed instances, precise inference. The type system shaped the engine's design.

One idea, carried through

Reactive() transforms a class once. A getter returning ref() becomes state: created on first touch, cached, stable forever. A plain getter stays plain and re-derives on every read — reactive with zero allocation. Methods bind themselves once, to the right this. Instances stay ordinary objects: no proxy wraps them, no work happens at construction.

Inheritance, teardown, development parity, speed — consequences of that one move. And composables plug straight in:

import { useMouse } from '@vueuse/core';

class $Pointer {
  private get $mouse() {
    return useMouse() // created once, encapsulated
  }
  get x() {
    return this.$mouse.x
  }
  get y() {
    return this.$mouse.y
  }
}

Hard problems, solved together

Each of these sank earlier class-reactivity attempts. ivue ships all of them as one coherent design:

  • Bound methods — this.method is always correct, always the same reference.
  • Reactive inheritance — deep super.x.value chains resolve level-safe.
  • Development parity — the same class identity, direct binding, and engine branches in development and production.
  • Circular import immunity — the namespace pattern resolves mutual references in any load order.
  • Writable getter types — ref-returning getters type as writable; instances fully inferred.
  • Deterministic teardown — $watch scopes per instance, $stopEffects() cleans up.
  • Minimal memory footprint — derivations are shared prototype getters, not per-instance allocations.
  • Hot paths — reads hoist to native ref speed with one line where it matters.

Static() — capability classes (ivue/extras, +0.5 kB)

The same discipline for the class-level surface: Static() makes static methods lazy-bound and $-prefixed static getters cached per receiver — a lazy singleton, an inheritance-aware store, an override seam, and a test boundary in one declaration. It retires module-level state outright, and it has no Vue dependency — the identical idiom runs under Node and Bun:

import { Static } from 'ivue/extras';

class $TextSegmentation {
  protected static get $segmenter() {
    return new Intl.Segmenter(undefined, { granularity: 'grapheme' });
  }
}

export namespace TextSegmentation {
  export const $Class = Static($TextSegmentation); // anchor — children extend this
  export let Class = $Class;
}

Proven at scale

Invar — a terminal IDE built on ivue

Invar is ivue at full scale: a complete terminal IDE — editor, workspace search, git, terminals, LSP, agents — running on ivue classes under Bun, with no DOM and no Vue components. 108,000 source lines, 384 classes, 39 invariant contracts, zero import cycles, built almost entirely by AI agents holding the Standard as their base discipline.

And at the other end of scale on the web: a 1,000,000-row virtual scroller, a 20,000,000-cell flyweight grid at 4.7 bytes per live cell, and production-grade Quasar field components — all with full source on the page.

The numbers

Measured, not promised — every number carries its method, and the load-bearing benchmarks run live in your browser on the shipped engine:

creating 1,000,000 instances time ivue is
ivue new Class() 21.7 ms the baseline
composable factory 139 ms 6.4× faster
native reactive() 470 ms 22× faster
memory heap at 100,000 live instances per instance 100k total
ivue class, 30 getters 3.7 KB 364 MB
composable, 30 closures 8.0 KB 781 MB
reactive(), fields + getters 10.4 KB 1.02 GB
composable, 30 computeds 19.7 KB 1.93 GB

Taken all the way down: a fully reactive spreadsheet model holding 20,000,000 live cells at 4.7 bytes each — 8.5× below the plain-object floor — because in ivue, everything costs proportional to what's observed, nothing costs proportional to what exists.

Go deeper

Community

Questions, ideas, bug reports — there's no ticket queue, just the people who write the code: Discussions · Issues · Discord · X @evgenykalash · Community page

A note on the size

The complete engine is 1.1 kB gzipped: lazy prototype transformation, bound methods, inheritance, lifecycle ownership, and the public utilities. Development uses that same engine without a second hot-update execution path.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. — Antoine de Saint-Exupéry

License

MIT

Releases

Packages

Used by

Contributors

Languages