nuicpp/nui/nui-cpp
Claude Code and agent skill by nuicpp/nui
- community
Checking that the SKILL.md file is still in the repository.
Expert guidance for writing frontend code using NuiCpp -- a C++ WebAssembly (WASM) frontend library compiled via Emscripten. Conceptually similar to JSX but expressed entirely in C++. Use this skill whenever the user asks to build UI components, pages, or applications using NuiCpp, Nui, or "C++ frontend/WASM UI". Also trigger when the user mentions Nui::Observed, Nui::range, ElementRenderer, Nui::Elements, Nui::Attributes, StateTransformer, ChangePolicy, ValWrapper, convertToVal, convertFromVal, or any other Nui:: namespace identifiers. Trigger even for partial tasks like "add a button to my Nui component", "how do I handle events in Nui", or "write a function component". This skill covers element syntax, reactive state, range rendering, class components (functor + pimpl), function components, StateTransformer, nil/fragment, WebAPI event wrappers, val conversion, JS interop via emscripten::val, and reactive side-effects via listen/smartListen/ListenRemover.
Install
npx vskill@latest install nuicpp/nui/nui-cppSKILL.md
NuiCpp Frontend Skill
NuiCpp is a C++ WASM frontend library (Emscripten). Think of it as JSX-in-C++: you build DOM trees using a C++ DSEL (domain-specific embedded language). Always apply the patterns below precisely -- the syntax is strict and deviations cause compile errors.
Element Syntax
Key rules:
- Children go inside
()after the{}attribute block. Always include()even if empty. - Mix text with other children using
text{"..."}(), not raw string literals alongside elements. - Supported named event wrappers:
Nui::WebApi::MouseEvent,Nui::WebApi::Event,
Nui::WebApi::KeyboardEvent, Nui::WebApi::DragEvent.
Reactive State -- Nui::Observed
Mutation semantics
| Intent | Syntax | Effect | |
|---|---|---|---|
| Mutate + track change | items.push_back("x") | Queues UI update | |
| Mutate silently | items.value().push_back("x") | No UI update | |
| Full invalidation | items.modify() | Full range redraw |
Use .modify() when changing 50% or more of a vector's elements.
Flushing updates
Changes are queued, not applied immediately.
- Inside event handlers -- flushed automatically at handler end.
- Outside event handlers (timers, async, mousemove) -- call manually:
``cpp Nui::globalEventContext.executeActiveEventsImmediately(); ``
Do not copy Nui::Observed into temporaries when mutating -- always mutate the original.
Listening to Observed Changes -- listen / smartListen
Use listen / smartListen to run imperative side-effects whenever an Observed value changes (logging, fetching, cascading state updates, etc.). This is separate from the declarative UI bindings in the section below.
listen -- raw event registration
Returns an EventRegistry::EventIdType. You are responsible for removing the event manually.
Warning: Do not mutate any Observed from inside a listen callback -- this causes infinite recursion. Use smartListen instead.
smartListen -- RAII + safe side-effects
Returns a ListenRemover that automatically deregisters the listener on destruction. The callback is delayed until after all currently-active events have finished, so it is safe to mutate other Observed values inside the callback.
ListenRemover is move-only (no copy). Store it as a member in the component that owns the side-effect:
smartListen with shared_ptr<Observed>
When the observed value is heap-allocated and may be destroyed independently:
Manual cleanup with ListenRemover
Quick reference
| API | Returns | Safe to mutate Observed? | Lifetime managed by | |
|---|---|---|---|---|
Nui::listen(obs, fn) | EventIdType | ❌ causes recursion | caller | |
Nui::smartListen(obs, fn) | ListenRemover (nodiscard) | ✅ delayed execution | ListenRemover RAII |
Using Observed in the UI
Reactive attribute
Reactive style
Reactive text content
Reactive subtree (Nui::observe + renderer)
Must be the only logical child of its parent:
Range Rendering
Nui::range must be the first (and only) logical child of its parent element, paired immediately with its renderer lambda.
Simple range
Range with before/after siblings
Use .before() / .after() instead of placing elements outside the range:
nil -- Rendering Nothing
Nui::nil() produces an ElementRenderer that inserts nothing into the DOM. Use it to conditionally render nothing in places that syntactically require a child expression.
fragment -- Wrapper-free Multi-child Rendering
Nui::Elements::fragment(...) renders multiple children into a parent without adding an enclosing DOM node, similar to React fragments.
Important limitation: Do not use fragments with observed/reactive logic. Because fragments are removed and reinserted as a unit on change, and the rerender is deferred, their contents end up appended to the back of the parent rather than staying in place. Keep fragments to simple, static structural groupings only.
WebAPI Event Wrappers
All typed event classes (MouseEvent, KeyboardEvent, etc.) extend Nui::ValWrapper, which is a lightweight, non-owning view over a Nui::val. Construction is cheap -- no data is copied; all property accessors read directly from the underlying JS object.
Using MouseEvent
Available MouseEvent properties
clientX/Y, x/y, screenX/Y, pageX/Y, offsetX/Y, movementX/Y, button, buttons, altKey, ctrlKey, shiftKey, metaKey, relatedTarget.
Other event types
| Header | Type | Typical use | |
|---|---|---|---|
nui/frontend/api/event.hpp | Nui::WebApi::Event | onChange, onInput, generic | |
nui/frontend/api/keyboard_event.hpp | Nui::WebApi::KeyboardEvent | onKeyDown/Up/Press | |
nui/frontend/api/drag_event.hpp | Nui::WebApi::DragEvent | onDrag, onDrop, etc. | |
nui/frontend/api/ui_event.hpp | Nui::WebApi::UiEvent | base of mouse/keyboard events |
All wrappers have a .val() accessor returning the raw Nui::val for any property not directly exposed.
Using Nui::val directly is always valid too, for cases where the typed wrapper isn't available or you need a property not yet wrapped:
convertToVal / convertFromVal -- C++ to JS Conversion
These are rarely needed directly -- prefer Nui::val member access for JS interop -- but they are useful when passing structured C++ data to a JS function or when receiving structured data back.
convertToVal -- C++ to JS
Handles: fundamental types, std::string, std::string_view, std::filesystem::path, std::vector, std::map/unordered_map<std::string, T>, std::pair, std::optional, std::variant, std::unique_ptr, std::shared_ptr, Nui::Observed<T>, Nui::val, and any boost-described struct/class.
convertFromVal -- JS to C++
Mirror of the above; writes into an existing object by reference.
Custom ADL hooks
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingclaude-skill/nui-cpp/SKILL.md
Popularity
- Repository stars
- 225
- Repository forks
- 17
- 7-day trend score
- 27
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/nuicpp/nui/nui-cpp)