@michthemaker/vite-plugin-vanjs
v0.1.0
Published
The default Vite plugin for VanJS projects
Maintainers
Readme
VanJS
VanJS is a lightweight reactive UI framework that works directly with the real DOM.
- No Virtual DOM: VanJS binds state directly to real DOM nodes. When state changes, only the affected nodes update — no diffing, no reconciliation, no overhead.
- No Compiler: Write plain JavaScript or TypeScript. No JSX, no template syntax, no build-time magic. Your components are just functions that return DOM elements.
- Reactive by Default:
van.state()andvan.derive()give you fine-grained reactivity out of the box. Pass state directly to tags or derive computed values — updates propagate automatically. - Tiny by Design: The entire runtime fits in a few KB. No dependencies, no framework DSL, no abstractions you didn't ask for.
Documentation
Quick Start
npm create-van-appimport van from "@michthemaker/vanjs";
const { div, p, button } = van.tags;
const App = () => {
const count = van.state(0);
return div(
p(() => `Count: ${count.val}`),
button({ onclick: () => count.val++ }, "+")
);
};
van.add(document.body, App());Core Primitives
VanJS has four primitives. That's it.
import van from "@michthemaker/vanjs";
const { div, button, p } = van.tags; // create DOM elements
van.state(0); // reactive state
van.derive(() => count.val * 2); // computed values
van.add(document.body, App()); // mount to DOMReactive State
van.state(initialValue) creates a reactive state object. Reading .val inside a binding or derive tracks it as a dependency. Writing .val triggers updates.
const count = van.state(0);
count.val; // read — tracked as dependency
count.val = 5; // write — triggers reactive updates
count.oldVal; // previous value before last update
count.rawVal; // raw value, no dependency trackingvan.derive(fn) creates a computed value that re-runs automatically when its dependencies change.
const count = van.state(0);
const doubled = van.derive(() => count.val * 2);
count.val = 3;
doubled.val; // 6 — updated automaticallyReactive Lists
Arrays returned from bindings are handled as list bindings — efficient DOM updates for dynamic lists using start/end comment markers. Only changed nodes are updated, not the whole container.
const items = van.state(["apple", "banana", "cherry"]);
van.add(
document.body,
div(() => items.val.map((item) => p(item)))
);
// Add an item — only the new node is inserted
items.val = [...items.val, "date"];API Reference
| API | Description |
| --------------------------- | ------------------------------- |
| van.state(init) | Create reactive state |
| van.derive(fn) | Create a computed value |
| van.tags | Proxy for creating DOM elements |
| van.add(dom, ...children) | Mount children to a DOM element |
Examples
Here is a full counter example:
import van from "@michthemaker/vanjs";
const { div, h1, p, button } = van.tags;
const Counter = () => {
const count = van.state(0);
const doubled = van.derive(() => count.val * 2);
return div(
h1("Counter"),
p(() => `Count: ${count.val}`),
p(() => `Doubled: ${doubled.val}`),
button({ onclick: () => count.val++ }, "+"),
button({ onclick: () => count.val-- }, "-")
);
};
van.add(document.body, Counter());Contributing
Development happens in the open on GitHub. Bug fixes, improvements, and new ideas are welcome. Read the contributing guide to learn about the development process and how to propose changes.
Good First Issues
New to the codebase? Check out the good first issues label for bugs with limited scope — a great place to start.
License
VanJS is MIT licensed.
Acknowledgments
My Acknowledgments go to the original vanjs creators, I am only doing this because of their exceptional work.
