Nuedom is the component system at the heart of Nue. Rather than expressing UI as JavaScript functions that return virtual nodes, Nuedom treats components as extended HTML — familiar markup augmented with just enough syntax to handle dynamic data, user events, and conditional rendering. The result is components that look like HTML, because they are HTML.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nuejs/nue/llms.txt
Use this file to discover all available pages before exploring further.
How Nue components differ from React
The architectural difference is fundamental. React components are JavaScript functions. The JSX they return is transpiled toReact.createElement() calls, which build a virtual DOM tree that gets reconciled on each render. A simple form becomes a file full of hooks, refs, and effect handlers.
Nue components are HTML documents. The parser reads standard HTML extended with : prefixed attributes for event binding and { } expressions for data interpolation. There is no virtual DOM — Nue’s AST maps directly to DOM operations.
React form component
React form component
Nue form component
Nue form component
<dialog> with the Popover API for the success state, native form validation for the required fields, and a single method defined in an inline <script>. No hooks, no refs, no state variables.
Dynamic expressions
Data bindings use{ } curly-brace syntax inside text content and attribute values. Expressions are compiled to arrow functions that receive the component’s data object as _:
compileFn in compiler.js) transforms _.foo + 1 into _=>(_.foo + 1), making simple property references as concise as possible while supporting full JavaScript expressions:
Event listeners
Event binding uses:on prefixed attributes. The event name follows the colon — :onclick, :oninput, :onsubmit, :onchange. The value is a method name or inline expression:
(_,$e) => where _ is the component instance and $e is the DOM event. A method name like submit becomes (_,$e) => submit($e). An inline expression with semicolons becomes a block: (_,$e) => { expr1; expr2 }.
For input elements, you can bind directly to state without a method:
Conditional rendering
Use the:if, :else-if, and :else attributes to conditionally render elements:
Loops
The:for attribute iterates over arrays and objects. The value uses JavaScript destructuring syntax:
Composing components
Nue components reference each other by tag name. If a component file defines a<user-avatar> component and it is in scope (either in the same file or imported via a library file), you use it like any HTML element:
: binding syntax on the parent, and appear as plain data properties on the child.
Library files
A file is treated as a component library when theis_lib flag is set. This happens when the HTML file uses the <!dhtml lib> or html lib doctype declaration. Library components are loaded and shared across all pages that depend on them.
In asset.js, the components() method collects all library dependencies:
@shared/ so they are available to all applications in your project.
Server-side vs client-side rendering
Nue uses the doctype declaration to determine how a component file is rendered:Static HTML (server-side only)
A file with no special doctype or
<!html> is rendered entirely on the server. No JavaScript is sent to the browser. Use this for content components like headers, footers, and article layouts.Dynamic HTML (client-side)
A file with
<!dhtml> compiles to JavaScript and runs in the browser. The server renders a stub element; the client hydrates it with full interactivity.renderHTML function in page.js checks the is_dhtml flag from the parsed AST and routes to either renderNue (server rendering) or renderDHTML (client compilation with a server-rendered stub).
Library files (
is_lib: true) are skipped during direct rendering — they are only included as dependencies of page files that reference their components.