Skip to main content
skill Claude Code CX Codex Cursor GitHub Copilot

frontend-ui-engineering — Claude Code skill: what it does & install

Enforces production standards for component architecture, WCAG 2.1 AA accessibility, and design systems. Stops AI models from defaulting to purple buttons, heavy shadows, and arbitrary spacing.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add addyosmani/agent-skills --skill frontend-ui-engineering -a claude-code
Open on GitHub

What frontend-ui-engineering does

The skill instructs coding assistants to structure code like human engineers. It mandates component colocation, placing tests, stories, types, and hooks together in the component directory. Component composition takes priority over massive prop objects. It also separates data containers from pure rendering logic and forbids prop drilling deeper than three levels.

Visual rules eliminate the usual AI aesthetic. The assistant will not generate purple palettes, excessive gradients, generic hero grids, or rounded-2xl corners on everything. Spacing sticks to a fixed 0.25rem scale, colors require semantic tokens, and typography follows strict heading levels without skips.

Add this skill if AI agents keep cluttering your project with unstyled div clicks and bloated configurations.

What it helps with

  • eliminate generic AI defaults like purple gradients and excessive corner radii
  • separate data-fetching containers from presentational components
  • implement keyboard navigation and contrast matching WCAG 2.1 AA
  • organise component directories with colocated tests, hooks, and types

Example prompts for the agent

  • Build a TaskList component using composition instead of configuration props
  • Check this layout against WCAG 2.1 AA for keyboard accessibility and contrast
  • Refactor the component tree to avoid prop drilling deeper than 3 levels

How to install frontend-ui-engineering

1Skills CLI (Vercel)

npx skills add addyosmani/agent-skills --skill frontend-ui-engineering -a claude-code

2Manually: put the files in place

~/.claude/skills/frontend-ui-engineering/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/frontend-ui-engineering/

From the same set25

The whole set →
code-review-and-quality addyosmani Five review axes and a limit on diff size, so an agent checks a change before merge instead of after. Claude Code CX Codex Cursor +1 72,500installs security-and-hardening addyosmani Guides threat modeling and security checks for code that handles user input, authentication, sessions, or external services. Use it when building a feature that accepts untrusted data or reviewing code before release. Claude Code CX Codex Cursor +1 69,400installs performance-optimization addyosmani An agent skill that measures before it changes code: Core Web Vitals budgets, N+1 queries, missing indexes and slow endpoints. Claude Code CX Codex Cursor +1 64,500installs spec-driven-development addyosmani Enforces writing a structured specification before coding. Useful when starting new features, tackling vague requirements, or making architectural decisions. Claude Code CX Codex Cursor +1 64,300installs planning-and-task-breakdown addyosmani Breaks specifications into small, testable tasks with clear acceptance criteria. Prevents agents from jumping straight into coding before dependencies and risks are mapped. Claude Code CX Codex Cursor +1 63,600installs documentation-and-adrs addyosmani Captures architectural decisions (ADRs) and the context behind code changes. Useful for tracking design choices, API updates, and trade-offs. Claude Code CX Codex Cursor +1 63,200installs code-simplification addyosmani Clarifies code and removes unnecessary complexity without altering behavior. Useful when refactoring working features that feel harder to maintain than they should. Claude Code CX Codex Cursor +1 62,200installs debugging-and-error-recovery addyosmani This skill guides an agent from reproducing a failure to checking the fix. Use it when tests fail, a build breaks, or runtime behavior differs from expectations. Claude Code CX Codex Cursor +1 62,200installs

Similar

