# Nuclo > Nuclo is a lightweight, zero-dependency, type-safe DOM library for JavaScript and TypeScript. You build the UI with global tag-builder functions such as `div()` and `button()`, keep state in plain mutable variables, and call `update()` to sync the real DOM. There is no virtual DOM, no compiler, no proxies, no signals and no automatic change tracking. It ships server-side rendering with hydration and a typed atomic CSS-in-TS engine. MIT licensed. Nuclo is not React, Vue, Solid or Svelte. There are no hooks, no JSX, no components API, no reactive primitives and no effects. A component is a plain function that returns a builder. Nothing on the page changes until code calls `update()`. ## Core rules - Install with `npm install nuclo`, or scaffold a Vite + TypeScript app with `npm create nuclo@latest`. - `import 'nuclo'` once, before any code that calls a builder. It registers globals: 175 tag builders (`div`, `span`, ..., `var_` for ``; SVG tags use an `Svg` suffix: `svgSvg`, `pathSvg`, `circleSvg`) and 14 helpers: `update`, `scope`, `when`, `list`, `on`, `render`, `hydrate`, `forceUpdate`, `css`, `cx`, `createCss`, `variants`, `keyframes`, `globalStyle`. - Tag builders are globals only: `import { div } from 'nuclo'` does not work. Helpers are also named exports. - A function with zero parameters is a dynamic value, re-run on every `update()`: ``p(() => `Hi ${name}`)``, `{ disabled: () => busy }`. A function that declares a parameter is a modifier that receives the element and runs once. - Mutate state directly (`count++`, `todos.push(t)`), then call `update()` once. `update('id')` only updates elements marked with `scope('id')`. - Conditionals: `when(() => cond, ...children).when(...).else(...)`. Never `cond && el`: booleans render as the text "false". - Lists: `list(() => items, (item, index) => li(...))`. Rows are matched by object identity and kept rows are not rendered again, so use dynamic values for fields that change. - Events: `{ onClick: (e) => ... }` in an attribute object, or `on('click', fn, options)` for several listeners, listener options or custom events. - Lifecycle: `{ onMount: (el) => cleanup?, onDestroy: (el) => ... }`. Hooks run once per element and are not effects. - Classes: use `className` (or a `css()` result), not `class`. Inline `style` takes a camelCase object with explicit units. - Mount with `render(App, root)`: pass the component, not `App()`. Render into an element that is in the document; detached nodes stop updating. - SSR: `import 'nuclo/polyfill'` then `import 'nuclo'` on the server, call `renderToString(App)` and put `getCssText()` in `