This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
When to Invoke This Skill
Automatically activate for:
-
Building UI components, pages, dashboards, or applications
-
Creating landing pages, forms, or interactive interfaces
-
Designing data visualizations or charts
-
Implementing design systems or component libraries
-
Any frontend work where visual quality matters
Design Thinking
Before coding, understand the context and commit to a BOLD aesthetic direction:
-
Purpose: What problem does this interface solve? Who uses it?
-
Tone: Pick a distinctive aesthetic:
-
Brutally minimal | Maximalist chaos | Retro-futuristic
-
Organic/natural | Luxury/refined | Playful/toy-like
-
Editorial/magazine | Brutalist/raw | Art deco/geometric
-
Soft/pastel | Industrial/utilitarian | Neo-brutalist
-
Swiss/grid-based | Cyberpunk/neon | Scandinavian/calm
-
Constraints: Technical requirements (framework, performance, accessibility)
-
Differentiation: What makes this UNFORGETTABLE?
CRITICAL: Choose a clear conceptual direction and execute it with precision.
Technology Stack Preferences
Component Libraries (Priority Order)
-
shadcn/ui - First choice for React projects. Copy components, full customization.
-
Radix UI - Accessible primitives when shadcn isn't available
-
Headless UI - For Tailwind-based projects
-
Custom CSS - When libraries aren't appropriate
Data Visualization
-
Recharts - First choice for charts in React. Clean, composable, customizable.
-
Tremor - Dashboard-ready charts with great defaults
-
Victory - When Recharts doesn't fit
-
D3.js - For complex, custom visualizations only
Styling
-
Tailwind CSS - Utility-first, consistent spacing/colors
-
CSS Variables - For theming and design tokens
-
CSS Modules - When Tailwind isn't available
Animation
-
Framer Motion - First choice for React animations
-
CSS animations - For simple, performant effects
-
GSAP - For complex timeline animations
Anti-Slop Design Rules
NEVER Use These (AI Slop Indicators)
Typography Slop:
-
Inter, Roboto, Arial, system-ui as primary fonts
-
Font sizes that are too uniform (everything 14-16px)
-
Generic font pairings (Inter + Inter)
Color Slop:
-
Purple/violet gradients on white backgrounds
-
Blue-to-purple CTA buttons
-
Washed-out, low-contrast color schemes
-
Rainbow gradients for no reason
-
Generic blue (#3B82F6) as primary color
Layout Slop:
-
Perfectly centered everything
-
Cards with equal rounded corners (rounded-lg everywhere)
-
Symmetric layouts with no visual hierarchy
-
Grid of 3-4 identical cards pattern
-
Hero with centered text + gradient background + floating shapes
Component Slop:
-
Glassmorphism on everything
-
Shadows that are too soft and uniform
-
Generic avatar circles with gradient backgrounds
-
Empty state illustrations that are too cute
-
Progress bars with gradient fills
Animation Slop:
-
Fade-in on scroll for everything
-
Bounce effects on buttons
-
Spinning loaders when skeleton screens work better
-
Hover effects that all feel the same
INSTEAD, Create Distinctive Design
Typography That Stands Out:
Display fonts: Clash Display, Cabinet Grotesk, Satoshi, Space Grotesk (sparingly), Instrument Serif, Fraunces, Playfair Display, Editorial New Body fonts: Geist, Plus Jakarta Sans, DM Sans, Source Serif Pro, Literata Monospace: JetBrains Mono, Fira Code, IBM Plex Mono
-
Create contrast between display and body fonts
-
Use larger type than feels comfortable (48px+ for headlines)
-
Vary font weights dramatically (300 vs 700)
Color With Intent:
-
Pick ONE dominant color and use it sparingly
-
Use near-black (#0A0A0A, #111111) instead of pure black
-
Create depth with subtle gradients in backgrounds
-
Use color for meaning, not decoration
-
Consider dark mode as primary (not afterthought)
Layouts That Break the Grid:
-
Asymmetric compositions with clear hierarchy
-
Overlapping elements that create depth
-
Generous negative space OR intentional density
-
Grid-breaking hero elements
-
Varying content widths within the same page
Components With Character:
-
Micro-interactions that feel tactile
-
Loading states that match the brand
-
Error states that are helpful and on-brand
-
Empty states that guide rather than decorate
-
Form inputs that feel substantial
React Component Architecture
Design components like you are the creator of React. Think in composition, reusability, and elegance.
Component Philosophy
Small, Focused Components:
-
Each component does ONE thing well
-
Prefer 20-50 lines per component
-
If a component exceeds 100 lines, split it
-
Name components by what they ARE, not what they DO
Composition Over Configuration:
// BAD: Monolithic component with many props <Card title="User Profile" subtitle="Settings" avatar={user.avatar} showBadge={true} badgeColor="green" actions={[...]} />
// GOOD: Composable components <Card> <Card.Header> <Avatar src={user.avatar} /> <Card.Title>User Profile</Card.Title> <Badge variant="success" /> </Card.Header> <Card.Content>...</Card.Content> <Card.Actions>...</Card.Actions> </Card>
Props Design Principles
Meaningful, Typed Props:
// Generic, reusable props interface ButtonProps { variant?: 'primary' | 'secondary' | 'ghost' | 'destructive'; size?: 'sm' | 'md' | 'lg'; loading?: boolean; disabled?: boolean; children: React.ReactNode; }
// State props that tell a story interface DataTableProps<T> { data: T[]; columns: Column<T>[]; isLoading?: boolean; isEmpty?: boolean; onRowClick?: (row: T) => void; selectedRows?: Set<string>; }
Prop Patterns:
-
Use children for content (not content prop)
-
Use render props for customization: renderItem , renderEmpty
-
Use compound patterns for complex UIs
-
Avoid boolean props when variants work better
State Management
Local State First:
// Keep state as close to where it's used as possible function SearchInput({ onSearch }: { onSearch: (query: string) => void }) { const [query, setQuery] = useState(''); const debouncedSearch = useDebouncedCallback(onSearch, 300);
return ( <Input value={query} onChange={(e) => { setQuery(e.target.value); debouncedSearch(e.target.value); }} /> ); }
Lift State Only When Needed:
-
Lift when siblings need to share state
-
Lift when parent needs to control behavior
-
Don't lift "just in case"
Component Patterns
- Container/Presenter Pattern:
// Container: handles data fetching, state function UserProfileContainer({ userId }: { userId: string }) { const { data: user, isLoading } = useUser(userId); if (isLoading) return <UserProfileSkeleton />; return <UserProfile user={user} />; }
// Presenter: pure UI, receives props function UserProfile({ user }: { user: User }) { return ( <Card> <Avatar src={user.avatar} /> <h2>{user.name}</h2> </Card> ); }
- Compound Components:
// Parent provides context const TabsContext = createContext<TabsContextValue>(null);
function Tabs({ children, defaultValue }: TabsProps) { const [active, setActive] = useState(defaultValue); return ( <TabsContext.Provider value={{ active, setActive }}> <div className="tabs">{children}</div> </TabsContext.Provider> ); }
Tabs.List = TabsList; Tabs.Tab = Tab; Tabs.Panel = TabPanel;
// Usage <Tabs defaultValue="overview"> <Tabs.List> <Tabs.Tab value="overview">Overview</Tabs.Tab> <Tabs.Tab value="settings">Settings</Tabs.Tab> </Tabs.List> <Tabs.Panel value="overview">...</Tabs.Panel> </Tabs>
- Render Props for Flexibility:
interface ListProps<T> { items: T[]; renderItem: (item: T, index: number) => React.ReactNode; renderEmpty?: () => React.ReactNode; keyExtractor: (item: T) => string; }
function List<T>({ items, renderItem, renderEmpty, keyExtractor }: ListProps<T>) { if (items.length === 0 && renderEmpty) return renderEmpty(); return ( <ul> {items.map((item, i) => ( <li key={keyExtractor(item)}>{renderItem(item, i)}</li> ))} </ul> ); }
File Organization
components/ ├── ui/ # Primitive components (Button, Input, Card) │ ├── button.tsx │ ├── input.tsx │ └── card.tsx ├── patterns/ # Composed patterns (DataTable, Form, Modal) │ ├── data-table/ │ │ ├── data-table.tsx │ │ ├── data-table-header.tsx │ │ ├── data-table-row.tsx │ │ └── index.ts │ └── form/ ├── features/ # Feature-specific components │ ├── dashboard/ │ └── settings/ └── layouts/ # Page layouts ├── sidebar-layout.tsx └── centered-layout.tsx
Anti-Patterns to Avoid
Component Slop:
-
Giant 500+ line components
-
Props drilling through 5+ levels
-
useEffect for everything
-
Inline styles mixed with Tailwind
-
any types on props
Instead:
-
Split into smaller, focused components
-
Use Context or composition for deep data
-
Prefer derived state over effects
-
Consistent styling approach
-
Strict TypeScript types
shadcn/ui Quick Reference
Core Philosophy: shadcn/ui is NOT a component library—it's how you build your component library. You get actual component code that you own and can modify.
Quick Start
Initialize shadcn/ui
npx shadcn@latest init
Add components
npx shadcn@latest add button card dialog
Search registry
npx shadcn@latest search @shadcn -q "button"
Key Principles
-
Open Code: Full transparency, easy customization, AI-readable
-
Composition: Common, composable interface across all components
-
Distribution: Flat-file schema + CLI for easy installation
-
Beautiful Defaults: Great design out-of-the-box, easily customizable
-
AI-Ready: Open code structure for LLMs to understand and improve
Component Categories
Category Components
Form & Input Form, Field, Button, Input, Textarea, Checkbox, Radio, Select, Switch, Slider, Calendar, Date Picker, Combobox
Layout & Navigation Accordion, Breadcrumb, Navigation Menu, Sidebar, Tabs, Separator, Scroll Area, Resizable
Overlays & Dialogs Dialog, Alert Dialog, Sheet, Drawer, Popover, Tooltip, Hover Card, Context Menu, Dropdown Menu, Command
Feedback & Status Alert, Toast, Progress, Spinner, Skeleton, Badge, Empty
Display & Media Avatar, Card, Table, Data Table, Chart, Carousel, Aspect Ratio, Typography
Theming Basics
// Color convention: background + foreground <div className="bg-background text-foreground">Hello</div> <div className="bg-primary text-primary-foreground">Primary</div> <div className="bg-muted text-muted-foreground">Muted</div>
Customization Tips
Customize the theme - Don't use defaults
:root { --radius: 0.5rem; /* or 0 for sharp corners / --primary: 220 13% 10%; / custom primary */ }
Extend components - Add custom variants, modify animations, adjust spacing
Combine primitives - Layer components for unique effects
For Complete Documentation
See references/shadcn.md for:
-
Complete components.json configuration
-
Full theming system with CSS variables
-
Dark mode setup guide
-
CLI commands reference
-
MCP server integration
-
Registry schema for publishing components
Recharts Quick Reference
When creating charts:
Style the chart to match the UI
<ResponsiveContainer> <LineChart data={data}> <Line type="monotone" strokeWidth={2} dot={false} stroke="hsl(var(--primary))" /> <XAxis tickLine={false} axisLine={false} tick={{ fill: 'hsl(var(--muted-foreground))' }} /> </LineChart> </ResponsiveContainer>
Remove visual clutter
-
Hide axis lines when not needed
-
Use subtle grid lines or none
-
Custom tooltips that match your design
Add meaningful interactions
-
Hover states that reveal detail
-
Click handlers for drill-down
-
Animate data changes smoothly
Implementation Checklist
Before considering frontend work complete:
-
Typography creates clear hierarchy (display vs body)
-
Colors are intentional and consistent (CSS variables)
-
Spacing follows a rhythm (8px/4px grid)
-
Interactive elements have hover/focus/active states
-
Loading and empty states exist
-
Dark mode works (if applicable)
-
Animations are smooth (60fps, no jank)
-
Accessibility: keyboard navigation, ARIA labels, color contrast
-
Mobile responsive (or explicitly desktop-only)
-
Code is production-ready (no console logs, proper error handling)
Output Format
When implementing frontend:
-
Explain the aesthetic direction (2-3 sentences)
-
List key design decisions (typography, colors, key components)
-
Provide complete, working code with:
-
All imports and dependencies noted
-
CSS/Tailwind classes included
-
TypeScript types when applicable
-
Comments for non-obvious choices
Remember: Claude is capable of extraordinary creative work. Commit fully to a distinctive vision that could only have been designed for this specific context.