codex-skills/yororen-ui-user/SKILL.md
High-quality app code generation for end users building Rust desktop GUIs with gpui + Yororen UI (yororen_ui). Use when a user asks to build, scaffold, or modify an application using Yororen UI/gpui, or when working in a Rust project that depends on yororen_ui. Triggers include "build a counter with yororen ui", "make a form with TextInput", "add a modal", "add a theme switcher", "use yororen_ui". Routes to sibling skills ($yororen-ui-app-core, $yororen-ui-state-inputs, $yororen-ui-recipes) for deep dives. Not for contributing to yororen-ui itself.
npx skillsauth add meowlynxsea/yororen-ui yororen-ui-userInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate application code that uses Yororen UI correctly: pick the right sub-skill, follow the 3-layer split, wire the one-call bootstrap, and trust the framework's built-in patterns for state, inputs, themes, and i18n.
If the user is editing the yororen-ui library itself, stop and ask for an app repository.
Yororen UI ships as three independent layers you compose at the import boundary:
theme JSON ─▶ renderer (TokenXxxRenderer) ─▶ headless (XxxProps) ─▶ gpui-ce
| Layer | Crate | Role |
|---|---|---|
| headless | yororen-ui-core | data + state machine + a11y. No visual decisions. |
| renderer | yororen-ui-default-renderer (or -brutalism-) | turns props into a styled Div. 54 trait impls. |
| theme | a JSON file | palette + tokens the renderer reads by path. |
The headless layer is the source of truth. The renderer is swappable.
The theme is data. Read more in
references/three-layer-architecture.md.
When the user asks for code, route to the right sub-skill. The boundary is about what kind of work the user is doing, not which file gets edited.
| If the user wants to… | Use this sub-skill |
|---|---|
| Scaffold a new app / main.rs / window / theme / i18n / state module layout | $yororen-ui-app-core |
| Add or fix an input, form, modal, dropdown, popover, listbox, tree, virtual list | $yororen-ui-state-inputs |
| Copy a complete working example (counter / layers / inputs / gallery / theme switch) | $yororen-ui-recipes |
If the request spans two or three (e.g. "build a settings modal in my
counter app"), prefer $yororen-ui-recipes first (it links to the others).
If the repository is the yororen-ui library itself, refuse. Ask the user to point you at their app repo.
Pin these. Mismatched gpui-ce versions cause compile errors that look like library bugs.
# Cargo.toml
[dependencies]
gpui = { package = "gpui-ce", version = "0.3" }
yororen_ui = "0.3"
gpui. Do not depend on the
upstream gpui crate — it will resolve to a different version and
break.gpui-ce minor version to whatever yororen_ui resolves to.
cargo tree -i gpui-ce will tell you.For a brand-new project, prefer a tagged git dep for reproducibility:
yororen_ui = { git = "https://github.com/MeowLynxSea/yororen-ui.git", tag = "v0.3.0" }
For local development against the workspace, path = "../../yororen-ui"
is fine — but only when the user explicitly asks to track local changes.
Do not introduce path = ... for end users.
These are the rules the framework was built to enforce. Violate them and the app will either not compile or quietly misbehave.
One-call bootstrap. Always start the app with
yororen_ui::renderer::install(cx, cx.window_appearance()) (or
default_renderer::install_with(cx, my_theme) for a custom JSON theme).
This single call sets the global Theme and registers all 54 default
renderers.
The Theme global is read-only from app code. You read it via
cx.theme().get_color("action.primary.bg") and friends. The renderer
is the only thing that should write the theme, and it does that
once at install time (or per-render, for live theme switching).
State goes in Entity<T>, not Arc<Mutex<T>>. gpui-ce already
tracks which entities a render closure reads, so cx.notify() on the
entity is enough to invalidate the window. Arc<Mutex<T>> is
unnecessary and complicates cx.notify() plumbing.
Stateful composites own their Entity<XxxState>. select,
combo_box, modal, popover, dropdown_menu, tooltip, listbox,
menu, overlay each ship with a XxxState struct whose ::new(cx)
mints the entity. You keep the Entity<XxxState> in your app state
and call state.update(cx, |s, _| s.open()) etc.
Inputs are uncontrolled by default. Wire
.on_change(|new, _w, cx| { ... }) and trust the component to own its
caret / selection / IME state. If you need to reset the field (open
edit modal, clear after submit), the component itself is the source
of truth — derive the new value from your own state, don't fight the
component.
Don't call render() inside an event handler. Render closures
run on the GPUI main thread; side effects inside them (timers,
cx.spawn, file I/O) belong in event handlers, not in the
render path.
Stable identity. Every stateful child in a list or a virtualized
view needs a stable .id(...). List reordering without identity
silently desyncs focus and animation state.
The demos converge on this shape; copy it unless the user has a reason not to.
my_app/
├── Cargo.toml
├── locales/ # your app's i18n JSON, optional
│ ├── en.json
│ └── zh-CN.json
├── themes/ # your app's theme JSON, optional
│ └── my-light.json
└── src/
├── main.rs # bootstrap only (10–30 lines)
├── state.rs # global state + composite entity fields
├── my_app.rs # root Render impl
└── components/ # sub-screens, panels, modals
├── settings_modal.rs
└── ...
main.rs does only:
fn main() {
let app = Application::new().with_assets(UiAsset);
app.run(|cx: &mut App| {
yororen_ui::renderer::install(cx, cx.window_appearance());
yororen_ui::locale_en::install(cx); // or locale::install_locale(cx, "zh-CN")
cx.set_global(state::AppState::new(cx)); // if you have one
cx.set_global(NotificationCenter::new()); // only if you use toasts
// cx.open_window(...) goes here
});
}
See $yororen-ui-app-core for the full bootstrap, theme authoring, i18n
plumbing, and the state.rs pattern.
When you write code for the user:
use yororen_ui::headless::button::button;
imports the factory function. use yororen_ui::headless::button; imports
the module (which is almost never what you want).crates/yororen-ui-core/src/headless/*.rs of the dependency
source checkout.cargo check
on the user's project. The dylib ABI and trait bounds shift enough
that "it looks right" is not enough.Entity<XxxState> pattern,
cx.entity().clone() for closures, gpui::deferred(...).with_priority(N)
for overlay z-order — these are framework-specific. A one-line
comment next to the pattern saves a future reader an hour.$yororen-ui-app-core — bootstrap, project layout, theme, i18n, state$yororen-ui-state-inputs — inputs, forms, modals, composites, cx.entity() pattern$yororen-ui-recipes — full working examples (counter, layers, inputs, gallery, theme)yororen-ui itself (or a fork). Refuse, point at the
repo's CONTRIBUTING.md.tools
State management and interactive components for end users building Yororen UI apps with gpui. Use when implementing TextInput/TextArea/SearchInput/PasswordInput/NumberInput/FilePathInput/KeybindingInput/ComboBox, building forms (form + form_field + submit_button), wiring on_change/on_submit/on_toggle/on_pick handlers, opening/closing modals/popovers/dropdowns/tooltips/select/menus, configuring the AnimatedVisibility lifecycle on composites, using virtual_list with infinite loading, or debugging typing lag and focus issues. Not for contributing to yororen-ui itself.
development
End-to-end recipe patterns for end users building gpui apps with Yororen UI (yororen_ui). Use when the user asks for a complete working example, wants a screen layout pattern, or needs guidance composing components, modals, forms, list rendering, virtualized lists, notifications, theme switching, or i18n. Triggers include "show me a full example", "copy from the gallery", "how do I do theme switching", "how do I compose a modal + form", "how do I virtualize a long list". Not for contributing to yororen-ui itself.
development
App bootstrap and core architecture for end users building a gpui desktop app with Yororen UI (yororen_ui). Use when generating or refactoring main.rs, window setup, the one-call renderer install, the i18n bootstrap, NotificationCenter global, custom theme JSON, project module layout (state.rs, *app.rs, components/), Entity<T> state pattern, or theme reads via cx.theme(). Not for contributing to yororen-ui itself.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.