A simple, explicit DOM library for building reactive user interfaces.
Build reactive UIs without the magic. Just functions, plain JavaScript objects, and explicit update()
calls. No virtual DOM, no complex state management required.
import 'nuclo';
let count = 0;
const counter = div(
h1(() => `Count: ${count}`),
button('Increment', on('click', () => {
count++;
update();
}))
);
render(counter, document.body);
You control when updates happen with a simple update()
call. No surprises, no magic.
Work directly with the DOM. No virtual layer, maximum efficiency.
Minimal bundle size means faster load times and better performance.
Natural API with global functions for all HTML and SVG elements.
Full type definitions for all 140+ HTML and SVG tags out of the box.
Only updates what changed, nothing more. Maximum efficiency.
npm install nuclo
Simply import once to register all global functions:
import 'nuclo';
// Now use div(), update(), on(), list(), when(), render(), etc. globally
let count = 0;
const app = div(
h1(() => `Count: ${count}`),
button('Click', on('click', () => { count++; update(); }))
);
render(app, document.body);
Add to your tsconfig.json
:
{
"compilerOptions": {
"types": ["nuclo/types"]
}
}
Or in your vite-env.d.ts
:
/// <reference types="nuclo/types" />
nuclo doesn't auto-detect changes. You call update()
when ready:
let name = 'World';
// Mutate freely
name = 'Alice';
name = name.toUpperCase();
// Update once when ready
update();
update()
to trace all state changesZero-arg functions become reactive:
let count = 0;
div(
() => `Count: ${count}`, // Updates when update() is called
{ title: () => `Current: ${count}` } // Attributes too
)
First matching condition wins:
when(() => user.isAdmin,
div('Admin Panel')
).when(() => user.isLoggedIn,
div('User Dashboard')
).else(
div('Please log in')
)
Lists use object identity to track items:
list(() => items, (item, index) =>
div(() => `${index}: ${item.name}`)
)