Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
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.
Automatically activate for:
Before coding, understand the context and commit to a BOLD aesthetic direction:
CRITICAL: Choose a clear conceptual direction and execute it with precision.
Typography Slop:
Color Slop:
Layout Slop:
Component Slop:
Animation Slop:
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
Color With Intent:
Layouts That Break the Grid:
Components With Character:
Design components like you are the creator of React. Think in composition, reusability, and elegance.
Small, Focused Components:
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>
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:
children for content (not content prop)renderItem, renderEmptyLocal 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:
1. 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>
);
}
2. 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>
3. 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>
);
}
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
Component Slop:
useEffect for everythingany types on propsInstead:
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.
# 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"
| 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 |
// 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>
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
See references/shadcn.md for:
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
Add meaningful interactions
Before considering frontend work complete:
When implementing frontend:
Remember: Claude is capable of extraordinary creative work. Commit fully to a distinctive vision that could only have been designed for this specific context.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer