Claude-Skills senior-frontend
git clone https://github.com/borghei/Claude-Skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/borghei/Claude-Skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/engineering/senior-frontend" ~/.claude/skills/borghei-claude-skills-senior-frontend && rm -rf "$T"
engineering/senior-frontend/SKILL.mdSenior Frontend
Frontend development patterns, performance optimization, and automation tools for React/Next.js applications.
Table of Contents
- Project Scaffolding
- Component Generation
- Bundle Analysis
- React Patterns
- Next.js Optimization
- 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
-
Run the scaffolder with your project name and template:
python scripts/frontend_scaffolder.py my-app --template nextjs -
Add optional features (auth, api, forms, testing, storybook):
python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api -
Navigate to the project and install dependencies:
cd my-app && npm install -
Start the development server:
npm run dev
Scaffolder Options
| Option | Description |
|---|---|
| Next.js 14+ with App Router and Server Components |
| React + Vite with TypeScript |
| Add NextAuth.js authentication |
| Add React Query + API client |
| Add React Hook Form + Zod validation |
| Add Vitest + Testing Library |
| 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
-
Generate a client component:
python scripts/component_generator.py Button --dir src/components/ui -
Generate a server component:
python scripts/component_generator.py ProductCard --type server -
Generate with test and story files:
python scripts/component_generator.py UserProfile --with-test --with-story -
Generate a custom hook:
python scripts/component_generator.py FormValidation --type hook
Generator Options
| Option | Description |
|---|---|
| Client component with 'use client' (default) |
| Async server component |
| Custom React hook |
| Include test file |
| Include Storybook story |
| Create in output dir without subdirectory |
| Preview without creating files |
Generated Component Example
'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
-
Run the analyzer on your project:
python scripts/bundle_analyzer.py /path/to/project -
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 -
Apply the recommended fixes by replacing heavy dependencies.
-
Re-run with verbose mode to check import patterns:
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:
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:
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:
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
// 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
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
// 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
- Semantic HTML: Use proper elements (
,<button>
,<nav>
)<main> - Keyboard Navigation: All interactive elements focusable
- ARIA Labels: Provide labels for icons and complex widgets
- Color Contrast: Minimum 4.5:1 for normal text
- Focus Indicators: Visible focus states
// 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
// 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
// next.config.js const nextConfig = { images: { remotePatterns: [{ hostname: 'cdn.example.com' }], formats: ['image/avif', 'image/webp'], }, experimental: { optimizePackageImports: ['lucide-react', '@heroicons/react'], }, };
Tailwind CSS Utilities
// 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
// 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
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Scaffolder fails with "Directory already exists" | Target project folder already present on disk | Delete or rename the existing directory, or choose a different project name |
| Component generator creates PascalCase name from kebab-case incorrectly | Input contains mixed delimiters (e.g., ) | Use consistent kebab-case () or PascalCase () as input |
| Bundle analyzer reports "No valid package.json found" | Script is pointed at a directory without or the file has invalid JSON | Pass the correct project root directory; validate syntax with |
shows files but content is listed as TODO | Feature file content keys are not mapped in dictionary | This is expected for some add-on features; implement the placeholder files manually after scaffolding |
| Bundle score unexpectedly low despite few dependencies | Dev-only packages (TypeScript, ESLint, Tailwind) are listed under instead of | Move build/dev tooling to in |
| Import analysis returns zero files checked | Source code is not in , , or directories | Run with and ensure your source files live in one of the three expected directories |
Generated component missing directive | Component was generated with instead of the default type | Re-run with or add the directive manually at the top of the file |
Success Criteria
- Lighthouse performance score above 90 on the generated project's production build, indicating Server Components and image optimization are configured correctly.
- Bundle size under 200KB gzipped for the initial JavaScript payload, validated by running the bundle analyzer with a grade of A or B.
- Zero heavy-dependency warnings from
after applying all recommended replacements.bundle_analyzer.py - Component generation time under 2 seconds per component, including test and story file creation.
- All generated TypeScript files pass
without errors, confirming type-safe scaffolding output.tsc --noEmit - Accessibility audit produces zero critical violations when running axe-core or Lighthouse accessibility checks against generated components.
- Test coverage above 80% for generated components when the
flag is used and tests are executed with Vitest.--with-test
Scope & Limitations
What this skill covers:
- React and Next.js project scaffolding with TypeScript and Tailwind CSS
- Component, hook, test, and Storybook story generation following established patterns
- Static bundle analysis based on
dependency inspection and import pattern scanningpackage.json - Frontend-specific best practices for Server Components, image optimization, data fetching, and accessibility
What this skill does NOT cover:
- Backend API development, database schema design, or server infrastructure -- see senior-backend and senior-fullstack
- End-to-end testing with Cypress or Playwright -- see senior-qa
- CI/CD pipeline configuration and Docker deployment -- see senior-devops
- Security vulnerability scanning and penetration testing -- see senior-secops and senior-security
Integration Points
| Skill | Integration | Data Flow |
|---|---|---|
| senior-fullstack | Scaffolded frontend projects connect to fullstack project scaffolder for API layer setup | Frontend project structure feeds into which adds backend, Docker, and CI/CD layers |
| senior-backend | Components consuming API data follow patterns defined by backend skill's REST/GraphQL conventions | Backend API response types imported into frontend directory generated by this skill |
| senior-qa | Generated test files () use the same Testing Library conventions that the QA skill's test strategies build upon | Component test files hand off to QA skill for integration and E2E test coverage expansion |
| senior-devops | Bundle analyzer output informs build pipeline optimization decisions | Bundle health score and dependency warnings feed into CI quality gates configured by DevOps skill |
| senior-secops | Dependency analysis identifies packages that need security audit | Heavy/outdated dependency warnings from trigger security review workflows |
| code-reviewer | Generated components follow patterns that the code reviewer skill validates | Code reviewer checks generated components against React/TypeScript best practices defined in this skill's references |
Tool Reference
frontend_scaffolder.py
- Purpose: Scaffold a complete Next.js or React project with TypeScript, Tailwind CSS, and optional feature modules.
- Usage:
python scripts/frontend_scaffolder.py <name> [flags] - Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
| positional | (required) | Project name, kebab-case recommended |
, | string | | Output directory where the project folder is created |
, | choice | | Project template: or |
, | string | (none) | Comma-separated features: , , , , |
| flag | off | List available project templates and exit |
| flag | off | List available feature modules and exit |
| flag | off | Preview generated file list without writing to disk |
| flag | off | Output result as JSON instead of human-readable summary |
- Example:
python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api --json{ "name": "dashboard", "template": "nextjs", "template_name": "Next.js 14+ App Router", "features": ["auth", "api"], "path": "./dashboard", "files_created": 28, "next_steps": ["cd dashboard", "npm install", "npm run dev"] } - Output Formats: Human-readable summary (default) or JSON (
).--json
component_generator.py
- Purpose: Generate React/Next.js component files with TypeScript, optional test, and Storybook story.
- Usage:
python scripts/component_generator.py <name> [flags] - Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
| positional | (required) | Component name in PascalCase or kebab-case |
, | string | | Output directory for generated files |
, | choice | | Component type: , , or |
| flag | off | Generate a file with Testing Library boilerplate |
| flag | off | Generate a file for Storybook |
| flag | off | Skip generating the barrel export file |
| flag | off | Place files directly in output dir without creating a subdirectory |
| flag | off | Preview what would be generated without writing files |
, | flag | off | Enable verbose output |
- Example:
python scripts/component_generator.py ProductCard --dir src/components/ui --type client --with-test --with-story================================================== Component Generated: ProductCard ================================================== Type: client Directory: src/components/ui/ProductCard Files created: - src/components/ui/ProductCard/ProductCard.tsx - src/components/ui/ProductCard/ProductCard.test.tsx - src/components/ui/ProductCard/ProductCard.stories.tsx - src/components/ui/ProductCard/index.ts ================================================== - Output Formats: Human-readable summary only.
bundle_analyzer.py
- Purpose: Analyze
and project source files for bundle size issues, heavy dependencies, and optimization opportunities.package.json - Usage:
python scripts/bundle_analyzer.py [project_dir] [flags] - Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
| positional | | Project directory containing |
| flag | off | Output full analysis as JSON |
, | flag | off | Include detailed import pattern analysis across , , and directories |
- Example:
python scripts/bundle_analyzer.py /path/to/my-app --verbose============================================================ FRONTEND BUNDLE ANALYSIS REPORT ============================================================ Bundle Health Score: 70/100 (C) Dependencies: 12 production, 18 dev --- HEAVY DEPENDENCIES --- moment (290KB) Reason: Large locale files bundled by default Alternative: date-fns (12KB) or dayjs (2KB) lodash (71KB) Reason: Full library often imported when only few functions needed Alternative: lodash-es with tree-shaking or individual imports (lodash/get) --- IMPORT ISSUES --- - src/utils/date.ts: Consider replacing moment with date-fns or dayjs --- RECOMMENDATIONS --- 1. Replace heavy dependencies with lighter alternatives ============================================================ - Output Formats: Human-readable report (default) or JSON (
).--json