Skip to content

Landing an AI-generated design as Vue SFCs

When a design arrives as a Claude Design "Send to Claude Code" bundle, a claude.ai artifact, or any HTML/React mockup, the goal is working Vue SFCs against PrimeVue + the active preset — not a literal port of the bundle. The bundle is reference material; the brand already lives in the preset.

This document is the canonical repo-side procedure. The design-handoff-build skill at .agents/skills/design-handoff-build/ carries the pre-flight checklists and forbidden-patterns lists that enforce the moves below.

Principle: the bundle is a requirements doc, not a visual spec

The Claude Design bundle (or any AI mockup) tells you what data is shown, what actions exist, what decisions the screen enables — the business intent. It does NOT tell you how to render it in OnRamp. The bundle's inline hex colors, custom shells, ad-hoc layouts, and density choices are a sketch, not load-bearing.

It is expected — and desirable — that the generated UI looks materially different from the bundle. The bundle's intent is what you preserve. The rendering follows the OnRamp design system + PrimeVue Aura conventions.

If you find yourself trying to match the bundle's layout structure exactly, stop. You're translating a wireframe instead of designing a product page.

The design decision hierarchy

Every non-trivial rendering decision walks a numbered ladder, stopping at the first step that gives a concrete answer. The canonical ladder — all six steps, in order — lives in .agents/skills/design-handoff-build/references/decision-hierarchy.md; walk it there rather than a copy here.

Two notes specific to this repo's current state:

  • Golden references exist (see conventions.md "Golden references") — read the one matching your screen's shape before generating. The canonical recipes in conventions.md (e.g. §4 for the tinted-icon-badge pattern, <Button :severity rounded text>) are the prose behind them; for shapes with no registry row yet (detail/edit, modal/drawer), the recipes do that step's work.
  • Sakai is inspiration, not law. It uses raw ramp utilities (bg-blue-100 text-blue-500), !important (text-xl!), and <div class="card"> — all forbidden in OnRamp. Translate Sakai's intent through OnRamp composites and severity primitives; never copy its markup.