banner-design claudekit Generates banners for social media, ads, and web hero sections using HTML/CSS. Useful when you need fast visual creative assets directly in your coding agent. Claude Code CX Codex Cursor +1 39,000installs slides claudekit Builds strategic HTML presentations using Chart.js and design tokens. Useful for generating pitch decks and marketing slides directly from the agent. Claude Code CX Codex Cursor +1 38,400installs vercel-optimize vercel-labs A skill that audits Vercel spend and speed: it gathers usage and route metrics first, then recommends code and config changes. Claude Code CX Codex Cursor +1 110,000installs ai-sdk vercel Teaches your coding agent to use the Vercel AI SDK accurately. It forces the model to read installed package docs instead of relying on memory. Claude Code CX Codex Cursor +1 66,000installs frontend-design official anthropics This skill guides intentional visual design for new interfaces and redesigns. Use it when a generic generated UI is not enough. Claude Code Claude.ai 1,025,790installs design-taste-frontend Leonxlnx This skill directs the design of public pages and work screens, then checks the result in a browser through screenshots. Use it when an interface feels generic or unfinished. Claude Code CX Codex Cursor +1 673,100installs prototype Matt Pocock Creates throwaway prototypes for checking state logic or exploring UI before committing the decision to the main codebase. Claude Code 986,201installs hyperframes heygen-com Instructs coding agents on creating, validating, and rendering HTML-based videos using the HyperFrames framework and CLI. Claude Code CX Codex Cursor +1 1,200,000installs

Questions about frontend-ui-engineering

How to install frontend-ui-engineering in Claude Code?

Run npx skills add addyosmani/agent-skills --skill frontend-ui-engineering -a claude-code. The file will be written to ~/.claude/skills/frontend-ui-engineering/SKILL.md.

What does frontend-ui-engineering do?

It instructs your AI assistant to follow strict UI architecture patterns, respect design tokens, and stop outputting clichéd AI styles like purple buttons and stock card grids.

Which accessibility standard does this skill enforce?

It enforces WCAG 2.1 AA compliance, including a 4.5:1 text contrast ratio, strict heading hierarchies, and keyboard focusability on interactive elements.

Source text

SKILL.md · MIT
---
name: frontend-ui-engineering
description: Builds production-quality, accessible, responsive user-facing UIs. Use when building or modifying interfaces and pages, creating components, implementing layouts, meeting WCAG accessibility requirements, managing state, or when the output needs to look and feel production-quality rather than AI-generated.
---

# Frontend UI Engineering

## Overview

Build production-quality user interfaces that are accessible, performant, and visually polished. The goal is UI that looks like it was built by a design-aware engineer at a top company — not like it was generated by an AI. This means real design system adherence, proper accessibility, thoughtful interaction patterns, and no generic "AI aesthetic."

## When to Use

- Building new UI components or pages
- Modifying existing user-facing interfaces
- Implementing responsive layouts
- Adding interactivity or state management
- Fixing visual or UX issues

## Component Architecture

### File Structure

Colocate everything related to a component:

```
src/components/
  TaskList/
    TaskList.tsx          # Component implementation
    TaskList.test.tsx     # Tests
    TaskList.stories.tsx  # Storybook stories (if using)
    use-task-list.ts      # Custom hook (if complex state)
    types.ts              # Component-specific types (if needed)
```

### Component Patterns

**Prefer composition over configuration:**

```tsx
// Good: Composable
<Card>
  <CardHeader>
    <CardTitle>Tasks</CardTitle>
  </CardHeader>
  <CardBody>
    <TaskList tasks={tasks} />
  </CardBody>
</Card>

// Avoid: Over-configured
<Card
  title="Tasks"
  headerVariant="large"
  bodyPadding="md"
  content={<TaskList tasks={tasks} />}
/>
```

**Keep components focused:**

```tsx
// Good: Does one thing
export function TaskItem({ task, onToggle, onDelete }: TaskItemProps) {
  return (
    <li className="flex items-center gap-3 p-3">
      <Checkbox checked={task.done} onChange={() => onToggle(task.id)} />
      <span className={task.done ? 'line-through text-muted' : ''}>{task.title}</span>
      <Button variant="ghost" size="sm" onClick={() => onDelete(task.id)}>
        <TrashIcon />
      </Button>
    </li>
  );
}
```

**Separate data fetching from presentation:**

```tsx
// Container: handles data
export function TaskListContainer() {
  const { tasks, isLoading, error, refetch } = useTasks();

  if (isLoading) return <TaskListSkeleton />;
  if (error) return <ErrorState message="Failed to load tasks" retry={refetch} />;
  if (tasks.length === 0) return <EmptyState message="No tasks yet" />;

  return <TaskList tasks={tasks} />;
}

// Presentation: handles rendering
export function TaskList({ tasks }: { tasks: Task[] }) {
  return (
    <ul role="list" className="divide-y">
      {tasks.map(task => <TaskItem key={task.id} task={task} />)}
    </ul>
  );
}
```

