Skip to content
SkillVault logo SkillVault
Free Featured ChatGPT GPTs Claude Code Cursor

senior-frontend

Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS applications. Use when building React components, optimizing Next.js performance, analyzing bundle sizes, scaffolding frontend projects, implementing accessibility, or reviewing frontend code quality.

1 downloads 1 views Updated Oct 31, 2026 v1.0.0
senior-frontend skill cover

Overview

Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS applications. Use when building React components, optimizing Next.js performance, analyzing bundle sizes, scaffolding frontend projects, implementing accessibility, or reviewing frontend code quality.

Source: https://github.com/alirezarezvani/claude-skills · MIT · © 2025 Alireza Rezvani

System prompt

The instruction block that defines the agent's role, rules and output format.

system-prompt.txt
# Senior Frontend

Frontend development patterns, performance optimization, and automation tools for React/Next.js applications.

## Table of Contents

- [Project Scaffolding](#project-scaffolding)
- [Component Generation](#component-generation)
- [Bundle Analysis](#bundle-analysis)
- [React Patterns](#react-patterns)
- [Next.js Optimization](#nextjs-optimization)
- [Accessibility and Testing](#accessibility-and-testing)

---

## Project Scaffolding

Generate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations.

### Workflow: Create New Frontend Project

1. Run the scaffolder with your project name and template:
   ```bash
   python scripts/frontend_scaffolder.py my-app --template nextjs
   ```

2. Add optional features (auth, api, forms, testing, storybook):
   ```bash
   python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api
   ```

3. Navigate to the project and install dependencies:
   ```bash
   cd my-app && npm install
   ```

4. Start the development server:
   ```bash
   npm run dev
   ```

### Scaffolder Options

| Option | Description |
|--------|-------------|
| `--template nextjs` | Next.js 14+ with App Router and Server Components |
| `--template react` | React + Vite with TypeScript |
| `--features auth` | Add NextAuth.js authentication |
| `--features api` | Add React Query + API client |
| `--features forms` | Add React Hook Form + Zod validation |
| `--features testing` | Add Vitest + Testing Library |
| `--dry-run` | Preview files without creating them |

### Generated Structure (Next.js)

```
my-app/
├── app/
│   ├── layout.tsx        # Root layout with fonts
│   ├── page.tsx          # Home page
│   ├── globals.css       # Tailwind + CSS variables
│   └── api/health/route.ts
├── components/
│   ├── ui/               # Button, Input, Card
│   └── layout/           # Header, Footer, Sidebar
├── hooks/                # useDebounce, useLocalStorage
├── lib/                  # utils (cn), constants
├── types/                # TypeScript interfaces
├── tailwind.config.ts
├── next.config.js
└── package.json
```

---

## Component Generation

Generate React components with TypeScript, tests, and Storybook stories.

### Workflow: Create a New Component

1. Generate a client component:
   ```bash
   python scripts/component_generator.py Button --dir src/components/ui
   ```

2. Generate a server component:
   ```bash
   python scripts/component_generator.py ProductCard --type server
   ```

3. Generate with test and story files:
   ```bash
   python scripts/component_generator.py UserProfile --with-test --with-story
   ```

4. Generate a custom hook:
   ```bash
   python scripts/component_generator.py FormValidation --type hook
   ```

### Generator Options

| Option | Description |
|--------|-------------|
| `--type client` | Client component with 'use client' (default) |
| `--type server` | Async server component |
| `--type hook` | Custom React hook |
| `--with-test` | Include test file |
| `--with-story` | Include Storybook story |
| `--flat` | Create in output dir without subdirectory |
| `--dry-run` | Preview without creating files |

### Generated Component Example

```tsx
'use client';

import { useState } from 'react';
import { cn } from '@/lib/utils';

interface ButtonProps {
  className?: string;
  children?: React.ReactNode;
}

export function Button({ className, children }: ButtonProps) {
  return (
    <div className={cn('', className)}>
      {children}
    </div>
  );
}
```

---

## Bundle Analysis

Analyze package.json and project structure for bundle optimization opportunities.

### Workflow: Optimize Bundle Size

1. Run the analyzer on your project:
   ```bash
   python scripts/bundle_analyzer.py /path/to/project
   ```

2. Review the health score and issues:
   ```
   Bundle Health Score: 75/100 (C)

   HEAVY DEPENDENCIES:
     moment (290KB)
       Alternative: date-fns (12KB) or dayjs (2KB)

     lodash (71KB)
       Alternative: lodash-es with tree-shaking
   ```

3. Apply the recommended fixes by replacing heavy dependencies.

4. Re-run with verbose mode to check import patterns:
   ```bash
   python scripts/bundle_analyzer.py . --verbose
   ```

### Bundle Score Interpretation

| Score | Grade | Action |
|-------|-------|--------|
| 90-100 | A | Bundle is well-optimized |
| 80-89 | B | Minor optimizations available |
| 70-79 | C | Replace heavy dependencies |
| 60-69 | D | Multiple issues need attention |
| 0-59 | F | Critical bundle size problems |

### Heavy Dependencies Detected

The analyzer identifies these common heavy packages:

| Package | Size | Alternative |
|---------|------|-------------|
| moment | 290KB | date-fns (12KB) or dayjs (2KB) |
| lodash | 71KB | lodash-es with tree-shaking |
| axios | 14KB | Native fetch or ky (3KB) |
| jquery | 87KB | Native DOM APIs |
| @mui/material | Large | shadcn/ui or Radix UI |

---

## React Patterns

Reference: `references/react_patterns.md`

### Compound Components

Share state between related components:

```tsx
const Tabs = ({ children }) => {
  const [active, setActive] = useState(0);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
};

Tabs.List = TabList;
Tabs.Panel = TabPanel;

// Usage
<Tabs>
  <Tabs.List>
    <Tabs.Tab>One</Tabs.Tab>
    <Tabs.Tab>Two</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel>Content 1</Tabs.Panel>
  <Tabs.Panel>Content 2</Tabs.Panel>
</Tabs>
```

### Custom Hooks

Extract reusable logic:

```tsx
function useDebounce<T>(value: T, delay = 500): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Usage
const debouncedSearch = useDebounce(searchTerm, 300);
```

### Render Props

Share rendering logic:

```tsx
function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));
  }, [url]);

  return render({ data, loading });
}

// Usage
<DataFetcher
  url="/api/users"
  render={({ data, loading }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
/>
```

---

## Next.js Optimization

Reference: `references/nextjs_optimization_guide.md`

### Server vs Client Components

Use Server Components by default. Add 'use client' only when you need:
- Event handlers (onClick, onChange)
- State (useState, useReducer)
- Effects (useEffect)
- Browser APIs

```tsx
// Server Component (default) - no 'use client'
async function ProductPage({ params }) {
  const product = await getProduct(params.id);  // Server-side fetch

  return (
    <div>
      <h1>{product.name}</h1>
      <AddToCartButton productId={product.id} />  {/* Client component */}
    </div>
  );
}

// Client Component
'use client';
function AddToCartButton({ productId }) {
  const [adding, setAdding] = useState(false);
  return <button onClick={() => addToCart(productId)}>Add</button>;
}
```

### Image Optimization

```tsx
import Image from 'next/image';

// Above the fold - load immediately
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
/>

// Responsive image with fill
<div className="relative aspect-video">
  <Image
    src="/product.jpg"
    alt="Product"
    fill
    sizes="(max-width: 768px) 100vw, 50vw"
    className="object-cover"
  />
</div>
```

### Data Fetching Patterns

```tsx
// Parallel fetching
async function Dashboard() {
  const [user, stats] = await Promise.all([
    getUser(),
    getStats()
  ]);
  return <div>...</div>;
}

// Streaming with Suspense
async function ProductPage({ params }) {
  return (
    <div>
      <ProductDetails id={params.id} />
      <Suspense fallback={<ReviewsSkeleton />}>
        <Reviews productId={params.id} />
      </Suspense>
    </div>
  );
}
```

---

## Accessibility and Testing

Reference: `references/frontend_best_practices.md`

### Accessibility Checklist

1. **Semantic HTML**: Use proper elements (`<button>`, `<nav>`, `<main>`)
2. **Keyboard Navigation**: All interactive elements focusable
3. **ARIA Labels**: Provide labels for icons and complex widgets
4. **Color Contrast**: Minimum 4.5:1 for normal text
5. **Focus Indicators**: Visible focus states

```tsx
// Accessible button
<button
  type="button"
  aria-label="Close dialog"
  onClick={onClose}
  className="focus-visible:ring-2 focus-visible:ring-blue-500"
>
  <XIcon aria-hidden="true" />
</button>

// Skip link for keyboard users
<a href="#main-content" className="sr-only focus:not-sr-only">
  Skip to main content
</a>
```

### Testing Strategy

```tsx
// Component test with React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('button triggers action on click', async () => {
  const onClick = vi.fn();
  render(<Button onClick={onClick}>Click me</Button>);

  await userEvent.click(screen.getByRole('button'));
  expect(onClick).toHaveBeenCalledTimes(1);
});

// Test accessibility
test('dialog is accessible', async () => {
  render(<Dialog open={true} title="Confirm" />);

  expect(screen.getByRole('dialog')).toBeInTheDocument();
  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');
});
```

---

## Quick Reference

### Common Next.js Config

```js
// next.config.js
const nextConfig = {
  images: {
    remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }],
    formats: ['image/avif', 'image/webp'],
  },
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react'],
  },
};
```

### Tailwind CSS Utilities

```tsx
// Conditional classes with cn()
import { cn } from '@/lib/utils';

<button className={cn(
  'px-4 py-2 rounded',
  variant === 'primary' && 'bg-blue-500 text-white',
  disabled && 'opacity-50 cursor-not-allowed'
)} />
```

### TypeScript Patterns

```tsx
// Props with children
interface CardProps {
  className?: string;
  children: React.ReactNode;
}

// Generic component
interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return <ul>{items.map(renderItem)}</ul>;
}
```

---

## Resources

- React Patterns: `references/react_patterns.md`
- Next.js Optimization: `references/nextjs_optimization_guide.md`
- Best Practices: `references/frontend_best_practices.md`
- Forcing-question library (Matt Pocock grill): `references/forcing_questions.md`
- Composition map (which specialist to fork into): `references/composition_map.md`

---

## Assumptions and Verifiable Success Criteria (Karpathy discipline)

Before this skill scaffolds a component, recommends a framework, or audits a bundle, the following four assumptions MUST be surfaced.

1. **Primary user device + network** — mobile-4G, desktop-fiber, low-end-Android, or corporate-network. Drives every perf decision.
2. **LCP target in milliseconds** — a single number, not "fast." Drives bundle budget and rendering choice.
3. **SEO-dependent vs. auth-walled** — drives rendering (SSR/SSG/RSC vs. SPA).
4. **WCAG target + named a11y owner** — AA, AAA, or best-effort. Drives a11y investment and CI gates.

**Verifiable success criteria** (Karpathy #4) — every recommendation must include:

- Core Web Vitals targets (LCP, INP, CLS) at p75 on the primary device
- A per-route JS bundle budget in KB-gzip
- A Lighthouse a11y floor + perf floor

If any of those three is not stated, the recommendation is incomplete — return to Q2 of the forcing-question library.

The `scripts/frontend_decision_engine.py` tool encodes these checks: it refuses to recommend a profile without the four assumption inputs and prints the verifiable thresholds for the matched profile.

---

## Customization profiles

Four built-in profiles in `profiles/` calibrate every recommendation:

| Profile | When to pick | LCP target (mobile-4G p75) | Bundle budget |
|---|---|---|---|
| `next-app-router` | SaaS customer-facing, SEO + dynamic, RSC-first | 2000ms | 150 KB-gzip / route |
| `remix-or-sveltekit` | Mobile-4G primary, low-JS-first, progressive enhancement | 1500ms | 80 KB-gzip / route |
| `vite-spa` | Auth-walled app, desktop/corporate primary | 2500ms | 200 KB init + 80 KB / route |
| `astro-or-static` | Marketing / docs / blog, near-zero write, SEO-critical | 1200ms | 30 KB JS / page |

Pick a profile via:

```bash
python scripts/frontend_decision_engine.py \
  --primary-device mobile-4g --lcp-target-ms 2000 \
  --seo-dependent true --auth-walled false --team-size 5
```

The tool returns the best-fit profile, the runner-up tradeoff (if within 15%), the stack picks, the anti-patterns to avoid on that profile, and the required CI gates.

To add a custom profile (e.g., your org's internal-tool defaults): copy `profiles/vite-spa.json` to `profiles/<your-org>.json` and adjust `constraints` + `success_thresholds`.

---

## Composition map

This skill does NOT reimplement scope owned by the POWERFUL-tier specialists. It forks into them. See `references/composition_map.md` for the full routing table. Key forks:

| Concern | Fork into |
|---|---|
| WCAG audit, contrast, screen-reader | `engineering-team/skills/a11y-audit/` |
| Bundle profiling + runtime perf | `engineering/skills/performance-profiler/` |
| Cinematic / scroll-storytelling landing | `engineering-team/skills/epic-design/` |
| Apple HIG (iOS / macOS / visionOS) | `product-team/skills/apple-hig-expert/` |
| Pre-commit Karpathy review | `engineering/karpathy-coder/` |
| Pre-flight architecture grill | `engineering/grill-me/` |

The `cs-frontend-engineer` agent orchestrates these forks via `context: fork`. Invoke it from another agent with `Agent({subagent_type: "cs-frontend-engineer", prompt: "..."})` or via `/cs-frontend-review <your problem>`.

---

## Forcing-question library (Matt Pocock grill)

Before locking any framework or rendering decision, walk the seven forcing questions in `references/forcing_questions.md`. Discipline:

1. One question per turn. No bundling.
2. Always recommend the answer with cited canon.
3. Track answers in `/tmp/frontend-grill-<date>.md`.
4. If a kill criterion trips, stop. Don't scaffold around an unresolved gap.
5. After Q7, run `frontend_decision_engine.py` with the seven answers.

Summary:

1. Primary device + network?
2. LCP target in ms (and INP, CLS)?
3. RSC / SPA / SSR / SSG — pick and defend?
4. JS bundle budget per route?
5. SEO-dependent or auth-walled?
6. Design-system source of truth?
7. WCAG target + named a11y owner?

---

## Invocation from other agents and skills

Three surfaces:

1. **Slash command:** `/cs-frontend-review <prompt>` — full grill + decision engine + composition routing.
2. **Agent subagent:** `Agent({subagent_type: "cs-frontend-engineer", prompt: "..."})` — forks context, returns ≤ 200-word digest.
3. **Direct tool call:** `python scripts/frontend_decision_engine.py ...` — deterministic profile match when inputs are known.

See `agents/engineering/cs-frontend-engineer.md` for the full invocation contract.

User prompt template

Fill in the variables and send it to run the skill: {{variables}}

user-template.txt

Variables

Name Required Description Example

Full skill configuration

The standard .aiskill file in JSON and YAML.

senior-frontend.aiskill (JSON)
{
  "format": "aiskill/v1",
  "skill": {
    "name": "senior-frontend",
    "slug": "senior-frontend",
    "version": "1.0.0",
    "description": "Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS applications. Use when building React components, optimizing Next.js performance, analyzing bundle sizes, scaffolding frontend projects, implementing accessibility, or reviewing frontend code quality.",
    "category": "Development",
    "tags": [
      "engineering",
      "typescript",
      "frontend",
      "performance"
    ],
    "platforms": [
      "chatgpt",
      "claude-code",
      "cursor"
    ],
    "tested_environment": "Agent Skills convention (SKILL.md) — works with Claude Code, Cursor, ChatGPT/Codex and compatible agents",
    "license": "MIT"
  },
  "prompts": {
    "system": "# Senior Frontend\r\n\r\nFrontend development patterns, performance optimization, and automation tools for React/Next.js applications.\r\n\r\n## Table of Contents\r\n\r\n- [Project Scaffolding](#project-scaffolding)\r\n- [Component Generation](#component-generation)\r\n- [Bundle Analysis](#bundle-analysis)\r\n- [React Patterns](#react-patterns)\r\n- [Next.js Optimization](#nextjs-optimization)\r\n- [Accessibility and Testing](#accessibility-and-testing)\r\n\r\n---\r\n\r\n## Project Scaffolding\r\n\r\nGenerate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations.\r\n\r\n### Workflow: Create New Frontend Project\r\n\r\n1. Run the scaffolder with your project name and template:\r\n   ```bash\r\n   python scripts/frontend_scaffolder.py my-app --template nextjs\r\n   ```\r\n\r\n2. Add optional features (auth, api, forms, testing, storybook):\r\n   ```bash\r\n   python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api\r\n   ```\r\n\r\n3. Navigate to the project and install dependencies:\r\n   ```bash\r\n   cd my-app && npm install\r\n   ```\r\n\r\n4. Start the development server:\r\n   ```bash\r\n   npm run dev\r\n   ```\r\n\r\n### Scaffolder Options\r\n\r\n| Option | Description |\r\n|--------|-------------|\r\n| `--template nextjs` | Next.js 14+ with App Router and Server Components |\r\n| `--template react` | React + Vite with TypeScript |\r\n| `--features auth` | Add NextAuth.js authentication |\r\n| `--features api` | Add React Query + API client |\r\n| `--features forms` | Add React Hook Form + Zod validation |\r\n| `--features testing` | Add Vitest + Testing Library |\r\n| `--dry-run` | Preview files without creating them |\r\n\r\n### Generated Structure (Next.js)\r\n\r\n```\r\nmy-app/\r\n├── app/\r\n│   ├── layout.tsx        # Root layout with fonts\r\n│   ├── page.tsx          # Home page\r\n│   ├── globals.css       # Tailwind + CSS variables\r\n│   └── api/health/route.ts\r\n├── components/\r\n│   ├── ui/               # Button, Input, Card\r\n│   └── layout/           # Header, Footer, Sidebar\r\n├── hooks/                # useDebounce, useLocalStorage\r\n├── lib/                  # utils (cn), constants\r\n├── types/                # TypeScript interfaces\r\n├── tailwind.config.ts\r\n├── next.config.js\r\n└── package.json\r\n```\r\n\r\n---\r\n\r\n## Component Generation\r\n\r\nGenerate React components with TypeScript, tests, and Storybook stories.\r\n\r\n### Workflow: Create a New Component\r\n\r\n1. Generate a client component:\r\n   ```bash\r\n   python scripts/component_generator.py Button --dir src/components/ui\r\n   ```\r\n\r\n2. Generate a server component:\r\n   ```bash\r\n   python scripts/component_generator.py ProductCard --type server\r\n   ```\r\n\r\n3. Generate with test and story files:\r\n   ```bash\r\n   python scripts/component_generator.py UserProfile --with-test --with-story\r\n   ```\r\n\r\n4. Generate a custom hook:\r\n   ```bash\r\n   python scripts/component_generator.py FormValidation --type hook\r\n   ```\r\n\r\n### Generator Options\r\n\r\n| Option | Description |\r\n|--------|-------------|\r\n| `--type client` | Client component with 'use client' (default) |\r\n| `--type server` | Async server component |\r\n| `--type hook` | Custom React hook |\r\n| `--with-test` | Include test file |\r\n| `--with-story` | Include Storybook story |\r\n| `--flat` | Create in output dir without subdirectory |\r\n| `--dry-run` | Preview without creating files |\r\n\r\n### Generated Component Example\r\n\r\n```tsx\r\n'use client';\r\n\r\nimport { useState } from 'react';\r\nimport { cn } from '@/lib/utils';\r\n\r\ninterface ButtonProps {\r\n  className?: string;\r\n  children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({ className, children }: ButtonProps) {\r\n  return (\r\n    <div className={cn('', className)}>\r\n      {children}\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n---\r\n\r\n## Bundle Analysis\r\n\r\nAnalyze package.json and project structure for bundle optimization opportunities.\r\n\r\n### Workflow: Optimize Bundle Size\r\n\r\n1. Run the analyzer on your project:\r\n   ```bash\r\n   python scripts/bundle_analyzer.py /path/to/project\r\n   ```\r\n\r\n2. Review the health score and issues:\r\n   ```\r\n   Bundle Health Score: 75/100 (C)\r\n\r\n   HEAVY DEPENDENCIES:\r\n     moment (290KB)\r\n       Alternative: date-fns (12KB) or dayjs (2KB)\r\n\r\n     lodash (71KB)\r\n       Alternative: lodash-es with tree-shaking\r\n   ```\r\n\r\n3. Apply the recommended fixes by replacing heavy dependencies.\r\n\r\n4. Re-run with verbose mode to check import patterns:\r\n   ```bash\r\n   python scripts/bundle_analyzer.py . --verbose\r\n   ```\r\n\r\n### Bundle Score Interpretation\r\n\r\n| Score | Grade | Action |\r\n|-------|-------|--------|\r\n| 90-100 | A | Bundle is well-optimized |\r\n| 80-89 | B | Minor optimizations available |\r\n| 70-79 | C | Replace heavy dependencies |\r\n| 60-69 | D | Multiple issues need attention |\r\n| 0-59 | F | Critical bundle size problems |\r\n\r\n### Heavy Dependencies Detected\r\n\r\nThe analyzer identifies these common heavy packages:\r\n\r\n| Package | Size | Alternative |\r\n|---------|------|-------------|\r\n| moment | 290KB | date-fns (12KB) or dayjs (2KB) |\r\n| lodash | 71KB | lodash-es with tree-shaking |\r\n| axios | 14KB | Native fetch or ky (3KB) |\r\n| jquery | 87KB | Native DOM APIs |\r\n| @mui/material | Large | shadcn/ui or Radix UI |\r\n\r\n---\r\n\r\n## React Patterns\r\n\r\nReference: `references/react_patterns.md`\r\n\r\n### Compound Components\r\n\r\nShare state between related components:\r\n\r\n```tsx\r\nconst Tabs = ({ children }) => {\r\n  const [active, setActive] = useState(0);\r\n  return (\r\n    <TabsContext.Provider value={{ active, setActive }}>\r\n      {children}\r\n    </TabsContext.Provider>\r\n  );\r\n};\r\n\r\nTabs.List = TabList;\r\nTabs.Panel = TabPanel;\r\n\r\n// Usage\r\n<Tabs>\r\n  <Tabs.List>\r\n    <Tabs.Tab>One</Tabs.Tab>\r\n    <Tabs.Tab>Two</Tabs.Tab>\r\n  </Tabs.List>\r\n  <Tabs.Panel>Content 1</Tabs.Panel>\r\n  <Tabs.Panel>Content 2</Tabs.Panel>\r\n</Tabs>\r\n```\r\n\r\n### Custom Hooks\r\n\r\nExtract reusable logic:\r\n\r\n```tsx\r\nfunction useDebounce<T>(value: T, delay = 500): T {\r\n  const [debouncedValue, setDebouncedValue] = useState(value);\r\n\r\n  useEffect(() => {\r\n    const timer = setTimeout(() => setDebouncedValue(value), delay);\r\n    return () => clearTimeout(timer);\r\n  }, [value, delay]);\r\n\r\n  return debouncedValue;\r\n}\r\n\r\n// Usage\r\nconst debouncedSearch = useDebounce(searchTerm, 300);\r\n```\r\n\r\n### Render Props\r\n\r\nShare rendering logic:\r\n\r\n```tsx\r\nfunction DataFetcher({ url, render }) {\r\n  const [data, setData] = useState(null);\r\n  const [loading, setLoading] = useState(true);\r\n\r\n  useEffect(() => {\r\n    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));\r\n  }, [url]);\r\n\r\n  return render({ data, loading });\r\n}\r\n\r\n// Usage\r\n<DataFetcher\r\n  url=\"/api/users\"\r\n  render={({ data, loading }) =>\r\n    loading ? <Spinner /> : <UserList users={data} />\r\n  }\r\n/>\r\n```\r\n\r\n---\r\n\r\n## Next.js Optimization\r\n\r\nReference: `references/nextjs_optimization_guide.md`\r\n\r\n### Server vs Client Components\r\n\r\nUse Server Components by default. Add 'use client' only when you need:\r\n- Event handlers (onClick, onChange)\r\n- State (useState, useReducer)\r\n- Effects (useEffect)\r\n- Browser APIs\r\n\r\n```tsx\r\n// Server Component (default) - no 'use client'\r\nasync function ProductPage({ params }) {\r\n  const product = await getProduct(params.id);  // Server-side fetch\r\n\r\n  return (\r\n    <div>\r\n      <h1>{product.name}</h1>\r\n      <AddToCartButton productId={product.id} />  {/* Client component */}\r\n    </div>\r\n  );\r\n}\r\n\r\n// Client Component\r\n'use client';\r\nfunction AddToCartButton({ productId }) {\r\n  const [adding, setAdding] = useState(false);\r\n  return <button onClick={() => addToCart(productId)}>Add</button>;\r\n}\r\n```\r\n\r\n### Image Optimization\r\n\r\n```tsx\r\nimport Image from 'next/image';\r\n\r\n// Above the fold - load immediately\r\n<Image\r\n  src=\"/hero.jpg\"\r\n  alt=\"Hero\"\r\n  width={1200}\r\n  height={600}\r\n  priority\r\n/>\r\n\r\n// Responsive image with fill\r\n<div className=\"relative aspect-video\">\r\n  <Image\r\n    src=\"/product.jpg\"\r\n    alt=\"Product\"\r\n    fill\r\n    sizes=\"(max-width: 768px) 100vw, 50vw\"\r\n    className=\"object-cover\"\r\n  />\r\n</div>\r\n```\r\n\r\n### Data Fetching Patterns\r\n\r\n```tsx\r\n// Parallel fetching\r\nasync function Dashboard() {\r\n  const [user, stats] = await Promise.all([\r\n    getUser(),\r\n    getStats()\r\n  ]);\r\n  return <div>...</div>;\r\n}\r\n\r\n// Streaming with Suspense\r\nasync function ProductPage({ params }) {\r\n  return (\r\n    <div>\r\n      <ProductDetails id={params.id} />\r\n      <Suspense fallback={<ReviewsSkeleton />}>\r\n        <Reviews productId={params.id} />\r\n      </Suspense>\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n---\r\n\r\n## Accessibility and Testing\r\n\r\nReference: `references/frontend_best_practices.md`\r\n\r\n### Accessibility Checklist\r\n\r\n1. **Semantic HTML**: Use proper elements (`<button>`, `<nav>`, `<main>`)\r\n2. **Keyboard Navigation**: All interactive elements focusable\r\n3. **ARIA Labels**: Provide labels for icons and complex widgets\r\n4. **Color Contrast**: Minimum 4.5:1 for normal text\r\n5. **Focus Indicators**: Visible focus states\r\n\r\n```tsx\r\n// Accessible button\r\n<button\r\n  type=\"button\"\r\n  aria-label=\"Close dialog\"\r\n  onClick={onClose}\r\n  className=\"focus-visible:ring-2 focus-visible:ring-blue-500\"\r\n>\r\n  <XIcon aria-hidden=\"true\" />\r\n</button>\r\n\r\n// Skip link for keyboard users\r\n<a href=\"#main-content\" className=\"sr-only focus:not-sr-only\">\r\n  Skip to main content\r\n</a>\r\n```\r\n\r\n### Testing Strategy\r\n\r\n```tsx\r\n// Component test with React Testing Library\r\nimport { render, screen } from '@testing-library/react';\r\nimport userEvent from '@testing-library/user-event';\r\n\r\ntest('button triggers action on click', async () => {\r\n  const onClick = vi.fn();\r\n  render(<Button onClick={onClick}>Click me</Button>);\r\n\r\n  await userEvent.click(screen.getByRole('button'));\r\n  expect(onClick).toHaveBeenCalledTimes(1);\r\n});\r\n\r\n// Test accessibility\r\ntest('dialog is accessible', async () => {\r\n  render(<Dialog open={true} title=\"Confirm\" />);\r\n\r\n  expect(screen.getByRole('dialog')).toBeInTheDocument();\r\n  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');\r\n});\r\n```\r\n\r\n---\r\n\r\n## Quick Reference\r\n\r\n### Common Next.js Config\r\n\r\n```js\r\n// next.config.js\r\nconst nextConfig = {\r\n  images: {\r\n    remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }],\r\n    formats: ['image/avif', 'image/webp'],\r\n  },\r\n  experimental: {\r\n    optimizePackageImports: ['lucide-react', '@heroicons/react'],\r\n  },\r\n};\r\n```\r\n\r\n### Tailwind CSS Utilities\r\n\r\n```tsx\r\n// Conditional classes with cn()\r\nimport { cn } from '@/lib/utils';\r\n\r\n<button className={cn(\r\n  'px-4 py-2 rounded',\r\n  variant === 'primary' && 'bg-blue-500 text-white',\r\n  disabled && 'opacity-50 cursor-not-allowed'\r\n)} />\r\n```\r\n\r\n### TypeScript Patterns\r\n\r\n```tsx\r\n// Props with children\r\ninterface CardProps {\r\n  className?: string;\r\n  children: React.ReactNode;\r\n}\r\n\r\n// Generic component\r\ninterface ListProps<T> {\r\n  items: T[];\r\n  renderItem: (item: T) => React.ReactNode;\r\n}\r\n\r\nfunction List<T>({ items, renderItem }: ListProps<T>) {\r\n  return <ul>{items.map(renderItem)}</ul>;\r\n}\r\n```\r\n\r\n---\r\n\r\n## Resources\r\n\r\n- React Patterns: `references/react_patterns.md`\r\n- Next.js Optimization: `references/nextjs_optimization_guide.md`\r\n- Best Practices: `references/frontend_best_practices.md`\r\n- Forcing-question library (Matt Pocock grill): `references/forcing_questions.md`\r\n- Composition map (which specialist to fork into): `references/composition_map.md`\r\n\r\n---\r\n\r\n## Assumptions and Verifiable Success Criteria (Karpathy discipline)\r\n\r\nBefore this skill scaffolds a component, recommends a framework, or audits a bundle, the following four assumptions MUST be surfaced.\r\n\r\n1. **Primary user device + network** — mobile-4G, desktop-fiber, low-end-Android, or corporate-network. Drives every perf decision.\r\n2. **LCP target in milliseconds** — a single number, not \"fast.\" Drives bundle budget and rendering choice.\r\n3. **SEO-dependent vs. auth-walled** — drives rendering (SSR/SSG/RSC vs. SPA).\r\n4. **WCAG target + named a11y owner** — AA, AAA, or best-effort. Drives a11y investment and CI gates.\r\n\r\n**Verifiable success criteria** (Karpathy #4) — every recommendation must include:\r\n\r\n- Core Web Vitals targets (LCP, INP, CLS) at p75 on the primary device\r\n- A per-route JS bundle budget in KB-gzip\r\n- A Lighthouse a11y floor + perf floor\r\n\r\nIf any of those three is not stated, the recommendation is incomplete — return to Q2 of the forcing-question library.\r\n\r\nThe `scripts/frontend_decision_engine.py` tool encodes these checks: it refuses to recommend a profile without the four assumption inputs and prints the verifiable thresholds for the matched profile.\r\n\r\n---\r\n\r\n## Customization profiles\r\n\r\nFour built-in profiles in `profiles/` calibrate every recommendation:\r\n\r\n| Profile | When to pick | LCP target (mobile-4G p75) | Bundle budget |\r\n|---|---|---|---|\r\n| `next-app-router` | SaaS customer-facing, SEO + dynamic, RSC-first | 2000ms | 150 KB-gzip / route |\r\n| `remix-or-sveltekit` | Mobile-4G primary, low-JS-first, progressive enhancement | 1500ms | 80 KB-gzip / route |\r\n| `vite-spa` | Auth-walled app, desktop/corporate primary | 2500ms | 200 KB init + 80 KB / route |\r\n| `astro-or-static` | Marketing / docs / blog, near-zero write, SEO-critical | 1200ms | 30 KB JS / page |\r\n\r\nPick a profile via:\r\n\r\n```bash\r\npython scripts/frontend_decision_engine.py \\\r\n  --primary-device mobile-4g --lcp-target-ms 2000 \\\r\n  --seo-dependent true --auth-walled false --team-size 5\r\n```\r\n\r\nThe tool returns the best-fit profile, the runner-up tradeoff (if within 15%), the stack picks, the anti-patterns to avoid on that profile, and the required CI gates.\r\n\r\nTo add a custom profile (e.g., your org's internal-tool defaults): copy `profiles/vite-spa.json` to `profiles/<your-org>.json` and adjust `constraints` + `success_thresholds`.\r\n\r\n---\r\n\r\n## Composition map\r\n\r\nThis skill does NOT reimplement scope owned by the POWERFUL-tier specialists. It forks into them. See `references/composition_map.md` for the full routing table. Key forks:\r\n\r\n| Concern | Fork into |\r\n|---|---|\r\n| WCAG audit, contrast, screen-reader | `engineering-team/skills/a11y-audit/` |\r\n| Bundle profiling + runtime perf | `engineering/skills/performance-profiler/` |\r\n| Cinematic / scroll-storytelling landing | `engineering-team/skills/epic-design/` |\r\n| Apple HIG (iOS / macOS / visionOS) | `product-team/skills/apple-hig-expert/` |\r\n| Pre-commit Karpathy review | `engineering/karpathy-coder/` |\r\n| Pre-flight architecture grill | `engineering/grill-me/` |\r\n\r\nThe `cs-frontend-engineer` agent orchestrates these forks via `context: fork`. Invoke it from another agent with `Agent({subagent_type: \"cs-frontend-engineer\", prompt: \"...\"})` or via `/cs-frontend-review <your problem>`.\r\n\r\n---\r\n\r\n## Forcing-question library (Matt Pocock grill)\r\n\r\nBefore locking any framework or rendering decision, walk the seven forcing questions in `references/forcing_questions.md`. Discipline:\r\n\r\n1. One question per turn. No bundling.\r\n2. Always recommend the answer with cited canon.\r\n3. Track answers in `/tmp/frontend-grill-<date>.md`.\r\n4. If a kill criterion trips, stop. Don't scaffold around an unresolved gap.\r\n5. After Q7, run `frontend_decision_engine.py` with the seven answers.\r\n\r\nSummary:\r\n\r\n1. Primary device + network?\r\n2. LCP target in ms (and INP, CLS)?\r\n3. RSC / SPA / SSR / SSG — pick and defend?\r\n4. JS bundle budget per route?\r\n5. SEO-dependent or auth-walled?\r\n6. Design-system source of truth?\r\n7. WCAG target + named a11y owner?\r\n\r\n---\r\n\r\n## Invocation from other agents and skills\r\n\r\nThree surfaces:\r\n\r\n1. **Slash command:** `/cs-frontend-review <prompt>` — full grill + decision engine + composition routing.\r\n2. **Agent subagent:** `Agent({subagent_type: \"cs-frontend-engineer\", prompt: \"...\"})` — forks context, returns ≤ 200-word digest.\r\n3. **Direct tool call:** `python scripts/frontend_decision_engine.py ...` — deterministic profile match when inputs are known.\r\n\r\nSee `agents/engineering/cs-frontend-engineer.md` for the full invocation contract.",
    "user_template": ""
  },
  "variables": [],
  "install": {
    "steps": [
      {
        "title": "Download & unzip",
        "detail": "Download the .zip package from SkillVault and unzip it. The senior-frontend/ folder contains SKILL.md plus any companion scripts, references and assets."
      },
      {
        "title": "Copy into your agent skills directory",
        "detail": "Move the folder into your agent's skills directory — e.g. ~/.claude/skills/ (Claude Code), .codex/skills/, .cursor/skills/ or your project's .claude/skills/ folder — then restart or reload the session."
      },
      {
        "title": "Use it",
        "detail": "Describe the task in natural language; the agent loads the skill automatically when the request matches the skill description."
      }
    ]
  },
  "usage": {
    "steps": []
  },
  "metadata": {
    "author": "SkillVault",
    "source": "https://skillvault.top/skills/senior-frontend",
    "exported_at": "2026-11-03T06:36:14.962Z"
  }
}
senior-frontend.aiskill (YAML)
format: aiskill/v1
skill:
  name: senior-frontend
  slug: senior-frontend
  version: 1.0.0
  description: >-
    Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS applications. Use
    when building React components, optimizing Next.js performance, analyzing bundle sizes,
    scaffolding frontend projects, implementing accessibility, or reviewing frontend code quality.
  category: Development
  tags:
    - engineering
    - typescript
    - frontend
    - performance
  platforms:
    - chatgpt
    - claude-code
    - cursor
  tested_environment: >-
    Agent Skills convention (SKILL.md) — works with Claude Code, Cursor, ChatGPT/Codex and
    compatible agents
  license: MIT
prompts:
  system: "# Senior Frontend\r\n\r\nFrontend development patterns, performance optimization, and automation tools for React/Next.js applications.\r\n\r\n## Table of Contents\r\n\r\n- [Project Scaffolding](#project-scaffolding)\r\n- [Component Generation](#component-generation)\r\n- [Bundle Analysis](#bundle-analysis)\r\n- [React Patterns](#react-patterns)\r\n- [Next.js Optimization](#nextjs-optimization)\r\n- [Accessibility and Testing](#accessibility-and-testing)\r\n\r\n---\r\n\r\n## Project Scaffolding\r\n\r\nGenerate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations.\r\n\r\n### Workflow: Create New Frontend Project\r\n\r\n1. Run the scaffolder with your project name and template:\r\n   ```bash\r\n   python scripts/frontend_scaffolder.py my-app --template nextjs\r\n   ```\r\n\r\n2. Add optional features (auth, api, forms, testing, storybook):\r\n   ```bash\r\n   python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api\r\n   ```\r\n\r\n3. Navigate to the project and install dependencies:\r\n   ```bash\r\n   cd my-app && npm install\r\n   ```\r\n\r\n4. Start the development server:\r\n   ```bash\r\n   npm run dev\r\n   ```\r\n\r\n### Scaffolder Options\r\n\r\n| Option | Description |\r\n|--------|-------------|\r\n| `--template nextjs` | Next.js 14+ with App Router and Server Components |\r\n| `--template react` | React + Vite with TypeScript |\r\n| `--features auth` | Add NextAuth.js authentication |\r\n| `--features api` | Add React Query + API client |\r\n| `--features forms` | Add React Hook Form + Zod validation |\r\n| `--features testing` | Add Vitest + Testing Library |\r\n| `--dry-run` | Preview files without creating them |\r\n\r\n### Generated Structure (Next.js)\r\n\r\n```\r\nmy-app/\r\n├── app/\r\n│   ├── layout.tsx        # Root layout with fonts\r\n│   ├── page.tsx          # Home page\r\n│   ├── globals.css       # Tailwind + CSS variables\r\n│   └── api/health/route.ts\r\n├── components/\r\n│   ├── ui/               # Button, Input, Card\r\n│   └── layout/           # Header, Footer, Sidebar\r\n├── hooks/                # useDebounce, useLocalStorage\r\n├── lib/                  # utils (cn), constants\r\n├── types/                # TypeScript interfaces\r\n├── tailwind.config.ts\r\n├── next.config.js\r\n└── package.json\r\n```\r\n\r\n---\r\n\r\n## Component Generation\r\n\r\nGenerate React components with TypeScript, tests, and Storybook stories.\r\n\r\n### Workflow: Create a New Component\r\n\r\n1. Generate a client component:\r\n   ```bash\r\n   python scripts/component_generator.py Button --dir src/components/ui\r\n   ```\r\n\r\n2. Generate a server component:\r\n   ```bash\r\n   python scripts/component_generator.py ProductCard --type server\r\n   ```\r\n\r\n3. Generate with test and story files:\r\n   ```bash\r\n   python scripts/component_generator.py UserProfile --with-test --with-story\r\n   ```\r\n\r\n4. Generate a custom hook:\r\n   ```bash\r\n   python scripts/component_generator.py FormValidation --type hook\r\n   ```\r\n\r\n### Generator Options\r\n\r\n| Option | Description |\r\n|--------|-------------|\r\n| `--type client` | Client component with 'use client' (default) |\r\n| `--type server` | Async server component |\r\n| `--type hook` | Custom React hook |\r\n| `--with-test` | Include test file |\r\n| `--with-story` | Include Storybook story |\r\n| `--flat` | Create in output dir without subdirectory |\r\n| `--dry-run` | Preview without creating files |\r\n\r\n### Generated Component Example\r\n\r\n```tsx\r\n'use client';\r\n\r\nimport { useState } from 'react';\r\nimport { cn } from '@/lib/utils';\r\n\r\ninterface ButtonProps {\r\n  className?: string;\r\n  children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({ className, children }: ButtonProps) {\r\n  return (\r\n    <div className={cn('', className)}>\r\n      {children}\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n---\r\n\r\n## Bundle Analysis\r\n\r\nAnalyze package.json and project structure for bundle optimization opportunities.\r\n\r\n### Workflow: Optimize Bundle Size\r\n\r\n1. Run the analyzer on your project:\r\n   ```bash\r\n   python scripts/bundle_analyzer.py /path/to/project\r\n   ```\r\n\r\n2. Review the health score and issues:\r\n   ```\r\n   Bundle Health Score: 75/100 (C)\r\n\r\n   HEAVY DEPENDENCIES:\r\n     moment (290KB)\r\n       Alternative: date-fns (12KB) or dayjs (2KB)\r\n\r\n     lodash (71KB)\r\n       Alternative: lodash-es with tree-shaking\r\n   ```\r\n\r\n3. Apply the recommended fixes by replacing heavy dependencies.\r\n\r\n4. Re-run with verbose mode to check import patterns:\r\n   ```bash\r\n   python scripts/bundle_analyzer.py . --verbose\r\n   ```\r\n\r\n### Bundle Score Interpretation\r\n\r\n| Score | Grade | Action |\r\n|-------|-------|--------|\r\n| 90-100 | A | Bundle is well-optimized |\r\n| 80-89 | B | Minor optimizations available |\r\n| 70-79 | C | Replace heavy dependencies |\r\n| 60-69 | D | Multiple issues need attention |\r\n| 0-59 | F | Critical bundle size problems |\r\n\r\n### Heavy Dependencies Detected\r\n\r\nThe analyzer identifies these common heavy packages:\r\n\r\n| Package | Size | Alternative |\r\n|---------|------|-------------|\r\n| moment | 290KB | date-fns (12KB) or dayjs (2KB) |\r\n| lodash | 71KB | lodash-es with tree-shaking |\r\n| axios | 14KB | Native fetch or ky (3KB) |\r\n| jquery | 87KB | Native DOM APIs |\r\n| @mui/material | Large | shadcn/ui or Radix UI |\r\n\r\n---\r\n\r\n## React Patterns\r\n\r\nReference: `references/react_patterns.md`\r\n\r\n### Compound Components\r\n\r\nShare state between related components:\r\n\r\n```tsx\r\nconst Tabs = ({ children }) => {\r\n  const [active, setActive] = useState(0);\r\n  return (\r\n    <TabsContext.Provider value={{ active, setActive }}>\r\n      {children}\r\n    </TabsContext.Provider>\r\n  );\r\n};\r\n\r\nTabs.List = TabList;\r\nTabs.Panel = TabPanel;\r\n\r\n// Usage\r\n<Tabs>\r\n  <Tabs.List>\r\n    <Tabs.Tab>One</Tabs.Tab>\r\n    <Tabs.Tab>Two</Tabs.Tab>\r\n  </Tabs.List>\r\n  <Tabs.Panel>Content 1</Tabs.Panel>\r\n  <Tabs.Panel>Content 2</Tabs.Panel>\r\n</Tabs>\r\n```\r\n\r\n### Custom Hooks\r\n\r\nExtract reusable logic:\r\n\r\n```tsx\r\nfunction useDebounce<T>(value: T, delay = 500): T {\r\n  const [debouncedValue, setDebouncedValue] = useState(value);\r\n\r\n  useEffect(() => {\r\n    const timer = setTimeout(() => setDebouncedValue(value), delay);\r\n    return () => clearTimeout(timer);\r\n  }, [value, delay]);\r\n\r\n  return debouncedValue;\r\n}\r\n\r\n// Usage\r\nconst debouncedSearch = useDebounce(searchTerm, 300);\r\n```\r\n\r\n### Render Props\r\n\r\nShare rendering logic:\r\n\r\n```tsx\r\nfunction DataFetcher({ url, render }) {\r\n  const [data, setData] = useState(null);\r\n  const [loading, setLoading] = useState(true);\r\n\r\n  useEffect(() => {\r\n    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));\r\n  }, [url]);\r\n\r\n  return render({ data, loading });\r\n}\r\n\r\n// Usage\r\n<DataFetcher\r\n  url=\"/api/users\"\r\n  render={({ data, loading }) =>\r\n    loading ? <Spinner /> : <UserList users={data} />\r\n  }\r\n/>\r\n```\r\n\r\n---\r\n\r\n## Next.js Optimization\r\n\r\nReference: `references/nextjs_optimization_guide.md`\r\n\r\n### Server vs Client Components\r\n\r\nUse Server Components by default. Add 'use client' only when you need:\r\n- Event handlers (onClick, onChange)\r\n- State (useState, useReducer)\r\n- Effects (useEffect)\r\n- Browser APIs\r\n\r\n```tsx\r\n// Server Component (default) - no 'use client'\r\nasync function ProductPage({ params }) {\r\n  const product = await getProduct(params.id);  // Server-side fetch\r\n\r\n  return (\r\n    <div>\r\n      <h1>{product.name}</h1>\r\n      <AddToCartButton productId={product.id} />  {/* Client component */}\r\n    </div>\r\n  );\r\n}\r\n\r\n// Client Component\r\n'use client';\r\nfunction AddToCartButton({ productId }) {\r\n  const [adding, setAdding] = useState(false);\r\n  return <button onClick={() => addToCart(productId)}>Add</button>;\r\n}\r\n```\r\n\r\n### Image Optimization\r\n\r\n```tsx\r\nimport Image from 'next/image';\r\n\r\n// Above the fold - load immediately\r\n<Image\r\n  src=\"/hero.jpg\"\r\n  alt=\"Hero\"\r\n  width={1200}\r\n  height={600}\r\n  priority\r\n/>\r\n\r\n// Responsive image with fill\r\n<div className=\"relative aspect-video\">\r\n  <Image\r\n    src=\"/product.jpg\"\r\n    alt=\"Product\"\r\n    fill\r\n    sizes=\"(max-width: 768px) 100vw, 50vw\"\r\n    className=\"object-cover\"\r\n  />\r\n</div>\r\n```\r\n\r\n### Data Fetching Patterns\r\n\r\n```tsx\r\n// Parallel fetching\r\nasync function Dashboard() {\r\n  const [user, stats] = await Promise.all([\r\n    getUser(),\r\n    getStats()\r\n  ]);\r\n  return <div>...</div>;\r\n}\r\n\r\n// Streaming with Suspense\r\nasync function ProductPage({ params }) {\r\n  return (\r\n    <div>\r\n      <ProductDetails id={params.id} />\r\n      <Suspense fallback={<ReviewsSkeleton />}>\r\n        <Reviews productId={params.id} />\r\n      </Suspense>\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n---\r\n\r\n## Accessibility and Testing\r\n\r\nReference: `references/frontend_best_practices.md`\r\n\r\n### Accessibility Checklist\r\n\r\n1. **Semantic HTML**: Use proper elements (`<button>`, `<nav>`, `<main>`)\r\n2. **Keyboard Navigation**: All interactive elements focusable\r\n3. **ARIA Labels**: Provide labels for icons and complex widgets\r\n4. **Color Contrast**: Minimum 4.5:1 for normal text\r\n5. **Focus Indicators**: Visible focus states\r\n\r\n```tsx\r\n// Accessible button\r\n<button\r\n  type=\"button\"\r\n  aria-label=\"Close dialog\"\r\n  onClick={onClose}\r\n  className=\"focus-visible:ring-2 focus-visible:ring-blue-500\"\r\n>\r\n  <XIcon aria-hidden=\"true\" />\r\n</button>\r\n\r\n// Skip link for keyboard users\r\n<a href=\"#main-content\" className=\"sr-only focus:not-sr-only\">\r\n  Skip to main content\r\n</a>\r\n```\r\n\r\n### Testing Strategy\r\n\r\n```tsx\r\n// Component test with React Testing Library\r\nimport { render, screen } from '@testing-library/react';\r\nimport userEvent from '@testing-library/user-event';\r\n\r\ntest('button triggers action on click', async () => {\r\n  const onClick = vi.fn();\r\n  render(<Button onClick={onClick}>Click me</Button>);\r\n\r\n  await userEvent.click(screen.getByRole('button'));\r\n  expect(onClick).toHaveBeenCalledTimes(1);\r\n});\r\n\r\n// Test accessibility\r\ntest('dialog is accessible', async () => {\r\n  render(<Dialog open={true} title=\"Confirm\" />);\r\n\r\n  expect(screen.getByRole('dialog')).toBeInTheDocument();\r\n  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');\r\n});\r\n```\r\n\r\n---\r\n\r\n## Quick Reference\r\n\r\n### Common Next.js Config\r\n\r\n```js\r\n// next.config.js\r\nconst nextConfig = {\r\n  images: {\r\n    remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }],\r\n    formats: ['image/avif', 'image/webp'],\r\n  },\r\n  experimental: {\r\n    optimizePackageImports: ['lucide-react', '@heroicons/react'],\r\n  },\r\n};\r\n```\r\n\r\n### Tailwind CSS Utilities\r\n\r\n```tsx\r\n// Conditional classes with cn()\r\nimport { cn } from '@/lib/utils';\r\n\r\n<button className={cn(\r\n  'px-4 py-2 rounded',\r\n  variant === 'primary' && 'bg-blue-500 text-white',\r\n  disabled && 'opacity-50 cursor-not-allowed'\r\n)} />\r\n```\r\n\r\n### TypeScript Patterns\r\n\r\n```tsx\r\n// Props with children\r\ninterface CardProps {\r\n  className?: string;\r\n  children: React.ReactNode;\r\n}\r\n\r\n// Generic component\r\ninterface ListProps<T> {\r\n  items: T[];\r\n  renderItem: (item: T) => React.ReactNode;\r\n}\r\n\r\nfunction List<T>({ items, renderItem }: ListProps<T>) {\r\n  return <ul>{items.map(renderItem)}</ul>;\r\n}\r\n```\r\n\r\n---\r\n\r\n## Resources\r\n\r\n- React Patterns: `references/react_patterns.md`\r\n- Next.js Optimization: `references/nextjs_optimization_guide.md`\r\n- Best Practices: `references/frontend_best_practices.md`\r\n- Forcing-question library (Matt Pocock grill): `references/forcing_questions.md`\r\n- Composition map (which specialist to fork into): `references/composition_map.md`\r\n\r\n---\r\n\r\n## Assumptions and Verifiable Success Criteria (Karpathy discipline)\r\n\r\nBefore this skill scaffolds a component, recommends a framework, or audits a bundle, the following four assumptions MUST be surfaced.\r\n\r\n1. **Primary user device + network** — mobile-4G, desktop-fiber, low-end-Android, or corporate-network. Drives every perf decision.\r\n2. **LCP target in milliseconds** — a single number, not \"fast.\" Drives bundle budget and rendering choice.\r\n3. **SEO-dependent vs. auth-walled** — drives rendering (SSR/SSG/RSC vs. SPA).\r\n4. **WCAG target + named a11y owner** — AA, AAA, or best-effort. Drives a11y investment and CI gates.\r\n\r\n**Verifiable success criteria** (Karpathy #4) — every recommendation must include:\r\n\r\n- Core Web Vitals targets (LCP, INP, CLS) at p75 on the primary device\r\n- A per-route JS bundle budget in KB-gzip\r\n- A Lighthouse a11y floor + perf floor\r\n\r\nIf any of those three is not stated, the recommendation is incomplete — return to Q2 of the forcing-question library.\r\n\r\nThe `scripts/frontend_decision_engine.py` tool encodes these checks: it refuses to recommend a profile without the four assumption inputs and prints the verifiable thresholds for the matched profile.\r\n\r\n---\r\n\r\n## Customization profiles\r\n\r\nFour built-in profiles in `profiles/` calibrate every recommendation:\r\n\r\n| Profile | When to pick | LCP target (mobile-4G p75) | Bundle budget |\r\n|---|---|---|---|\r\n| `next-app-router` | SaaS customer-facing, SEO + dynamic, RSC-first | 2000ms | 150 KB-gzip / route |\r\n| `remix-or-sveltekit` | Mobile-4G primary, low-JS-first, progressive enhancement | 1500ms | 80 KB-gzip / route |\r\n| `vite-spa` | Auth-walled app, desktop/corporate primary | 2500ms | 200 KB init + 80 KB / route |\r\n| `astro-or-static` | Marketing / docs / blog, near-zero write, SEO-critical | 1200ms | 30 KB JS / page |\r\n\r\nPick a profile via:\r\n\r\n```bash\r\npython scripts/frontend_decision_engine.py \\\r\n  --primary-device mobile-4g --lcp-target-ms 2000 \\\r\n  --seo-dependent true --auth-walled false --team-size 5\r\n```\r\n\r\nThe tool returns the best-fit profile, the runner-up tradeoff (if within 15%), the stack picks, the anti-patterns to avoid on that profile, and the required CI gates.\r\n\r\nTo add a custom profile (e.g., your org's internal-tool defaults): copy `profiles/vite-spa.json` to `profiles/<your-org>.json` and adjust `constraints` + `success_thresholds`.\r\n\r\n---\r\n\r\n## Composition map\r\n\r\nThis skill does NOT reimplement scope owned by the POWERFUL-tier specialists. It forks into them. See `references/composition_map.md` for the full routing table. Key forks:\r\n\r\n| Concern | Fork into |\r\n|---|---|\r\n| WCAG audit, contrast, screen-reader | `engineering-team/skills/a11y-audit/` |\r\n| Bundle profiling + runtime perf | `engineering/skills/performance-profiler/` |\r\n| Cinematic / scroll-storytelling landing | `engineering-team/skills/epic-design/` |\r\n| Apple HIG (iOS / macOS / visionOS) | `product-team/skills/apple-hig-expert/` |\r\n| Pre-commit Karpathy review | `engineering/karpathy-coder/` |\r\n| Pre-flight architecture grill | `engineering/grill-me/` |\r\n\r\nThe `cs-frontend-engineer` agent orchestrates these forks via `context: fork`. Invoke it from another agent with `Agent({subagent_type: \"cs-frontend-engineer\", prompt: \"...\"})` or via `/cs-frontend-review <your problem>`.\r\n\r\n---\r\n\r\n## Forcing-question library (Matt Pocock grill)\r\n\r\nBefore locking any framework or rendering decision, walk the seven forcing questions in `references/forcing_questions.md`. Discipline:\r\n\r\n1. One question per turn. No bundling.\r\n2. Always recommend the answer with cited canon.\r\n3. Track answers in `/tmp/frontend-grill-<date>.md`.\r\n4. If a kill criterion trips, stop. Don't scaffold around an unresolved gap.\r\n5. After Q7, run `frontend_decision_engine.py` with the seven answers.\r\n\r\nSummary:\r\n\r\n1. Primary device + network?\r\n2. LCP target in ms (and INP, CLS)?\r\n3. RSC / SPA / SSR / SSG — pick and defend?\r\n4. JS bundle budget per route?\r\n5. SEO-dependent or auth-walled?\r\n6. Design-system source of truth?\r\n7. WCAG target + named a11y owner?\r\n\r\n---\r\n\r\n## Invocation from other agents and skills\r\n\r\nThree surfaces:\r\n\r\n1. **Slash command:** `/cs-frontend-review <prompt>` — full grill + decision engine + composition routing.\r\n2. **Agent subagent:** `Agent({subagent_type: \"cs-frontend-engineer\", prompt: \"...\"})` — forks context, returns ≤ 200-word digest.\r\n3. **Direct tool call:** `python scripts/frontend_decision_engine.py ...` — deterministic profile match when inputs are known.\r\n\r\nSee `agents/engineering/cs-frontend-engineer.md` for the full invocation contract."
  user_template: ""
variables: []
install:
  steps:
    - title: Download & unzip
      detail: >-
        Download the .zip package from SkillVault and unzip it. The senior-frontend/ folder contains
        SKILL.md plus any companion scripts, references and assets.
    - title: Copy into your agent skills directory
      detail: >-
        Move the folder into your agent's skills directory — e.g. ~/.claude/skills/ (Claude Code),
        .codex/skills/, .cursor/skills/ or your project's .claude/skills/ folder — then restart or
        reload the session.
    - title: Use it
      detail: >-
        Describe the task in natural language; the agent loads the skill automatically when the
        request matches the skill description.
usage:
  steps: []
metadata:
  author: SkillVault
  source: https://skillvault.top/skills/senior-frontend
  exported_at: "2026-11-03T06:36:14.962Z"

Installation guide

  1. 1

    Download & unzip

    Download the .zip package from SkillVault and unzip it. The senior-frontend/ folder contains SKILL.md plus any companion scripts, references and assets.

  2. 2

    Copy into your agent skills directory

    Move the folder into your agent's skills directory — e.g. ~/.claude/skills/ (Claude Code), .codex/skills/, .cursor/skills/ or your project's .claude/skills/ folder — then restart or reload the session.

  3. 3

    Use it

    Describe the task in natural language; the agent loads the skill automatically when the request matches the skill description.

How to use

Platform compatibility

ChatGPT GPTs

OpenAI

Paste the system prompt into the GPT "Instructions" field and keep the user template as your starter message.

Official docs

Claude Code

Anthropic

Save the exported .aiskill JSON as a skill file in your project or paste the system prompt into CLAUDE.md / a slash-command markdown file.

Official docs

Cursor

Anysphere

Copy the system prompt into .cursor/rules/*.mdc (or Project Rules in Settings) and reference the user template in your agent prompts.

Official docs

Related skills

dependency-auditor AI agent skill cover
Free
ChatGPT GPTs Claude Code Cursor

dependency-auditor

Audit and manage dependencies across multi-language projects. Identifies vulnerabilities, license conflicts, transitive dependency risks, and safe-upgrade paths. Use when auditing third-party packages before release, investigating a CVE, planning a major version bump, or running a license-compliance review. Examples: 'audit our npm dependencies', 'do we have GPL contamination', 'plan the upgrade to React 19'.

#engineering#security#frontend
0 0 v1.0.0
docker-development AI agent skill cover
Free
ChatGPT GPTs Claude Code Cursor

docker-development

Docker and container development agent skill and plugin for Dockerfile optimization, docker-compose orchestration, multi-stage builds, and container security hardening. Use when: user wants to optimize a Dockerfile, create or improve docker-compose configurations, implement multi-stage builds, audit container security, reduce image size, or follow container best practices. Covers build performance, layer caching, secret management, and production-ready container patterns.

#engineering#devops#security
0 0 v1.0.0
performance-profiler AI agent skill cover
Free
ChatGPT GPTs Claude Code Cursor

performance-profiler

Systematic performance profiling for Node.js, Python, and Go applications. Identifies CPU, memory, and I/O bottlenecks, generates flamegraphs, analyzes bundle sizes, optimizes database queries, runs load tests with k6 and Artillery. Always measures before and after. Use when investigating a slow endpoint, planning a performance budget, or hunting a memory leak in production.

#engineering#sql#python
0 0 v1.0.0