Frontend UI Functional
victorGPT/vibeusage
A skill your agent uses when building or refactoring functional React/Vite/Tailwind UI pages, templates, or component libraries that need consistent structure, tokenized styling, accessibility…
Guides adding or modifying UI features (React "studios") in HOT-Step CPP — studio-folder convention, store patterns, API wiring, routing registration, Tailwind/i18n rules, and the Vite HMR dev loop.
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-dev --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/ui-feature-dev .claude/skills/ui-feature-dev && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .claude/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-devType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-dev --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/ui-feature-dev .agents/skills/ui-feature-dev && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .agents/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-dev --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/ui-feature-dev .cursor/skills/ui-feature-dev && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .cursor/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/scragnog/HOT-Step-CPP.git --path .claude/skills/ui-feature-dev--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-dev --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/ui-feature-dev .gemini/skills/ui-feature-dev && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .gemini/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-devInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/ui-feature-dev .github/skills/ui-feature-dev && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .github/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install scragnog/HOT-Step-CPP ui-feature-dev --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/scragnog/HOT-Step-CPP.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/ui-feature-dev .opencode/skills/ui-feature-dev && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ui-feature-dev" agent skill from https://github.com/scragnog/HOT-Step-CPP/tree/master/.claude/skills/ui-feature-dev into .opencode/skills/ui-feature-dev/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ui-feature-dev", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ui-feature-devGuides adding or modifying UI features (React "studios") in HOT-Step CPP — studio-folder convention, store patterns, API wiring, routing registration, Tailwind/i18n rules, and the Vite HMR dev loop.
UI Feature Dev is an agent skill from scragnog/HOT-Step-CPP. Guides adding or modifying UI features (React "studios") in HOT-Step CPP — studio-folder convention, store patterns, API wiring, routing registration, Tailwind/i18n rules, and the Vite HMR dev loop. Use when creating a new studio/panel/view, adding UI controls or sliders, wiring UI to a server endpoint, or changing anything under ui/src/. NOT for solver/scheduler/guidance knobs — those are declared by Lua plugins in engine/plugins/ (see the lua-plugin-authoring skill), with zero ui/src/ changes.
Its SKILL.md is about 5.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `reference.md`).
It sits in Frontend & Design, covering CSS and styling and Internationalization. It works with React, Lua, C++ and Vite. The repository describes itself as: Turn dials. Summon bangers! NOW WITH MORE C++! Local AI music generation powered by GGML. The licence is MIT.
11 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 91e92a8. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxnpmgittscnodecmakeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, npm and git, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
UI Feature Dev loads about 5.3k tokens when it runs. Until then it costs about 129 tokens; SKILL.md has 2,300 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from scragnog/HOT-Step-CPP at commit 91e92a8, republished under its MIT licence (© scragnog). 2,300 words, ~5,276 tokens.
.claude/skills/ui-feature-dev/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.The UI tier of HOT-Step CPP is a single-page React 19 app in ui/ (Vite 8, Tailwind 3.4, zustand 5, react-i18next, lucide-react icons). Every user-facing feature is a "studio" — a folder of components under ui/src/components/ mounted as a top-level view. There is no react-router: routing is hand-rolled history.pushState in App.tsx. All server calls are plain fetch() against relative /api/... URLs (no axios, no react-query).
Terms used below:
ui/src/components/ plus a branch in App.tsx.docs/dev/plugins-authoring.md, lua-plugin-authoring skill). Wiring one into getGlobalParams() is the wrong implementation entirely.StyledSelect, an on/off setting is Toggle, a parameter label is ParamLabel with info. Never a native <select> or <input type="checkbox">; node tools/docs/check-docs.mjs fails on a new one. WHY: the native widgets look nothing like the app (grey OS box, white text) and a knob with no explanation is a support question.npm run build during dev. Vite HMR means UI edits need no build and no restart. Type-check with npx tsc -b from ui\ (all tsconfigs have noEmit: true — nothing is emitted). Only build right before user prod testing. WHY: builds are slow and pointless mid-dev; the dev server already serves source.ui/package.json enforces "node": ">=20.0.0 <25.0.0".App.tsx: the import + viewFromUrl + urlForView + the renderContent branch, plus one NavItem in Sidebar.tsx — see procedure below). Skipping viewFromUrl()/urlForView() gives a studio that renders but breaks on refresh/back-button.getGlobalParams() in ui/src/stores/globalParamsStore.ts (starts line 324) — that function is the SINGLE assembly point for the request body. A slider not wired there silently does nothing.t() (react-i18next) with a key in ui/src/i18n/locales/en.json; other locales fall back to English. Note: en.json nests everything under a top-level "translation" key.master, never git add -A, never git add -f on gitignored paths — stage explicit paths only. Push only with explicit user approval, commit locally often. Never push a v* tag casually — it triggers a full multi-platform CI release build.dev-rebuild.bat at repo root, NEVER engine/build.cmd directly, under any circumstances (Node auto-respawns ace-server; only dev-rebuild.bat performs the clean shutdown). Never cmake --clean-first (20+ min CUDA recompile).AceRequest struct never survive the /lm round trip. Synth requests are rebuilt by spreading the original aceReq and taking ONLY LM-generated fields from the echo (server/src/routes/generate.ts:312-328). Add new sideband params to aceReq before the LM phase; NEVER extend the LM-field pick-list into a copy-across whitelist (bug class fixed in 8ea519b/168dcb5)..\dev.bat # run it detached; the app then lives at http://localhost:3000This starts BOTH tiers (verified dev.bat): the Node server via server\restart-loop.cmd on :3001 (tsx watch, auto-restart) and npx vite --port 3000 --host in ui\. Develop against **http://localhost:3000** — Vite proxies /api, /audio, and /references to :3001 (ui/vite.config.ts:10-24). LAUNCH.bat is the end-user prod launcher (Node :3001 serving prebuilt ui/dist/, server/src/index.ts:126) — agents never run it.
Checks while developing:
cd D:\Ace-Step-Latest\hot-step-cpp\ui
npx tsc -b # type-check UI (project references — catches what a plain tsc --noEmit on one file misses)
npx eslint . # lintIf you touched server/src/: cd D:\Ace-Step-Latest\hot-step-cpp\server; npx tsc --noEmit.
Only before handing to the user for prod testing: npm run build in ui\ (runs tsc -b && vite build).
Say the studio is "My Studio", slug my-studio.
ui/src/components/my-studio/ with an orchestrator MyStudio.tsx (PascalCase files, kebab-case folder). Export both named and default (export const MyStudio: React.FC = ... + export default MyStudio — see StemStudio.tsx:40,503). Layout convention (documented in-source at StemStudio.tsx:9-10): flex columns with border dividers, resizable right sidebar.ui/src/App.tsx — add the import { MyStudio } ... at the top (cf. App.tsx:38), then three places:viewFromUrl() (App.tsx:84-95): if (path.startsWith('/my-studio')) return 'my-studio';urlForView() (App.tsx:98-116): if (view === 'my-studio') return '/my-studio';renderContent() (App.tsx:652 onward): add a branch, wrapped in DiscoPulseWrapper (a beat-reactive visual wrapper) with a hue from the DISCO constants (App.tsx:279-289, e.g. DISCO.assistant = 175 cyan):if (activeView === 'my-studio') {
return (
<DiscoPulseWrapper hue={DISCO.assistant} className="flex-1 overflow-hidden">
<MyStudio />
</DiscoPulseWrapper>
);
}Navigation flows through navigateTo() (App.tsx:391-401) → setActiveView + history.pushState; back/forward is a popstate listener (App.tsx:404-408). Only Lyric Studio persists a deep URL (hs-lastLyricStudioUrl) — copy that only if your studio has sub-routes.
ui/src/components/sidebar/Sidebar.tsx — copy an existing NavItem block (e.g. Stem Studio at Sidebar.tsx:111-117): icon (lucide-react), label={t('sidebar.myStudio')}, active={activeView === 'my-studio'}, onClick={() => onViewChange('my-studio')}, isExpanded={isOpen}.server/src/routes/myStudio.ts, mount it in server/src/index.ts (app.use('/api/my-studio', ...) — see the mount block at index.ts:72-95), and create a per-studio client ui/src/services/myStudioApi.ts (see API layer below). Keep all endpoints under /api/... or the Vite proxy won't forward them in dev.ui/src/i18n/locales/en.json (under the "translation" root) for every user-visible string.Top-level docs say "Zustand" but only 2 of 8 files in ui/src/stores/ use zustand's create() (globalParamsStore.ts:9, vstChainStore.ts:6 — verified by grep). The majority pattern is a hand-rolled useSyncExternalStore module singleton. Match the pattern of the nearest existing store; don't introduce a fourth.
Pattern A — hand-rolled external store (majority; canonical example ui/src/stores/abCompareStore.ts, 101 lines). Module-level let _state, a Set of listeners, setState() that spreads + notifies, exported plain action functions (importable from non-React code), plus a useXxx() hook (useSyncExternalStore(subscribe, getSnapshot)) and a ref-cached useXxxSelector(selector) hook. Selector hooks are the preferred subscription style: useAudioGenQueueSelector(s => s.items.filter(...).length) (StemStudio.tsx:77-79). Used by: playbackStore, audioGenQueueStore, discoStore, streamingStore, abCompareStore, components/lyric-studio/playlistStore (studio-local stores may live inside the studio folder).
Pattern B — zustand + per-field localStorage (ui/src/stores/globalParamsStore.ts, 460 lines). create<any>()((set, get) => ({...})) — the any is deliberate (line 39-40). Every field initialises via readKey('hs-<name>', default) and every setter does set({...}); writeKey('hs-<name>', v) — per-key hs-* persistence, NOT zustand/persist middleware. getGlobalParams() (line 324-459, end of file) assembles ~100 knobs into a Partial<GenerationParams> request body with conditional gating — new generation params go here or nowhere. ui/src/context/GlobalParamsContext.tsx is a legacy compat shim; its own header (lines 1-8) says new code must import the store directly. Don't extend the context.
Pattern C — plain useState + localStorage inside the studio. StemStudio persists studio-local state via manual localStorage with hs-stem-* keys (StemStudio.tsx:43-46,97-104) or via usePersistedState(key, default) (ui/src/hooks/usePersistedState.ts:9). Cross-component/same-tab sync requires writePersistedState() (usePersistedState.ts:43-49), which manually dispatches a StorageEvent — native StorageEvents only fire cross-tab.
The generation queue store audioGenQueueStore.ts (992 lines) persists to IndexedDB (lireek-queue-store DB) with debounced 2 s writes because large queues blew localStorage's 5 MB cap (lines 65-73,126-133); on reload it resets in-flight items to pending + "Reconnecting…" (_sanitizeItems, lines 142-156).
Two tiers, both in ui/src/services/:
api.ts (406 lines): private get/post/patch/del<T> fetch helpers, BASE = '/api', optional Bearer token, uniform errors (non-OK → throw new Error(err.error || 'API error: <status>'), api.ts:10-64). Exports per-domain objects (songApi, generateApi, modelApi, adapterApi, settingsApi, ...).stemStudioApi.ts, 220 lines): standalone exported async functions, own API_BASE = '/api/stem-studio', own types/constants, and a submit-then-poll helper waitForExtraction(jobId, onProgress, pollMs=1000) (stemStudioApi.ts:190-211). New studios with their own routes follow this shape.Auth: single-user local app. AuthContext auto-logs-in on mount via authApi.autoLogin() (GET /api/auth/auto); components do const { token } = useAuth() and pass token to api methods. Newer endpoints (stem-studio, vst, settings) skip the token entirely — both styles coexist.
snake_case gotcha: the server returns SQLite snake_case rows. normalizeSong() (api.ts:76-114) maps to camelCase while keeping BOTH spellings (audioUrl and audio_url) and parses generation_params if it arrives as a JSON string. Any new endpoint returning songs must route through it or the player/library break.
Generation job protocol (verified api.ts:148-152, types.ts:266-281, polling loop audioGenQueueStore.ts:534-600):
POST /api/generate → { jobId, status }
GET /api/generate/status/:id → GenerationJob { status: 'pending|lm_running|synth_running|saving|succeeded|failed|cancelled',
progress?, stage?, error?,
result?: { audioUrls[], songIds[], masteredAudioUrl?, duration?, ... } }Poll every 1.5 s. Progress may arrive as 0–1 OR 0–100 — normalise both, as audioGenQueueStore.ts:548-550 does. No websockets. Job status is polled (audioGenQueueStore); SSE exists in three places: logs (hooks/useEventSource.ts → TerminalPanel), model-download progress (components/model-manager/useDownloadStream.ts, its own EventSource), and streaming audio previews during generation (hooks/useStreamGeneration.ts → GET /api/generate/stream/:jobId).
ui/tailwind.config.js: darkMode: 'class', custom suno dark palette (#09090b bg / #121214 panel / #18181b card / #27272a hover-border) and brand pink #ec4899; font Inter. ui/src/index.css adds CSS-variable design tokens on top of the @tailwind directives.border-zinc-200 dark:border-white/5, text-zinc-700 dark:text-zinc-300 (see StemStudio.tsx:271,289).focus:border-purple-500/40, #a78bfa labels) inside studios; brand pink for global CTAs.const styles: Record<string, React.CSSProperties> object for one-off widgets is accepted convention (StemStudio.tsx:419-501) — not tech debt to "fix".usePersistedState('hs-activitySidebarWidth', 320) — this key is shared across studios so sidebar width is consistent app-wide (StemStudio.tsx:76,244-262).const { t } = useTranslation(), namespaced keys per studio (t('stem.recentExtractions')), keys in locales/en.json under the "translation" root; ja/ko/ru/zh fall back to en. Helper scripts ui/add_strings.mjs and ui/generate_translations.mjs exist (purpose inferred from names — unverified, read before running). Some existing placeholders are hard-coded English (StemStudio.tsx:288,295); use t() anyway for new strings.| Path | Role |
|---|---|
ui/src/App.tsx (1437 ln) | Root: hand-rolled routing (viewFromUrl/urlForView/navigateTo), renderContent(), DISCO hues, player wiring |
ui/src/main.tsx | Entry: StrictMode > AuthProvider > Suspense > App |
ui/src/components/<studio>/ | One folder per studio; orchestrator component named after the studio |
ui/src/components/shared/ | Section (in ActivitySidebar.tsx — props title, icon, count?, countColor?, defaultOpen?), Slider, EditableSlider, Toast, ConfirmDialog, StemMixer, DiscoPulseWrapper, ... |
ui/src/components/sidebar/Sidebar.tsx | Left nav — one NavItem per studio |
ui/src/stores/globalParamsStore.ts | zustand; all generation knobs; getGlobalParams() = sole request assembler (line 324) |
ui/src/stores/abCompareStore.ts | Smallest canonical hand-rolled store — copy this as a template |
ui/src/stores/audioGenQueueStore.ts | Generation queue; IndexedDB persistence; submit/poll loop (line 534) |
ui/src/services/api.ts | Central fetch client + normalizeSong() (line 76) |
ui/src/services/stemStudioApi.ts | Model per-studio API client (submit-then-poll) |
ui/src/hooks/usePersistedState.ts | Persisted useState + writePersistedState() same-tab sync |
ui/src/context/AuthContext.tsx | Auto-login, useAuth() → { user, token } |
ui/src/context/GlobalParamsContext.tsx | LEGACY compat shim — do not extend |
ui/src/i18n/locales/en.json | Source-of-truth strings (root key "translation") |
ui/vite.config.ts | Dev proxy: /api, /audio, /references → :3001 |
ui/tailwind.config.js | suno palette, brand pink, darkMode: 'class' |
server/src/index.ts | Route mounts (lines 72-95), serves ui/dist in prod |
server/src/routes/stemStudio.ts | Model server route paired with stemStudioApi.ts |
| Symptom | Cause → fix |
|---|---|
npm install/dev fails with dep/engine errors | Check Node 20 to 24 range (ui/package.json engines field) and lockfile consistency. |
New studio renders but URL resets to / on refresh, or back-button breaks | Added renderContent() branch but missed viewFromUrl() and/or urlForView() — all three + Sidebar are required. |
| API 404 in dev but works in prod (or vice versa) | Route prefix not proxied — only /api, /audio, /references are in vite.config.ts. Keep endpoints under /api/.... |
| Songs missing audio/cover in one studio only | Endpoint bypassed normalizeSong() — raw snake_case leaked (api.ts:76-114). |
| Effects/API calls fire twice in dev | React StrictMode double-invoke (main.tsx:9). Dev-only; make mount effects idempotent, don't "fix" with flags. |
| New slider has no effect on generations | Value not wired into getGlobalParams() (globalParamsStore.ts:324) — the only place the request body is assembled. If it reaches getGlobalParams() but never reaches /synth: the server chain is routes/generate.ts → translateParams() (server/src/services/generation/translateParams.ts:11) → aceReq; sideband params must join aceReq BEFORE the LM phase (Golden rule 9 — never whitelist across the LM echo). |
| Setting change in one studio doesn't reflect in another | Wrote localStorage directly instead of writePersistedState() — same-tab listeners need the manually-dispatched StorageEvent. |
| Progress bar jumps 0→100 or shows 5000% | Server progress is 0–1 on some paths, 0–100 on others; normalise like audioGenQueueStore.ts:548-550. |
| Queue items stuck "generating" after reload | Expected behaviour: _sanitizeItems resets to pending+"Reconnecting…" and resumeQueue() re-submits (audioGenQueueStore.ts:142-156,610-621). |
UI shows a raw key like stem.queue | Key missing from i18n/locales/en.json. |
npx tsc --noEmit on a file passes but npm run build fails | build runs tsc -b across ALL project references — reproduce with npx tsc -b from ui\. |
| Generation fails and the UI just shows "failed" | Debug server-side: newest logs/YYYY-MM-DD_HH-MM-SS/ folder → generations/gen_*.log, then ace_engine.log / node_console.log. |
getGlobalParams() is the sole assembly point for generation request bodies; params bypass it → silently dropped. Confirmed by code and by commit 8ea519b ("adapter param plumbing bugs").ui/src/stores/ are hand-rolled useSyncExternalStore stores (a 6th, playlistStore, lives in components/lyric-studio/); 2 use zustand; playbackConverters.ts is pure helpers, not a store. Match your neighbours.GlobalParamsContext.tsx is a migration shim by its own header — extend the store, not the context.ui/add_strings.mjs / ui/generate_translations.mjs (files exist; purpose inferred from names — read before running).ui/README.md is the untouched Vite template — ignore it as documentation.CLAUDE.md (repo root) — cross-tier build/git rules.FEATURES.md — feature catalogue.docs/dev/plugins-authoring.md — if your UI feature exposes a new solver/scheduler/guidance knob, that's a Lua plugin, not C++ (plugins declare their own UI params).engine/docs/ARCHITECTURE.md — engine request JSON, generation modes.docs/plans/ — internal design docs. Gitignored, local-only — may be absent on a fresh clone.© scragnog, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in .claude/skills/ui-feature-dev of scragnog/HOT-Step-CPP.
Open the folder on GitHubat commit 91e92a8
UI Feature Dev next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| UI Feature Dev this skillscragnog/HOT-Step-CPP | 171 | — | ~5.3k | Automated safety check: Pass | MIT | |
| Frontend UI FunctionalvictorGPT/vibeusage | 131 | — | ~939 | Automated safety check: Pass | MIT | |
| Tailwind V4 Shadcnever-works/ever-works | 158 | 2 repos | ~3.8k | Automated safety check: Pass | MIT | |
| Shadcn Tailwind UILiarMTTT/TavernWeave | 150 | — | ~1.7k | Automated safety check: Pass | Custom licence | |
| Redesign My Landingpageinstructa/agent-skills | 139 | — | ~1.8k | Automated safety check: Pass | None | |
| Tailwind V4 Shadcnsecondsky/claude-skills | 227 | — | ~4k | Automated safety check: Pass | MIT |
victorGPT/vibeusage
A skill your agent uses when building or refactoring functional React/Vite/Tailwind UI pages, templates, or component libraries that need consistent structure, tokenized styling, accessibility…
ever-works/ever-works
Production-tested setup for Tailwind CSS v4 with shadcn/ui, Vite, and React.
LiarMTTT/TavernWeave
Build, restyle, or review accessible React interfaces that use shadcn/ui, Radix UI primitives, and Tailwind CSS.
instructa/agent-skills
Build, critique, and iterate high-converting marketing or product landing pages using React + Vite + TypeScript + Tailwind and shadcn/ui components, with all icons sourced from Iconify.
secondsky/claude-skills
| Production-tested setup for Tailwind CSS v4 with shadcn/ui, Vite, and React.
creativetimofficial/ui
Helps install, generate and review Creative Tim UI blocks: shadcn/ui-based React and Tailwind sections that follow a restrained, production-minded design philosophy.
scragnog/HOT-Step-CPP
The standard way to run a listening test in HOT-Step - a local HTML score sheet next to the renders where Rob plays each track, scores it 1-5 on named criteria, and the page charts the two score…
scragnog/HOT-Step-CPP
Explains where HOT-Step generation time goes (LM/DiT/VAE), how the TensorRT paths activate, how to benchmark from logs, and which knobs trade quality for speed.
scragnog/HOT-Step-CPP
Maps HOT-Step's native MiniMax-Music3 backend — engine port modules, endpoints, server/UI integration, parity/fixture infrastructure, and the hard-won trap list.
scragnog/HOT-Step-CPP
The validated recipe for training MiniMax-Music3 planner-LM style adapters (artist/album clones) with ace-train mm3-lm-train and the Training Studio.
scragnog/HOT-Step-CPP
Runbook for cutting and publishing a HOT-Step CPP release via a v git tag that triggers the multi-platform CI build and drafts a GitHub Release.
scragnog/HOT-Step-CPP
Safely pulls upstream acestep.cpp changes into the HOT-Step engine fork without destroying its integration hooks.
Works with
Categories
Guides adding or modifying UI features (React "studios") in HOT-Step CPP — studio-folder convention, store patterns, API wiring, routing registration, Tailwind/i18n rules, and the Vite HMR dev loop. UI Feature Dev is an agent skill from scragnog/HOT-Step-CPP. Guides adding or modifying UI features (React "studios") in HOT-Step CPP — studio-folder convention, store patterns, API wiring, routing registration, Tailwind/i18n rules, and the Vite HMR dev loop.
UI Feature Dev fits situations like: creating a new studio/panel/view; adding UI controls; wiring UI to a server endpoint; changing anything under ui/src/.
Run `npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a claude-code`. Or copy the skill folder (.claude/skills/ui-feature-dev in scragnog/HOT-Step-CPP) into .claude/skills/ui-feature-dev in your project. Claude Code loads it when a task matches its description.
Run `npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a codex`. Or copy the skill folder (.claude/skills/ui-feature-dev in scragnog/HOT-Step-CPP) into .agents/skills/ui-feature-dev in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add scragnog/HOT-Step-CPP --skill ui-feature-dev -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ui-feature-dev, .gemini/skills/ui-feature-dev, .github/skills/ui-feature-dev and .opencode/skills/ui-feature-dev in your project.
Going by SKILL.md and its folder, UI Feature Dev needs the command-line tools its instructions call (npx, npm, git, tsc, node and cmake). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use npx, npm and git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
UI Feature Dev is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.3k tokens (SKILL.md is roughly 21k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with UI Feature Dev: Frontend UI Functional (victorGPT/vibeusage, 131 stars), Tailwind V4 Shadcn (ever-works/ever-works, 158 stars), Shadcn Tailwind UI (LiarMTTT/TavernWeave, 150 stars) and Redesign My Landingpage (instructa/agent-skills, 139 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
scragnog (a GitHub user) maintains it in scragnog/HOT-Step-CPP, which has 171 GitHub stars. The repository holds 18 skills in this directory. The repository was last updated on October 7, 2026.
Source: scragnog/HOT-Step-CPP on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.