Existing ui audit
Skill event4u-app/agent-config/dist/agent-src/skills/existing-ui-audit
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.From its SKILL.md
npx -y skills add event4u-app/agent-config --skill existing-ui-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
14.1 KB, ~3.5k tokens by cl100k_base, as published. Nobody here has run it
existing-ui-audit
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.
When to use
Use this skill when:
- The dispatcher has routed work to
directive_set="ui"(intentui-buildorui-improve) - A
mixedflow is about to enter its UI phase - The user asks "what UI do we already have for X?"
Do 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 inventory- The audit findings already exist in
state.ui_auditfor this state-file (cached) — re-run only ifpackage.jsonorcomposer.jsonmtime changed
Resource-first context gate (design fidelity)
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.
- Search first (owned UI). Before proposing anything, search the project for: design tokens, global CSS, the component library / design system (§ 2), supplied screenshots or exported design context, Figma/exported context when connected, assets (logos, icons, fonts), and copy tone. Procedure steps 1–5 produce this inventory — do not skip them for a "quick" redesign.
- Hard stop on a promised-but-inaccessible source. When the user explicitly
references a design system, local folder, Figma file, or codebase you cannot
read, STOP and ask for access — never invent a design from memory to paper
over the missing source. A promised source that can't be reached is a blocking
question (
ask-when-uncertain), not a licence to improvise. (fixture:daf-inaccessible-design-system.) - Source priority — code beats screenshots. For exact values (tokens, spacing, component props) the design-system/code context is authoritative; a screenshot conveys gestalt but is not enough for component/token fidelity. Never read pixel values off a screenshot when the source is available.
- Tool composition — inspect before you generate. Owned UI → repository
search + local files FIRST. Connected/imported design data (Figma, tokens
export) → that connector next, when available. Browser / image search → only
for public references or current product/place imagery, never a substitute
for inspecting owned code. Generated imagery → only when the user asks for
synthetic assets, or no real inspection is required. (fixtures:
daf-no-context,daf-missing-asset.)
Procedure: Audit the existing UI surface
0. Inspect stack and input
- Read
state.stack.frontend— set byscripts/work_engine/stack/detect.ts(one ofblade-livewire-flux,react-shadcn,vue,plain). - Read
state.input— the request being processed. The audit must answer: "what already exists that is similar to this request?"
1. Enumerate components and templates
| 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]}.
2. Identify the design system
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 repo 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 | — |
3. Detect design tokens
Write into state.ui_audit.design_tokens (object, never null — empty object is fine):
| Source | What to extract |
|---|---|
tailwind.config.{js,ts,cjs,mjs} | theme.colors, theme.spacing, theme.fontFamily, theme.extend.* |
: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 |
Group output by category: colors, spacing, radius, font, shadow, breakpoint, other.
4. Detect shadcn inventory (only when state.stack.frontend == "react-shadcn")
Read components.json for the registered style + base color, then read package.json for @radix-ui/* and any locally vendored components/ui/*.tsx files. 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
}
5. List reusable patterns
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
}
6. Match candidates for the current input
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.
7. Greenfield branch
If all are true:
state.ui_audit.componentsis emptystate.ui_audit.design_system == "custom-or-none"state.ui_audit.design_tokensis 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).
8. (Optional) Capture an a11y baseline
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:
- The audit covers components with known a11y debt the project does not intend to fix in this run (legacy templates, third-party embeds, vendor widgets).
- The user says "don't block on existing a11y issues" or similar.
Skip the baseline (omit the key, leave state.ui_audit.a11y_baseline
unset) when:
- The surface is greenfield — the review gate should treat every violation as new.
- The project's a11y posture is "zero known violations" and any finding is by definition actionable.
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.
9. Validate and write findings
- Verify every key in the Output format below is present in
state.ui_audit(empty arrays/objects allowed;nullonly forshadcn_inventoryoutside the react-shadcn stack). - Verify
state.ui_audit.greenfield == trueimpliesstate.ui_audit.greenfield_decisionis set. - Write the full object back into the state-file. Audit completes with outcome
done— the dispatcher's audit gate now passes.
Output format
state.ui_audit.components— array of component/template descriptors (path, name, kind, exports)state.ui_audit.design_system— single string identifying the dominant system orcustom-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 isreact-shadcn;nullotherwise)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_decisionMUST 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): 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 — same shape an external tool produces,
so the import path is uniform.
Gotcha
- The model tends to skip the audit and start designing straight from the request — the dispatcher gate at
directives/ui/audit.tsenforces "no design without audit findings". Never treat this skill as optional for non-trivial UI. - The model tends to misidentify a single Tailwind utility as a "design token" — tokens come from the config or
:root, not from class strings in templates. - Don't assume a Radix-only
package.jsonmeans shadcn — shadcn requirescomponents.jsonat repo root. state.ui_audit.shadcn_inventory.versionis often missing; the shadcn CLI does not always pin itself inpackage.json. Recordnullrather than guessing.- Greenfield is detected, not assumed — a project with one Blade layout and no components is still greenfield only if tokens AND design system markers AND components are all empty.
- Re-running the skill on a stale state-file: cache by
(composer.json mtime, package.json mtime); if either changed, re-audit and overwrite.
Anti-slop cross-reference
When the audit inventory reveals an existing aesthetic direction (dominant color
scheme, border-radius convention, motion patterns), cross-check the findings
against
docs/guidelines/design-antipatterns.md.
If the existing UI already uses a listed anti-pattern, surface it as a design-debt
finding (separate from the reuse inventory) — flag by entry ID and severity. The
next design step can then decide whether to continue the existing pattern (for
consistency) or introduce a corrective direction change.
Do NOT
- Do NOT advance to
directives/ui/design.tsorapply.tsifstate.ui_auditis empty. - Do NOT advance to design or apply if
state.ui_audit.greenfield == trueandstate.ui_audit.greenfield_decisionis unset. - Do NOT silently skip the greenfield halt because "Tailwind has defaults" — the user picks the path explicitly.
- Do NOT write paths outside the project root into the inventory.
- Do NOT rewrite
state.ui_auditonce it is populated unless re-detection is triggered by mtime change — design and apply read from it.
What ships with it: 2 files
3.9 KB alongside SKILL.md
evals/
- triggers.json2.0 KB