ui-apply-generic
The plain lane used to be a name with nothing behind it. This skill is the
lane: it carries the implementation discipline that previously lived only
inside the framework executors, and it gets framework idiom from the 16-stack
corpus instead of from prose written here.
That split is the whole point. One skill plus a corpus serves Svelte, Astro,
Angular, Alpine, htmx and everything future at once. Sixteen framework skills
would serve the same set and cost a single maintainer sixteen surfaces to keep
current — the enumeration this package refuses.
When to use
state.stack.frontend resolves to plain, or to a label with no
framework-specific overlay.
- A stack whose
axes.reactivity or axes.meta is recognised but has no
executor skill (svelte, angular, astro, solid, qwik, htmx).
- As the base of a composition: an overlay skill (
livewire, flux,
blade-ui, react-shadcn-ui) adds framework specifics on top of this
contract, it does not replace it.
Do NOT use when a framework executor already covers the whole job — then this
skill is the base and the executor is the overlay, dispatched together.
Procedure
Step 1 — Query the stack corpus (mandatory)
Read state.stack.axes and query per resolved axis value, most specific first:
meta → reactivity → component_lib.
<skills-root>/corpus-grounding/scripts/ground search \
--manifest <skills-root>/design-intelligence/data/manifest.json \
--stack <axis-value> "<the concrete question>"
axes.meta: nuxt with axes.reactivity: vue means two queries —
--stack nuxtjs and --stack vue. A meta-framework does not replace the layer
it wraps; that conflation is the defect the axes exist to fix.
Cite what you used. The result names the corpus rows the implementation
followed. An uncited pick is indistinguishable from the model's memory, and
memory is exactly what the corpus exists to replace.
No corpus domain for the detected stack → say so, in the result:
No stack corpus for <stack> — proceeding on the generic contract. Framework
idiom below is not grounded and should be reviewed by someone who knows this
stack.
Silence is the failure mode. An unstated gap reads as grounded output.
Step 2 — Apply the stack-independent contract
Every item is a hard requirement, and none of them is framework-specific:
- Verbatim floor. Microcopy comes from
state.ui_design.microcopy exactly
as written — every label, empty-state line, and validation message. No
paraphrase, no improvement. Where a source artifact was provided, it beats
the brief (see design-fidelity).
- Token discipline. Colour, spacing, radius and shadow values come from the
project's tokens. A raw hex or arbitrary px that no token backs is a finding,
not a choice. Validate with
design-tokens' tokens validate.
- Component reuse. Check
state.ui_audit.components_found before creating
anything. In a run that has already added components, re-read the component
directories — the audit inventory is computed once per state-file and does
not refresh (see existing-ui-audit § Gotchas).
- a11y floor. Semantic elements over
div + role; every interactive
element reachable and labelled; focus visible; contrast meets the project's
stated level, AA when unstated.
- All five states.
empty, loading, error, success, disabled per
the brief. An explicit n/a is legitimate for a surface that genuinely has
no such state — declaring that is the opposite of inventing filler.
- Asset discipline. Copy referenced assets into the project's asset path.
Never hotlink; never fabricate a logo or a screenshot.
- No placeholders.
<placeholder>, lorem, todo:, tbd, xxx are
rejected at the boundary — including inside arrays.
Step 3 — Verify, with honest degrade
Exercise the result with whatever the host actually has, and name which:
| Available |
Do |
| Browser / Playwright |
Render, check the states, exercise one interaction |
| Screenshot only |
Capture and inspect layout at 375 / 768 / 1280 |
| Neither |
Static inspection only, and say the render is unverified |
Never claim a state or interaction works without having exercised it. A caveat
is a finding; a silent claim is a defect.
Output format
Four requirements, in order — each is checkable by a reader of the result:
- Name the corpora queried, or state that none exists for this stack.
- Cite the rows that changed a decision — not every row read.
- State the verification method and its caveats, never an unqualified
"works".
- List components reused before components added, so a duplicate is
visible rather than buried.
Write state.ticket["ui_apply"]:
ui_apply:
files: ["resources/js/UserCard.svelte"]
rendered:
"resources/js/UserCard.svelte": |
<full text, microcopy-locked>
components_added: ["UserCard"]
components_reused: ["Button"]
microcopy_lock: true
stack_corpus: # which corpora answered, or the degrade note
queried: ["svelte"]
cited: ["svelte.csv:12 — prefer stores over prop drilling"]
verify:
method: static_inspect # or playwright / screenshot
caveats: ["render not verified — no browser available"]
Gotchas
- Do not write framework prose into this skill. The moment it explains how
Svelte stores work, it stops being one maintainable surface and starts being
sixteen. Framework knowledge belongs in the corpus.
axes.reactivity: unknown is not none. unknown means a project has
manifests and no recognised reactivity layer — proceed, and say the stack was
not recognised. none means there genuinely is no reactivity layer, which is
the normal shape for a static page.
- A meta-framework needs its own query. Querying only
--stack vue for a
Nuxt project silently drops the routing, data-fetching and SSR idioms that
are the whole reason Nuxt exists.
- The generic contract is a floor, not a ceiling. Where an overlay skill is
dispatched with this one, its framework rules win on their subject.
- The floor now lives in exactly one place, and that is the point. Overlay
composition applies this contract to every lane, so a future change to any of
its seven items is a one-point edit here rather than four lane patches that
drift apart. Concretely: the five-states requirement reaches every lane
through this skill. That requirement is deliberately unconditional — an
explicit
n/a is the escape for a surface that genuinely has no such state
(asserted in ui_lane_matrix.test.ts), so this is not a defect being
broadened. But if the decision is ever revisited, revisit it here.
Do NOT
- Emit framework code from memory and present it as grounded.
- Skip the corpus query because the stack "looks obvious".
- Claim a render or an interaction was verified when no primitive was available.
- Invent states, sections, or copy the brief does not carry.
- Treat a missing corpus as an evidence gap — it is a missing pack, and the two
must not be recorded the same way.
See also
1---2name: ui-apply-generic3description: Use when implementing a UI brief on a stack with no framework executor — Svelte, Astro, Angular, plain HTML. Stack-independent sibling of react-shadcn-ui; idiom from the stack corpus.4---56# ui-apply-generic78> The `plain` lane used to be a name with nothing behind it. This skill is the9> lane: it carries the implementation discipline that previously lived **only**10> inside the framework executors, and it gets framework idiom from the 16-stack11> corpus instead of from prose written here.12>13> That split is the whole point. One skill plus a corpus serves Svelte, Astro,14> Angular, Alpine, htmx and everything future at once. Sixteen framework skills15> would serve the same set and cost a single maintainer sixteen surfaces to keep16> current — the enumeration this package refuses.1718## When to use1920- `state.stack.frontend` resolves to `plain`, or to a label with no21 framework-specific overlay.22- A stack whose `axes.reactivity` or `axes.meta` is recognised but has no23 executor skill (`svelte`, `angular`, `astro`, `solid`, `qwik`, `htmx`).24- As the base of a composition: an overlay skill (`livewire`, `flux`,25 `blade-ui`, `react-shadcn-ui`) adds framework specifics **on top** of this26 contract, it does not replace it.2728Do NOT use when a framework executor already covers the whole job — then this29skill is the base and the executor is the overlay, dispatched together.3031## Procedure3233### Step 1 — Query the stack corpus (mandatory)3435Read `state.stack.axes` and query per resolved axis value, most specific first:36`meta` → `reactivity` → `component_lib`.3738```bash39<skills-root>/corpus-grounding/scripts/ground search \40 --manifest <skills-root>/design-intelligence/data/manifest.json \41 --stack <axis-value> "<the concrete question>"42```4344`axes.meta: nuxt` with `axes.reactivity: vue` means **two** queries —45`--stack nuxtjs` and `--stack vue`. A meta-framework does not replace the layer46it wraps; that conflation is the defect the axes exist to fix.4748**Cite what you used.** The result names the corpus rows the implementation49followed. An uncited pick is indistinguishable from the model's memory, and50memory is exactly what the corpus exists to replace.5152**No corpus domain for the detected stack** → say so, in the result:5354> No stack corpus for `<stack>` — proceeding on the generic contract. Framework55> idiom below is not grounded and should be reviewed by someone who knows this56> stack.5758Silence is the failure mode. An unstated gap reads as grounded output.5960### Step 2 — Apply the stack-independent contract6162Every item is a hard requirement, and none of them is framework-specific:63641. **Verbatim floor.** Microcopy comes from `state.ui_design.microcopy` exactly65 as written — every label, empty-state line, and validation message. No66 paraphrase, no improvement. Where a source artifact was provided, it beats67 the brief (see `design-fidelity`).682. **Token discipline.** Colour, spacing, radius and shadow values come from the69 project's tokens. A raw hex or arbitrary px that no token backs is a finding,70 not a choice. Validate with `design-tokens`' `tokens validate`.713. **Component reuse.** Check `state.ui_audit.components_found` before creating72 anything. In a run that has already added components, re-read the component73 directories — the audit inventory is computed once per state-file and does74 not refresh (see `existing-ui-audit` § Gotchas).754. **a11y floor.** Semantic elements over `div` + role; every interactive76 element reachable and labelled; focus visible; contrast meets the project's77 stated level, AA when unstated.785. **All five states.** `empty`, `loading`, `error`, `success`, `disabled` per79 the brief. An explicit `n/a` is legitimate for a surface that genuinely has80 no such state — declaring that is the opposite of inventing filler.816. **Asset discipline.** Copy referenced assets into the project's asset path.82 Never hotlink; never fabricate a logo or a screenshot.837. **No placeholders.** `<placeholder>`, `lorem`, `todo:`, `tbd`, `xxx` are84 rejected at the boundary — including inside arrays.8586### Step 3 — Verify, with honest degrade8788Exercise the result with whatever the host actually has, and name which:8990| Available | Do |91|---|---|92| Browser / Playwright | Render, check the states, exercise one interaction |93| Screenshot only | Capture and inspect layout at 375 / 768 / 1280 |94| Neither | Static inspection only, and **say** the render is unverified |9596Never claim a state or interaction works without having exercised it. A caveat97is a finding; a silent claim is a defect.9899## Output format100101Four requirements, in order — each is checkable by a reader of the result:1021031. **Name the corpora queried**, or state that none exists for this stack.1042. **Cite the rows that changed a decision** — not every row read.1053. **State the verification method and its caveats**, never an unqualified106 "works".1074. **List components reused before components added**, so a duplicate is108 visible rather than buried.109110Write `state.ticket["ui_apply"]`:111112```yaml113ui_apply:114 files: ["resources/js/UserCard.svelte"]115 rendered:116 "resources/js/UserCard.svelte": |117 <full text, microcopy-locked>118 components_added: ["UserCard"]119 components_reused: ["Button"]120 microcopy_lock: true121 stack_corpus: # which corpora answered, or the degrade note122 queried: ["svelte"]123 cited: ["svelte.csv:12 — prefer stores over prop drilling"]124 verify:125 method: static_inspect # or playwright / screenshot126 caveats: ["render not verified — no browser available"]127```128129## Gotchas130131- **Do not write framework prose into this skill.** The moment it explains how132 Svelte stores work, it stops being one maintainable surface and starts being133 sixteen. Framework knowledge belongs in the corpus.134- **`axes.reactivity: unknown` is not `none`.** `unknown` means a project has135 manifests and no recognised reactivity layer — proceed, and say the stack was136 not recognised. `none` means there genuinely is no reactivity layer, which is137 the normal shape for a static page.138- **A meta-framework needs its own query.** Querying only `--stack vue` for a139 Nuxt project silently drops the routing, data-fetching and SSR idioms that140 are the whole reason Nuxt exists.141- **The generic contract is a floor, not a ceiling.** Where an overlay skill is142 dispatched with this one, its framework rules win on their subject.143- **The floor now lives in exactly one place, and that is the point.** Overlay144 composition applies this contract to every lane, so a future change to any of145 its seven items is a one-point edit here rather than four lane patches that146 drift apart. Concretely: the five-states requirement reaches every lane147 through this skill. That requirement is deliberately unconditional — an148 explicit `n/a` is the escape for a surface that genuinely has no such state149 (asserted in `ui_lane_matrix.test.ts`), so this is not a defect being150 broadened. But if the decision is ever revisited, revisit it here.151152## Do NOT153154- Emit framework code from memory and present it as grounded.155- Skip the corpus query because the stack "looks obvious".156- Claim a render or an interaction was verified when no primitive was available.157- Invent states, sections, or copy the brief does not carry.158- Treat a missing corpus as an evidence gap — it is a missing pack, and the two159 must not be recorded the same way.160161## See also162163- [`design-intelligence`](../design-intelligence/SKILL.md) — the `--stack`164 corpus this skill queries (16 stacks).165- [`existing-ui-audit`](../existing-ui-audit/SKILL.md) — the inventory Step 2166 checks, and its once-per-state-file limit.167- [`design-tokens`](../design-tokens/SKILL.md) — `tokens validate`.168- [`fe-design`](../fe-design/SKILL.md) — where the brief's selection decisions169 come from, and what it does when the corpus is not installed.170- [`ui-component-architect`](../ui-component-architect/SKILL.md),171 [`tailwind-engineer`](../tailwind-engineer/SKILL.md) — stack-neutral172 companions this skill composes with.