Best for
- The dispatcher has routed work to directiveset="ui" (intent ui-build or ui-improve)
- A mixed flow is about to enter its UI phase
- The user asks "what UI do we already have for X?"
event4u-app/agent-config/src/skills/existing-ui-audit/SKILL.md
Use BEFORE writing or editing any non-trivial UI — inventories components, design tokens, shadcn primitives, and reusable patterns into state.ui_audit. Hard gate for the ui directive set.
Decision brief
Interplay: this audit answers what exists (components, tokens, primitives → state.uiaudit); design-intelligence answers what to build (corpus-grounded style/token/typography/pattern selection for the brief). Audit runs first, and its reuse findings outrank corpus suggestions — n…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/existing-ui-audit"Inspect the Agent Skill "existing-ui-audit" from https://github.com/event4u-app/agent-config/blob/a36d4658de87e81bda8299dc3a01b9b9ce583af5/src/skills/existing-ui-audit/SKILL.md at commit a36d4658de87e81bda8299dc3a01b9b9ce583af5. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
1. Read state.stack.frontend — set by scripts/workengine/stack/detect.ts (one of blade-livewire-flux, react-shadcn, vue, plain). 2. Read state.input — the request being processed. The audit must answer: "what already exists that is similar to this request?"
Use this skill when: - The dispatcher has routed work to directiveset="ui" (intent ui-build or ui-improve) - A mixed flow is about to enter its UI phase - The user asks "what UI do we already have for X?"
Any request to recreate, redesign, mock, prototype, or improve a UI runs this gate BEFORE styling — the Inspect stage of the design-artifact lifecycle. Design starts from project truth, not generic aesthetic memory.
1. Read state.stack.frontend — set by scripts/workengine/stack/detect.ts (one of blade-livewire-flux, react-shadcn, vue, plain). 2. Read state.input — the request being processed. The audit must answer: "what already exists that is similar to this request?"
Capture each component/template as: {path, name, kind: page|partial|component|layout, exports?: [props]}.
Permission review
The documentation asks the agent to read local files, directories, or repositories.
**Tool composition — inspect before you generate.** Owned UI → repositoryEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 100/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 7 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Interplay: this audit answers what exists (components, tokens, primitives →
state.ui_audit);design-intelligenceanswers what to build (corpus-grounded style/token/typography/pattern selection for the brief). Audit runs first, and its reuse findings outrank corpus suggestions — never let a grounded recommendation introduce a new component the inventory already covers.
Use this skill when:
directive_set="ui" (intent ui-build or ui-improve)mixed flow is about to enter its UI phaseDo NOT use when:
directive_set="ui-trivial" — the trivial path bypasses audit by precondition (≤1 file, ≤5 lines, no new component, no new state, no new dep)directive_set="backend" — no UI surface to inventorystate.ui_audit for this state-file — the gate round-trips through SUCCESS once audit_path is set, and does not re-run for the life of that state-file (see Gotchas for what that does and does not cover)Any request to recreate, redesign, mock, prototype, or improve a UI runs this gate BEFORE styling — the Inspect stage of the design-artifact lifecycle. Design starts from project truth, not generic aesthetic memory.
ask-when-uncertain), not a
licence to improvise. (fixture: daf-inaccessible-design-system.)daf-no-context, daf-missing-asset.)state.stack.frontend — set by scripts/work_engine/stack/detect.ts (one of blade-livewire-flux, react-shadcn, vue, plain).state.input — the request being processed. The audit must answer: "what already exists that is similar to this request?"| Stack | Where to look |
|---|---|
blade-livewire-flux | resources/views/components/, resources/views/livewire/, resources/views/partials/, resources/views/layouts/, app/View/Components/, app/Livewire/ |
react-shadcn | components/, app/components/, src/components/, src/app/(routes)/, plus any app/**/page.tsx for Next.js |
vue | resources/js/components/, src/components/, pages/ |
plain | resources/views/, plus any *.html under public/ |
Capture each component/template as: {path, name, kind: page|partial|component|layout, exports?: [props]}.
Detect markers, in order. Stop at the first match — projects rarely run more than one design system.
| Marker | Signal | Where |
|---|---|---|
| Flux | livewire/flux in composer.json, <flux:*> tags in views | composer.json, grep resources/views |
| shadcn/ui | components.json exists at the workspace root — the package that owns it; in a monorepo this is never the repository root | components.json |
| Headless UI | @headlessui/react or @headlessui/vue in package.json | package.json |
| Radix | @radix-ui/* in package.json (without shadcn marker) | package.json |
| Material/Chakra/Mantine/Ant | their package names in package.json | package.json |
| Custom / none | none of the above match | — |
Write into state.ui_audit.design_tokens (object, never null — empty object is fine):
| Source | What to extract |
|---|---|
tailwind-v3 (axes.css) — tailwind.config.{js,ts,cjs,mjs} | theme.colors, theme.spacing, theme.fontFamily, theme.extend.* |
tailwind-v4 (axes.css) — the @theme block in the entry CSS; no config file exists, and components.json "tailwind": {"config": ""} is the marker | every --token: value declared inside @theme / @theme inline |
:root { --... } blocks in resources/css/, app/globals.css, src/app/globals.css | every --token-name: value pair |
theme.json / tokens.json (any depth) | flat or nested token tree |
app/css/variables.css, assets/scss/_tokens.scss | SCSS $var: value and CSS custom properties |
A supplied design-system.json (handed over with a provided artifact) | colors, typography, spacing, radius, shadow, and motion (durations, easings) — read as the answer, never re-derived |
A supplied artifact's own :root { --… } / inline <style> (the handover file itself, e.g. design.html) | every --token-name: value pair, when no design-system.json accompanies it |
Group output by category: colors, spacing, radius, font, shadow, breakpoint, other.
Branch on the axis, do not probe for a config file. detect_stack() emits
axes.css as tailwind-v3 or tailwind-v4
(work_engine/stack/detect.ts:521-524); reading it is how this step and
react-shadcn-ui § Gotcha stay on the same key. Absence of
tailwind.config.* is v4's normal state, never a missing file.
Artifact-sourced tokens stay distinguishable from project tokens. Every
group carries a source — project for the first four rows, artifact for the
last two — because the mapping between them is the thing a port has to keep
visible. Collapsing them loses the answer to "did this value come from what the
user handed me, or from what the repo already had?", and that is exactly the
question the apply coverage report has to answer per item. The two sets may
disagree; when they do, surface the conflict rather than merging it (a supplied
spec outranks house taste, but not a registered brand token — see
brand-source-of-truth).
motion is new here: the block has existed in the design-system.json schema
since capture shipped and nothing consumed it. On the port branch it is
read, so easing and duration stop being values the brief silently regenerates.
state.stack.frontend == "react-shadcn")Read components.json for the registered style + base color, then read the package.json of the scope root — state.stack.scope_root, relative to the project root, empty when the project root is the scope — for @radix-ui/* or the unified radix-ui package, plus any locally vendored components/ui/*.tsx files. In a monorepo the repository root carries neither the marker nor the dependency, so reading it finds nothing. Write into state.ui_audit.shadcn_inventory:
{
version: <from package.json shadcn registry CLI version, or null>,
style: "default" | "new-york" | <other>,
base_color: "slate" | "zinc" | ...,
primitives: ["Button", "Dialog", "Form", "Table", ...], // names of files in components/ui/
installed_radix: ["@radix-ui/react-dialog", ...] // raw radix list
}
When the project carries @storybook/addon-mcp and a Storybook is running, query it
instead of reading files: list-all-documentation for the inventory, then get-documentation
for the components that matter. The live read wins; the hand-read inventory of step 4 is the
fallback and is never removed — an agent that cannot reach a running Storybook must still be
able to inventory the library. The channel disappearing is normal, not an error.
React-only while the toolset is in preview. Storybook's own MCP FAQ (docs 10.5,
docs/ai/mcp/overview § FAQ) states the documentation toolset supports React only during
preview, so Vue, Angular, and Web Components take the file-read path. Stated here rather than
discovered at runtime, because the failure otherwise looks like a broken MCP server.
Discipline for what the live read returns is storybook-workshop's
— in particular: never use a prop the manifest does not document, and fetch the project's
story instructions before writing a story.
Categorize what already exists. Empty arrays are valid, never omit the keys.
state.ui_audit.patterns = {
forms: [<component path:str>, ...], // any component with <form>, useForm, <flux:input>, <Input> + <Button type=submit>
tables: [...], // <table>, <flux:table>, DataTable, headless table primitives
modals: [...], // <flux:modal>, <Dialog>, AlertDialog, Sheet
empty_states: [...], // components matching grep "no results"|"empty"|"keine"|"nothing yet"
navigation: [...], // sidebar, breadcrumb, tabs
data_display: [...] // cards, lists, stat tiles
}
For each item in state.ui_audit.components, score similarity to state.input.data (fuzzy on filename + props/slots + co-occurring terms). Keep top 5 with score >= 0.3. Write into state.ui_audit.candidates:
[{path, name, score, reason: "matches 'settings' + 'toggle' in props"}, ...]
If candidates is empty, the user is building net-new. That is normal — record the empty list, do not halt.
If all are true:
state.ui_audit.components is emptystate.ui_audit.design_system == "custom-or-none"state.ui_audit.design_tokens is empty (no Tailwind config customizations, no :root)then set state.ui_audit.greenfield = true and emit a halt:
> No existing UI surface detected — this looks like greenfield.
>
> 1. Scaffold a minimal token set + a base component primitive folder
> before building (recommended for projects with >1 planned screen)
> 2. Proceed bare with Tailwind defaults (recommended for one-off prototypes)
> 3. Point me at an external design-system reference (URL or file)
**Recommendation: 1 — Scaffold tokens + primitives** — even one extra screen
benefits from a shared base; the scaffold cost is ~10 min and saves
re-doing every primitive on screen 2. Caveat: flip to 2 if this is a
demo or single-page prototype that will not grow.
Record the user's pick in state.ui_audit.greenfield_decision (scaffold | bare | external_reference). Re-running the skill on the same state-file with greenfield_decision set is a no-op for the halt (audit findings stay).
The R4 visual-review-loop contract reads state.ui_audit.a11y_baseline
when present; the review gate then filters incoming
state.ui_review.a11y.violations against it so pre-existing
violations stay informational and only NEW or CHANGED entries block
the polish loop. Without a baseline the gate sees every violation as
actionable — fine for greenfield, noisy for legacy surfaces.
Capture the baseline when:
Skip the baseline (omit the key, leave state.ui_audit.a11y_baseline
unset) when:
Shape (each entry must carry at least rule + selector; severity
is optional but recommended so the review gate's severity-floor
filter behaves the same on replay):
state.ui_audit.a11y_baseline = [
{rule: "color-contrast", selector: ".legacy-tab", severity: "moderate"},
{rule: "label", selector: "form#search input[type=search]"},
...
]
Producer parity: the review skill that writes
state.ui_review.a11y.violations MUST use the same (rule, selector)
shape, otherwise the engine's de-dup will miss matches and pre-existing
violations will surface as new findings on every run.
state.ui_audit (empty arrays/objects allowed; null only for shadcn_inventory outside the react-shadcn stack).state.ui_audit.greenfield == true implies state.ui_audit.greenfield_decision is set.done — the dispatcher's audit gate now passes.Load on demand once the audit needs the pitfall catalog:
references/anti-slop-cross-reference.md — Anti-slop cross-reference
references/output-and-pitfalls.md — Output format · Gotcha · Anti-slop cross-reference
state.ui_audit.components — array of component/template descriptors (path, name, kind, exports)state.ui_audit.design_system — single string identifying the dominant system or custom-or-nonestate.ui_audit.design_tokens — object grouped by category (colors, spacing, radius, font, shadow, breakpoint, other)state.ui_audit.shadcn_inventory — object with version, style, base_color, primitives (only when stack is react-shadcn; null otherwise)state.ui_audit.patterns — object with forms, tables, modals, empty_states, navigation, data_display arraysstate.ui_audit.candidates — top-5 similarity matches for the current input (may be empty)state.ui_audit.greenfield — boolean; when true, greenfield_decision MUST also be set before the dispatcher advancesstate.ui_audit.a11y_baseline (optional) — array of {rule, selector, severity?} entries documenting pre-existing a11y violations the review gate should treat as informational. Omit the key entirely when no baseline applies; do not write [] for "I checked and there are none" — that disables the gate's filter for every future run.Design-system export (current-repo source): when the goal is to seed
DESIGN.md from this repo, emit the inventory as a design-system.json
artifact (the import contract in
design-system-capture)
and hand it to design-system-capture — the same shape an external extraction
tool produces, so the import path is uniform.
directives/ui/audit.ts enforces "no design without audit findings". Never treat this skill as optional for non-trivial UI.:root, not from class strings in templates.package.json means shadcn — shadcn requires components.json at the workspace root that owns the components. Each workspace carries its own; the repository root carries none, which is the layout the shadcn CLI scaffolds.state.ui_audit.shadcn_inventory.version is often missing; the shadcn CLI does not always pin itself in package.json. Record null rather than guessing.(composer.json mtime, package.json mtime) and re-audit when either changed.
No code implemented it, and the key was the wrong one anyway: apply adds
components without touching a manifest, so a manifest-keyed cache never
invalidates on the change that matters. What the engine does is simpler and
stricter — audit.ts returns SUCCESS unconditionally once audit_path is
high_confidence or ambiguous, so the inventory is computed once per
state-file and never refreshed.state.ui_audit.components_found.directives/ui/design.ts or apply.ts if state.ui_audit is empty.state.ui_audit.greenfield == true and state.ui_audit.greenfield_decision is unset.state.ui_audit once it is populated unless re-detection is triggered by mtime change — design and apply read from it.Frequently asked questions
Interplay: this audit answers what exists (components, tokens, primitives → state.uiaudit); design-intelligence answers what to build (corpus-grounded style/token/typography/pattern selection for the brief). Audit runs first, and its reuse findings outrank corpus suggestions — n…
The source record exposes this install command: npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/existing-ui-audit". Inspect the command and pinned source before running it.
Static rules flagged read-files in the source; the page lists the matching lines and excerpts.
Alternatives
fcakyon/claude-codex-settings
Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view
yonatangross/orchestkit
json-render component catalog patterns for AI-safe generative UI. Define Zod-typed catalogs that constrain what AI can generate, use @json-render/shadcn for 36 pre-built components, optimize specs with YAML mode, and apply the three edit modes (patch/merge/diff) for progressive updates. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native/Ink/Next.js projects.
theBGuy/GitDesktop
Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view
vibeeval/vibecosystem
Full-stack frontend development combining premium UI design, cinematic animations, AI-generated media assets, persuasive copywriting, and visual art. Builds complete, visually striking web pages with real media, advanced motion, and compelling copy. Use when: building landing pages, marketing sites, product pages, dashboards, generating media assets (image/video/audio/music), writing conversion copy, creating generative art, or implementing cinematic scroll animations.