Fine-grained reactive JavaScript UI framework with no Virtual DOM
npm install @nayan-ghate/lumin๐ Lumin
A lightweight, fine-grained reactive JavaScript UI framework with no Virtual DOM, SSR, and diff-less hydration.
Lumin is a learning-driven framework built from scratch to deeply understand how modern UI frameworks work internally โ from reactivity to scheduling, rendering, SSR, hydration, and DevTools.
โจ Features
โก Fine-grained reactivity (signals & effects)
๐ซ No Virtual DOM
๐ง Deterministic updates
๐งต Microtask-based batching scheduler
๐งฉ Function-based components
๐งผ Automatic cleanup & lifecycle handling
๐งช DevTools introspection
๐ Server-Side Rendering (SSR)
๐ง Diff-less hydration
๐งฑ JSX support (compile-time)
๐ฆ Project Structure
Lumin/
โโ packages/
โ โโ core/ # signals, effects
โ โโ scheduler/ # batching system
โ โโ renderer/ # DOM renderer, components, hydrate
โ โโ ssr/ # renderToString
โ โโ devtools/ # debugging hooks
โ โโ lumin/ # public framework API
โ
โโ examples/
โ โโ app.jsx
โ โโ app.js
โ โโ jsx.html
โ โโ ssr.js
โ โโ hydrate.html
โ
โโ docs/
โโ test-core.js
โโ .babelrc
โโ package.json
๐ Quick Start (Client Rendering)
import { signal } from "./packages/core/index.js"
import { component } from "./packages/renderer/index.js"
import { render } from "./packages/lumin/index.js"
const Counter = component(() => {
const count = signal(0)
return (
)
})
render(Counter, "#app")
๐ง Core Concepts
Signals
const count = signal(0)
count() // read
count(10) // write
Signals track dependencies automatically and notify only what depends on them.
Effects
effect(() => {
console.log(count())
})
Runs once initially
Re-runs only when dependencies change
Supports cleanup
๐งต Scheduler (Batching)
Multiple updates in the same tick are batched:
count(1)
count(2)
count(3)
// effect runs once with value = 3
Implemented using microtasks, not timeouts.
๐งฉ Components
Components are plain functions:
const Hello = component(() => {
return