Frontend Design Skill
This skill enforces a single principle: work WITH the framework, never against it. Use the component library natively. Use the CSS framework idiomatically. Let the design system do its job.
The user provides frontend requirements: a component, page, or interface to build or modify.
Core Philosophy
Don't fight the framework. Use it as it was designed to be used.
Every frontend framework and component library has an intended way to be used. The job of this skill is to ensure that every line of frontend code respects that intent. Customization happens through the channels the framework provides — not by bypassing them.
Step 1: Codebase Context Discovery (MANDATORY)
Before writing any code, scan the codebase. This step is non-negotiable.
What to Detect
- Frontend framework — Check for: , , , , , , ,
- Component library — Check dependencies for: PrimeVue, shadcn/ui, Vuetify, MUI, Chakra UI, Ant Design, Radix, Mantine, Quasar, Element Plus, Headless UI
- CSS framework — Check for: Tailwind (, directives), SCSS, CSS Modules, etc.
- Theme configuration — Find the theming mechanism:
- PrimeVue: theme preset in (Aura, Lara, Nora), design token overrides
- Vuetify: theme config
- MUI: config
- Tailwind: or block (v4)
- Existing component patterns — Examine 2-3 existing components to understand how the library is used in practice
State your findings before proceeding. Example: "Detected: Vue 3 + PrimeVue (Aura preset) + Tailwind CSS. I will use PrimeVue components natively with Tailwind for layout only."
Step 2: Framework-Native Implementation
The Golden Rule
Use every component, utility, and API the way the framework documentation shows it. If the framework has a built-in way to do something, use it. Do not invent alternatives.
Component Library Rules
These rules apply regardless of which component library the project uses (PrimeVue, MUI, Vuetify, shadcn/ui, etc.):
ALWAYS:
- Use the library's components directly with their documented props and API
- Customize appearance through the library's theming system (design tokens, theme presets, theme config)
- Use the library's built-in variants, severities, and sizes (, , etc.)
- Use the library's slot system when you need to customize content areas
- Follow the library's documented patterns for forms, dialogs, tables, etc.
- Use the library's icons and icon integration as documented
NEVER:
- Override component internals with CSS targeting internal class names or DOM structure
- Create wrapper components that re-style library components from the outside
- Use to override library styles
- Duplicate functionality that already exists in the library (if it has a Tooltip, use it)
- Mix components from multiple UI libraries in the same project
PrimeVue-Specific Rules
PrimeVue v4 uses a design token system with presets (Aura, Lara, Nora). This is the ONLY supported customization path.
NEVER do this:
- Use the PassThrough () API to restyle components with Tailwind classes
- Use mode to strip PrimeVue's styles and rebuild from scratch
- Use utility to override preset styling
- Create wrapper components that apply overrides globally
- Target PrimeVue's internal CSS classes (, , etc.) in your stylesheets
- Add Tailwind utility classes to PrimeVue component root elements to override their appearance
DO this instead:
- Pick a theme preset (Aura, Lara, Nora) and use it
- Customize through PrimeVue's design token system in or theme config:
typescript
app.use(PrimeVue, {
theme: {
preset: Aura,
options: {
prefix: 'p',
darkModeSelector: '.dark-mode',
cssLayer: { name: 'primevue', order: 'tailwind-base, primevue, tailwind-utilities' }
}
}
})
- Override design tokens at the theme level when you need different colors or spacing:
typescript
import { definePreset } from '@primevue/themes'
import Aura from '@primevue/themes/aura'
const MyPreset = definePreset(Aura, {
semantic: {
primary: {
50: '{indigo.50}',
// ...
950: '{indigo.950}'
}
}
})
- Use component props as documented: , , , , , , etc.
- Use PrimeVue's built-in CSS layer ordering to ensure Tailwind and PrimeVue coexist cleanly
Why no ? The PassThrough API fights the framework. It bypasses the theming system, creates maintenance burden when PrimeVue updates internal DOM structure, and produces code that is neither idiomatic PrimeVue nor idiomatic Tailwind. The design token system exists precisely so you don't need
.
CSS Framework Rules (Tailwind)
When the project uses Tailwind CSS, follow these rules on every frontend change:
ALWAYS:
- Use Tailwind utility classes directly in templates — this is the primary styling mechanism
- Follow mobile-first responsive design: base styles first, then , , ,
- Use consistent class ordering: layout > positioning > box model > typography > visual > interactive
- Use the project's Tailwind config tokens (, not )
- Use complete class strings — never concatenate ( breaks the compiler)
- Use computed properties or lookup objects for dynamic classes
- Use
prettier-plugin-tailwindcss
for automatic class sorting if available
- Use Tailwind for layout, spacing, and typography on YOUR elements (not library components)
NEVER:
- Write custom CSS when a Tailwind utility exists for it
- Use excessively — prefer Vue components for abstraction instead of CSS classes
- Use arbitrary values () when a Tailwind scale value exists ()
- Concatenate class names dynamically (breaks purging in production)
- Mix CSS methodologies — if the project uses Tailwind, don't add CSS Modules or styled-components
- Use Tailwind utilities to override component library styles
Tailwind + Component Library coexistence:
- Tailwind handles: page layout, spacing between components, custom elements, typography on non-library elements
- Component library handles: component appearance, component spacing internals, interactive states
- They do NOT overlap: don't use Tailwind to restyle library components, don't use library classes for page layout
Tailwind Best Practices Checklist
Apply this checklist on every frontend change:
Step 3: What This Skill is NOT
This skill does NOT cover:
- Aesthetic direction or creative design — it enforces framework discipline, not visual creativity
- Framework-specific API patterns — defer to , for those
- Greenfield design system creation — use
create-design-system-rules
for that
What to AVOID — Summary
| Anti-pattern | Why it's wrong | What to do instead |
|---|
| API on PrimeVue components | Fights the framework's theming system | Use design tokens and |
| mode + Tailwind rebuild | Re-implements PrimeVue from scratch | Use a theme preset |
| Wrapper components with style overrides | Unnecessary abstraction, breaks on updates | Use components directly with props |
| overrides | Specificity wars, unmaintainable | Fix the root cause through theme config |
| Tailwind classes on library components | Two systems fighting for control | Let the library own its components |
| Custom CSS for things Tailwind does | Mixed methodologies | Use Tailwind utilities |
| everywhere | Defeats utility-first purpose | Extract Vue components instead |
| Arbitrary values () | Bypasses design token system | Use scale values () |
| Class concatenation () | Breaks Tailwind compiler purging | Use lookup objects |
| Targeting internal library classes | Breaks on library updates | Use library's theming API |
Complementary Skills
- vue-best-practices / react-best-practices — Framework-specific API patterns and component architecture
- create-design-system-rules — For projects without an established design system
- web-design-guidelines — For auditing accessibility and UI quality
Remember
The best frontend code is invisible. It uses the tools the project chose — the component library, the CSS framework, the theme system — exactly as they were meant to be used. No overrides. No workarounds. No cleverness that the next developer has to reverse-engineer.
Use the framework. Trust the framework. Don't fight the framework.