## State Management

**Choose the simplest approach that works:**

```
Local state (useState)           → Component-specific UI state
Lifted state                     → Shared between 2-3 sibling components
Context                          → Theme, auth, locale (read-heavy, write-rare)
URL state (searchParams)         → Filters, pagination, shareable UI state
Server state (React Query, SWR)  → Remote data with caching
Global store (Zustand, Redux)    → Complex client state shared app-wide
```

**Avoid prop drilling deeper than 3 levels.** If you're passing props through components that don't use them, introduce context or restructure the component tree.

## Design System Adherence

### Reference-led UI quality

When the product needs a distinct visual direction, collect evidence before choosing a layout:

1. Search a trusted reference catalogue or use references supplied by the product team.
2. Study two or three relevant screens. Record decisions about hierarchy, density, navigation, controls, responsive behavior, and interaction states.
3. Turn those decisions into a short design contract before implementation. Name the screen's job, primary action, required states, responsive rules, and patterns to reject.
4. Rebuild the useful structure in the product's own components, tokens, content, and visual language. Never copy another product's branding, proprietary text, imagery, or exact layout.

Use references as evidence, not as templates. If references are unavailable, document the assumptions and verify the result against the product's existing design system.

### Avoid the AI Aesthetic

AI-generated UI has recognizable patterns. Avoid all of them:

| AI Default | Why It Is a Problem | Production Quality |
|---|---|---|
| Purple/indigo everything | Models default to visually "safe" palettes, making every app look identical | Use the project's actual color palette |
| Excessive gradients | Gradients add visual noise and clash with most design systems | Flat or subtle gradients matching the design system |
| Rounded everything (rounded-2xl) | Maximum rounding signals "friendly" but ignores the hierarchy of corner radii in real designs | Consistent border-radius from the design system |
| Generic hero sections | Template-driven layout with no connection to the actual content or user need | Content-first layouts |
| Lorem ipsum-style copy | Placeholder text hides layout problems that real content reveals (length, wrapping, overflow) | Realistic placeholder content |
| Oversized padding everywhere | Equal generous padding destroys visual hierarchy and wastes screen space | Consistent spacing scale |
| Stock card grids | Uniform grids are a layout shortcut that ignores information priority and scanning patterns | Purpose-driven layouts |
| Shadow-heavy design | Layered shadows add depth that competes with content and slows rendering on low-end devices | Subtle or no shadows unless the design system specifies |

### Spacing and Layout

Use a consistent spacing scale. Don't invent values:

```css
/* Use the scale: 0.25rem increments (or whatever the project uses) */
/* Good */  padding: 1rem;      /* 16px */
/* Good */  gap: 0.75rem;       /* 12px */
/* Bad */   padding: 13px;      /* Not on any scale */
/* Bad */   margin-top: 2.3rem; /* Not on any scale */
```

### Typography

Respect the type hierarchy:

```
h1 → Page title (one per page)
h2 → Section title
h3 → Subsection title
body → Default text
small → Secondary/helper text
```

Don't skip heading levels. Don't use heading styles for non-heading content.

### Color

- Use semantic color tokens: `text-primary`, `bg-surface`, `border-default` — not raw hex values
- Ensure sufficient contrast (4.5:1 for normal text, 3:1 for large text)
- Don't rely solely on color to convey information (use icons, text, or patterns too)

## Accessibility (WCAG 2.1 AA)

Every component must meet these standards:

### Keyboard Navigation

```tsx
// Every interactive element must be keyboard accessible
<button onClick={handleClick}>Click me</button>        // ✓ Focusable by default
<div onClick={handleClick}>Click me</div>               // ✗ Not focusable
<div role="button" tabIndex={0} onClick={handleClick}    // ✓ But prefer <button>
     onKeyDown={e => {
       if (e.key === 'Enter') handleClick();
       if (e.key === ' ') e.preventDefault();
     }}
     onKeyUp={e => {
       if (e.key === ' ') handleClick();
     }}>
  Click me
</div>
```

### ARIA Labels