Required moves (in order)

  1. Pick the app and alias. This procedure targets org-admin → app/ui-organization/ (@/); it sets the active preset, cssLayer, and dark selector — see the cssLayer guardrail in .claude/rules/ui-design-system.md. A customer-portal screen is a Mode-2 migration — defer to /primevue + ui-customer-primevue, build under pages/v2/**, never the frozen pages/private/**; the org conventions here do not apply unmodified.

  2. Map every primitive to PrimeVue v4 BEFORE writing. Open the cheatsheet in the design-handoff-build skill (.agents/skills/design-handoff-build/references/component-cheatsheet.md) and walk the design — for every card, chart, filter, status indicator, tab, button, etc., pick the PrimeVue answer.

    If a primitive isn't in the cheatsheet, look it up via @primevue/mcp first. Falling back: https://primevue.org/<component>.md. The pinned version is in .claude/rules/ui-design-system.md ("Stack & PrimeVue v4 names").

    Hand-rolling is a failure mode. If you find yourself writing <div class="card"> or <svg>...<path d="M...">, stop — there's a PrimeVue component for that.

    Anything with truly no PrimeVue equivalent (e.g. some heatmaps) stays a custom composite under app/ui-organization/components/composites/ — never inline in the page file.

  3. Severity, never color names. Map every status/state to a meaning per the canonical severity vocabulary in .claude/rules/ui-design-system.md ("Severity is meaning, not intensity") — danger / warn / success / info / secondary / primary. Apply via :severity="…" on PrimeVue components, never a color name (severity="amber") and never a raw ramp utility (text-red-500, bg-amber-100 — both forbidden). The severity → color resolution is owned by the preset; don't encode it here.

  4. Mock data rule — severity codes, never colors. Color values in mock data are severity codes only ('danger', 'warn', etc.) — never token strings, never hex. The canonical prohibition (with the why and the grep pattern) is docs/design-system/forbidden-patterns.md #3; charts resolve severity → color through the composites/chart/ layer (conventions.md §5).

  5. Write the SFC in <script setup>. Import PrimeVue components and use them directly — the active preset themes them. No :pt/:dt defaults (only as named, commented escape hatches for specific gaps), no .p-* scoped color overrides, no .cp-prime-* classes, no useOnRampTheme.

  6. Use tokens, never hex. Reference --color-* for brand/neutral values and var(--vendor-color) where vendor branding applies. For brand color in non-PrimeVue surfaces (SVG, JS color math), use useOnRampBrand from @onramp/theme/onramp-brand.

  7. If a needed semantic is missing, fix it at the right layer. A brand value → design-system/DESIGN.md + bun run tokens. An app-level semantic (page ground, severity palette) or deliberate deviation → the app preset (app/ui-organization/theme/preset.js). Never patch at the call site.

  8. Self-check against the forbidden-patterns list. Before declaring done, grep your output for the entries in .agents/skills/design-handoff-build/references/forbidden-patterns.md. Raw ramp utilities, hex, !important, v3 component names, color stored as data — these must all be zero matches.

  9. Run /design-handoff-eval on the output. Mandatory final step. The eval produces a structured drift report; surface findings and fix the high-priority ones (or explicitly flag and accept them) before declaring the task done.

  10. Browser-verify — run the light/dark/vendor-color checklist in .claude/rules/ui-design-system.md. If you can't run the dev server this session, say so explicitly rather than claiming the UI works.

Prompt templates

Implement a design as org-admin UI:

Build <feature> as a Vue 3.5 <script setup> SFC under app/ui-organization/. Compose on PrimeVue v4 components (auto-themed by the active org preset — no :pt/:dt, no .p-* scoped color CSS, no !important utilities). Map every primitive via the cheatsheet at .agents/skills/design-handoff-build/references/component-cheatsheet.md. Color through :severity or semantic primeui utilities only — never raw ramp (text-red-500), never hex. Mock data carries severity codes, never token strings or hex. Run /design-handoff-eval before declaring done.

Land a Claude Design artifact:

Here's a Claude Design bundle for <screen>. Treat the HTML as reference only. Emit Vue SFCs against PrimeVue + the active preset; map its primitives to v4 PrimeVue components via the cheatsheet; drop its inline colors (the preset carries the brand). Store severity codes in mock data, never colors. Follow the workflow doc, run the forbidden-patterns self-check, then invoke /design-handoff-eval and surface its findings.

Change a brand token:

Update <token> in design-system/DESIGN.md, run bun run tokens, and commit the regenerated design-system/generated/*. Don't hand-edit generated files.

Why the moves matter

The first version of this workflow described principles but not moves — generations defaulted to "do whatever the bundle shows", which meant hand-rolled card shells, hex colors, raw ramp utilities, !important overrides. The second version enforced technical compliance (severity codes, no raw ramp, no !important) but missed visual polish — generations passed the forbidden-patterns grep yet looked like wireframes.

This third version (decision hierarchy + polish checklist + bundle-as- requirements-doc reframe) is meant to close that loop: the output should look like a real PrimeVue Aura dashboard rendered in OnRamp identity, not a clean wireframe and not a Sakai clone.

The moves above (decision hierarchy, severity codes, polish checklist self-check, eval pass) are the difference between "starting point I can iterate on" and "starting point I have to rewrite."

  • .claude/rules/ui-design-system.md — the canonical UI conventions (auto-loads for agents on app/ui-* edits; human-readable directly).
  • design-system/DESIGN.md — canonical token source.
  • .agents/skills/design-handoff-build/ — skill with the cheatsheet and forbidden patterns; invoke via /design-handoff-build.
  • .agents/skills/design-handoff-eval/ — skill for the mandatory post-generation eval; invoke via /design-handoff-eval.
  • /primevue skill (.agents/skills/primevue/) — migration playbook, component mapping, theming patterns, anti-patterns.
  • docs/primevue-migration-example.md — a worked migration example.

Internal documentation — gated behind Cloudflare Access.