```tsx
// Label interactive elements that lack visible text
<button aria-label="Close dialog"><XIcon /></button>

// Label form inputs
<label htmlFor="email">Email</label>
<input id="email" type="email" />

// Or use aria-label when no visible label exists
<input aria-label="Search tasks" type="search" />
```

### Focus Management

```tsx
// Move focus when content changes
function Dialog({ isOpen, onClose }: DialogProps) {
  const closeRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    if (isOpen) closeRef.current?.focus();
  }, [isOpen]);

  // Trap focus inside dialog when open
  return (
    <dialog open={isOpen}>
      <button ref={closeRef} onClick={onClose}>Close</button>
      {/* dialog content */}
    </dialog>
  );
}
```

### Meaningful Empty and Error States

```tsx
// Don't show blank screens
function TaskList({ tasks }: { tasks: Task[] }) {
  if (tasks.length === 0) {
    return (
      <div role="status" className="text-center py-12">
        <TasksEmptyIcon className="mx-auto h-12 w-12 text-muted" />
        <h3 className="mt-2 text-sm font-medium">No tasks</h3>
        <p className="mt-1 text-sm text-muted">Get started by creating a new task.</p>
        <Button className="mt-4" onClick={onCreateTask}>Create Task</Button>
      </div>
    );
  }

  return <ul role="list">...</ul>;
}
```

## Responsive Design

Design for mobile first, then expand:

```tsx
// Tailwind: mobile-first responsive
<div className="
  grid grid-cols-1      /* Mobile: single column */
  sm:grid-cols-2        /* Small: 2 columns */
  lg:grid-cols-3        /* Large: 3 columns */
  gap-4
">
```

Test at these breakpoints: 320px, 768px, 1024px, 1440px.

## Loading and Transitions

```tsx
// Skeleton loading (not spinners for content)
function TaskListSkeleton() {
  return (
    <div className="space-y-3" aria-busy="true" aria-label="Loading tasks">
      {Array.from({ length: 3 }).map((_, i) => (
        <div key={i} className="h-12 bg-muted animate-pulse rounded" />
      ))}
    </div>
  );
}

// Optimistic updates for perceived speed
function useToggleTask() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: toggleTask,
    onMutate: async (taskId) => {
      await queryClient.cancelQueries({ queryKey: ['tasks'] });
      const previous = queryClient.getQueryData(['tasks']);

      queryClient.setQueryData(['tasks'], (old: Task[]) =>
        old.map(t => t.id === taskId ? { ...t, done: !t.done } : t)
      );

      return { previous };
    },
    onError: (_err, _taskId, context) => {
      queryClient.setQueryData(['tasks'], context?.previous);
    },
  });
}
```

## See Also

For detailed accessibility requirements and testing tools, see `../../references/accessibility-checklist.md`.

## Common Rationalizations

| Rationalization | Reality |
|---|---|
| "Accessibility is a nice-to-have" | It's a legal requirement in many jurisdictions and an engineering quality standard. |
| "We'll make it responsive later" | Retrofitting responsive design is 3x harder than building it from the start. |
| "The design isn't final, so I'll skip styling" | Use the design system defaults. Unstyled UI creates a broken first impression for reviewers. |
| "This is just a prototype" | Prototypes become production code. Build the foundation right. |
| "The AI aesthetic is fine for now" | It signals low quality. Use the project's actual design system from the start. |

## Red Flags

- Components with more than 200 lines (split them)
- Inline styles or arbitrary pixel values
- Missing error states, loading states, or empty states
- No keyboard navigation testing
- Color as the sole indicator of state (red/green without text or icons)
- Generic "AI look" (purple gradients, oversized cards, stock layouts)

## Verification

After building UI:

- [ ] Component renders without console errors
- [ ] All interactive elements are keyboard accessible (Tab through the page)
- [ ] Screen reader can convey the page's content and structure
- [ ] Responsive: works at 320px, 768px, 1024px, 1440px
- [ ] Loading, empty, error, success, and permission states handled when applicable
- [ ] Follows the project's design system (spacing, colors, typography)
- [ ] The rendered result passes a final UI-specific finish-gate review
- [ ] No accessibility warnings in dev tools or axe-core

© addyosmani · MIT · addyosmani/agent-skills

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor