Add 14 starter pack skills to library

Adds development-focused skills from the starter pack that were missing
from the repo: accessibility-auditor, api-endpoint-scaffolder,
css-animation-creator, dependency-auditor, design-system-generator,
docker-debugger, env-setup-wizard, error-boundary-creator,
git-pr-reviewer, landing-page-optimizer, performance-profiler,
react-component-generator, responsive-layout-builder, test-coverage-improver.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gabe Keding
2026-02-24 22:53:11 -05:00
parent 14b7f5bdba
commit 309ae7a57f
14 changed files with 4134 additions and 0 deletions
+299
View File
@@ -0,0 +1,299 @@
---
name: accessibility-auditor
description: Audit websites for accessibility issues and WCAG compliance. Use when checking accessibility, fixing a11y issues, or ensuring WCAG compliance.
---
# Accessibility Auditor
## Instructions
When auditing accessibility:
1. **Run automated checks** (axe, Lighthouse)
2. **Manual keyboard testing**
3. **Screen reader testing**
4. **Check WCAG criteria**
5. **Provide fixes**
## Automated Testing
```bash
# Lighthouse accessibility audit
npx lighthouse https://yoursite.com --only-categories=accessibility --view
# axe-core CLI
npx @axe-core/cli https://yoursite.com
# Pa11y
npx pa11y https://yoursite.com
```
### React Testing Library + jest-axe
```typescript
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('Button has no accessibility violations', async () => {
const { container } = render(<Button>Click me</Button>);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
```
### Playwright Accessibility Testing
```typescript
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('page has no accessibility violations', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
```
## WCAG Checklist
### Level A (Minimum)
#### Perceivable
- [ ] **1.1.1** Non-text content has alt text
- [ ] **1.3.1** Info and relationships are programmatically determined
- [ ] **1.3.2** Meaningful reading sequence
- [ ] **1.4.1** Color is not the only way to convey info
#### Operable
- [ ] **2.1.1** All functionality available via keyboard
- [ ] **2.1.2** No keyboard traps
- [ ] **2.4.1** Skip navigation link provided
- [ ] **2.4.2** Pages have descriptive titles
- [ ] **2.4.3** Focus order is logical
- [ ] **2.4.4** Link purpose is clear
#### Understandable
- [ ] **3.1.1** Page language is specified
- [ ] **3.2.1** Focus doesn't cause unexpected changes
- [ ] **3.3.1** Errors are identified and described
- [ ] **3.3.2** Labels or instructions provided
#### Robust
- [ ] **4.1.1** Valid HTML (no duplicate IDs, proper nesting)
- [ ] **4.1.2** Name, role, value for all UI components
### Level AA (Standard Target)
- [ ] **1.4.3** Contrast ratio 4.5:1 for text
- [ ] **1.4.4** Text resizable to 200%
- [ ] **1.4.10** Content reflows at 320px width
- [ ] **2.4.6** Headings and labels are descriptive
- [ ] **2.4.7** Focus indicator is visible
- [ ] **3.2.3** Navigation is consistent
- [ ] **3.2.4** Components identified consistently
## Common Issues & Fixes
### 1. Missing Alt Text
```tsx
// Bad
<img src="/hero.jpg" />
// Good - Informative image
<img src="/hero.jpg" alt="Team collaborating in modern office" />
// Good - Decorative image
<img src="/decoration.jpg" alt="" role="presentation" />
// Good - Icon button
<button aria-label="Close dialog">
<XIcon aria-hidden="true" />
</button>
```
### 2. Missing Form Labels
```tsx
// Bad
<input type="email" placeholder="Email" />
// Good - Visible label
<div>
<label htmlFor="email">Email</label>
<input id="email" type="email" />
</div>
// Good - Visually hidden label
<div>
<label htmlFor="search" className="sr-only">Search</label>
<input id="search" type="search" placeholder="Search..." />
</div>
```
### 3. Poor Color Contrast
```tsx
// Bad - 2.5:1 ratio
<p className="text-gray-400 bg-white">Low contrast text</p>
// Good - 4.5:1+ ratio
<p className="text-gray-700 bg-white">Accessible text</p>
// Check contrast: https://webaim.org/resources/contrastchecker/
```
### 4. Missing Focus Styles
```css
/* Bad - Removes focus */
*:focus { outline: none; }
/* Good - Custom focus style */
*:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
/* Tailwind */
.btn {
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2;
}
```
### 5. Non-semantic HTML
```tsx
// Bad
<div onClick={handleClick}>Click me</div>
// Good
<button onClick={handleClick}>Click me</button>
// Bad
<div className="header">...</div>
// Good
<header>...</header>
```
### 6. Missing ARIA for Dynamic Content
```tsx
// Loading state
<button disabled aria-busy="true">
<span className="sr-only">Loading</span>
<Spinner aria-hidden="true" />
</button>
// Live region for updates
<div aria-live="polite" aria-atomic="true">
{message && <p>{message}</p>}
</div>
// Modal
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<h2 id="modal-title">Dialog Title</h2>
</div>
```
### 7. Skip Link
```tsx
// Add as first focusable element
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-white"
>
Skip to main content
</a>
<main id="main-content">
...
</main>
```
## Screen Reader Only Class
```css
/* Visually hidden but accessible */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Show on focus (for skip links) */
.sr-only-focusable:focus {
position: static;
width: auto;
height: auto;
padding: inherit;
margin: inherit;
overflow: visible;
clip: auto;
white-space: normal;
}
```
## Keyboard Testing Checklist
1. **Tab through page** - Logical order?
2. **Enter/Space on buttons** - Activates?
3. **Arrow keys in menus** - Navigates?
4. **Escape** - Closes modals/dropdowns?
5. **Focus visible** - Always visible?
6. **No traps** - Can tab out of all components?
## Common ARIA Patterns
```tsx
// Tabs
<div role="tablist">
<button role="tab" aria-selected="true" aria-controls="panel-1">Tab 1</button>
<button role="tab" aria-selected="false" aria-controls="panel-2">Tab 2</button>
</div>
<div role="tabpanel" id="panel-1">Content 1</div>
<div role="tabpanel" id="panel-2" hidden>Content 2</div>
// Accordion
<button aria-expanded="true" aria-controls="content-1">Section 1</button>
<div id="content-1">Content</div>
// Menu
<button aria-haspopup="menu" aria-expanded="false">Options</button>
<ul role="menu" hidden>
<li role="menuitem">Option 1</li>
<li role="menuitem">Option 2</li>
</ul>
// Alert
<div role="alert">Error: Please fix the form</div>
// Progress
<div role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
50%
</div>
```
## Tools
- **axe DevTools** - Browser extension
- **WAVE** - Browser extension
- **Lighthouse** - Built into Chrome
- **NVDA** - Free Windows screen reader
- **VoiceOver** - Built into macOS (Cmd+F5)
- **Color Contrast Analyzer** - Desktop app
+104
View File
@@ -0,0 +1,104 @@
---
name: api-endpoint-scaffolder
description: Generate REST API endpoints with proper structure, validation, error handling, and types. Use when creating new API routes, endpoints, or backend services.
---
# API Endpoint Scaffolder
## Instructions
When creating a new API endpoint:
1. **Identify the framework** (Express, Next.js, FastAPI, etc.)
2. **Determine HTTP method** (GET, POST, PUT, PATCH, DELETE)
3. **Define request/response types**
4. **Implement with best practices**
## Templates
### Next.js App Router (TypeScript)
```typescript
// app/api/[resource]/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
const RequestSchema = z.object({
// Define your schema
});
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
// Implementation
return NextResponse.json({ data }, { status: 200 });
} catch (error) {
console.error('[API] Error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const validated = RequestSchema.parse(body);
// Implementation
return NextResponse.json({ data }, { status: 201 });
} catch (error) {
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Validation failed', details: error.errors },
{ status: 400 }
);
}
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
```
### Express (TypeScript)
```typescript
import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
const router = Router();
const CreateSchema = z.object({
// Define schema
});
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
try {
const data = CreateSchema.parse(req.body);
// Implementation
res.status(201).json({ success: true, data });
} catch (error) {
next(error);
}
});
export default router;
```
## Best Practices
1. **Always validate input** using Zod, Yup, or similar
2. **Use proper HTTP status codes**:
- 200: Success
- 201: Created
- 400: Bad Request
- 401: Unauthorized
- 403: Forbidden
- 404: Not Found
- 500: Server Error
3. **Log errors** but don't expose internals to clients
4. **Use consistent response format**
5. **Add rate limiting** for public endpoints
6. **Document with OpenAPI/Swagger** when possible
File diff suppressed because it is too large Load Diff
+185
View File
@@ -0,0 +1,185 @@
---
name: dependency-auditor
description: Audit npm dependencies for security vulnerabilities, outdated packages, and unused dependencies. Use when checking for security issues, updating packages, or cleaning up dependencies.
---
# Dependency Auditor
## Instructions
When auditing dependencies:
1. **Run security audit**
2. **Check for outdated packages**
3. **Find unused dependencies**
4. **Analyze bundle size impact**
5. **Review and update**
## Security Audit
```bash
# NPM audit
npm audit
# Get JSON output for processing
npm audit --json
# Fix automatically (safe fixes only)
npm audit fix
# Force fix (may have breaking changes)
npm audit fix --force
# PNPM
pnpm audit
# Yarn
yarn audit
```
## Check Outdated Packages
```bash
# NPM
npm outdated
# Interactive update
npx npm-check-updates -i
# Update all to latest
npx npm-check-updates -u
npm install
# Check specific package
npm view <package> versions
```
## Find Unused Dependencies
```bash
# Using depcheck
npx depcheck
# With details
npx depcheck --detailed
# Ignore patterns
npx depcheck --ignores="@types/*,eslint-*"
```
### Common False Positives
Depcheck may flag these as unused when they're actually needed:
- `@types/*` packages (used by TypeScript)
- ESLint/Prettier plugins (referenced in config)
- PostCSS plugins (referenced in config)
- Next.js plugins
- Babel presets
## Analyze Bundle Size
```bash
# For Next.js
npx @next/bundle-analyzer
# General purpose
npx source-map-explorer dist/**/*.js
# Check package size before installing
npx package-phobia <package-name>
# Compare alternatives
npx bundlephobia-cli compare lodash ramda
```
## Dependency Review Checklist
### Security
- [ ] No critical/high vulnerabilities
- [ ] Dependencies actively maintained
- [ ] No known malicious packages
- [ ] Lock file committed
### Freshness
- [ ] No major version behind (unless intentional)
- [ ] Security patches applied
- [ ] Deprecated packages replaced
### Cleanliness
- [ ] No unused dependencies
- [ ] No duplicate packages (check lock file)
- [ ] devDependencies vs dependencies correct
## Update Strategies
### Conservative (Recommended)
```bash
# Update patch versions only
npm update
# Update specific package
npm install package@latest
```
### Aggressive
```bash
# Update everything
npx npm-check-updates -u
npm install
npm test
```
### Interactive
```bash
npx npm-check-updates -i
# Options:
# a - update all
# space - toggle selection
# enter - apply selected
```
## Package.json Cleanup
```json
{
"dependencies": {
// Runtime dependencies only
},
"devDependencies": {
// Build/test tools only
},
"peerDependencies": {
// For libraries only
},
"optionalDependencies": {
// Platform-specific (rare)
}
}
```
## Lock File Best Practices
1. **Always commit** lock files (package-lock.json, pnpm-lock.yaml, yarn.lock)
2. **Use `npm ci`** in CI/CD (not `npm install`)
3. **Regenerate** if corrupted: delete lock file + node_modules, reinstall
4. **Single lock file** per project (don't mix package managers)
## Automated Monitoring
```yaml
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
dev-dependencies:
dependency-type: "development"
```
+388
View File
@@ -0,0 +1,388 @@
---
name: design-system-generator
description: Create design systems with tokens, components, and documentation. Use when building design systems, creating component libraries, or establishing design tokens.
---
# Design System Generator
## Instructions
When creating a design system:
1. **Define design tokens** (colors, typography, spacing)
2. **Create base components** (Button, Input, Card, etc.)
3. **Establish patterns** (forms, navigation, layouts)
4. **Document usage** and variants
## Design Tokens
### Colors
```typescript
// tokens/colors.ts
export const colors = {
// Brand
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6', // Main
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
// Semantic
success: {
light: '#dcfce7',
main: '#22c55e',
dark: '#15803d',
},
warning: {
light: '#fef3c7',
main: '#f59e0b',
dark: '#b45309',
},
error: {
light: '#fee2e2',
main: '#ef4444',
dark: '#b91c1c',
},
// Neutral
gray: {
50: '#f9fafb',
100: '#f3f4f6',
200: '#e5e7eb',
300: '#d1d5db',
400: '#9ca3af',
500: '#6b7280',
600: '#4b5563',
700: '#374151',
800: '#1f2937',
900: '#111827',
},
} as const;
```
### Typography
```typescript
// tokens/typography.ts
export const typography = {
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
fontSize: {
xs: ['0.75rem', { lineHeight: '1rem' }],
sm: ['0.875rem', { lineHeight: '1.25rem' }],
base: ['1rem', { lineHeight: '1.5rem' }],
lg: ['1.125rem', { lineHeight: '1.75rem' }],
xl: ['1.25rem', { lineHeight: '1.75rem' }],
'2xl': ['1.5rem', { lineHeight: '2rem' }],
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
'5xl': ['3rem', { lineHeight: '1.15' }],
},
fontWeight: {
normal: '400',
medium: '500',
semibold: '600',
bold: '700',
},
} as const;
```
### Spacing
```typescript
// tokens/spacing.ts
export const spacing = {
px: '1px',
0: '0',
0.5: '0.125rem', // 2px
1: '0.25rem', // 4px
1.5: '0.375rem', // 6px
2: '0.5rem', // 8px
2.5: '0.625rem', // 10px
3: '0.75rem', // 12px
4: '1rem', // 16px
5: '1.25rem', // 20px
6: '1.5rem', // 24px
8: '2rem', // 32px
10: '2.5rem', // 40px
12: '3rem', // 48px
16: '4rem', // 64px
20: '5rem', // 80px
24: '6rem', // 96px
} as const;
```
### Shadows & Radii
```typescript
// tokens/effects.ts
export const shadows = {
sm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
DEFAULT: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
md: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
lg: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',
xl: '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)',
};
export const radii = {
none: '0',
sm: '0.125rem',
DEFAULT: '0.25rem',
md: '0.375rem',
lg: '0.5rem',
xl: '0.75rem',
'2xl': '1rem',
full: '9999px',
};
```
## CSS Variables Setup
```css
/* globals.css */
:root {
/* Colors */
--color-primary: 59 130 246;
--color-primary-foreground: 255 255 255;
--color-background: 255 255 255;
--color-foreground: 17 24 39;
--color-muted: 243 244 246;
--color-muted-foreground: 107 114 128;
--color-border: 229 231 235;
--color-ring: 59 130 246;
/* Spacing */
--spacing-unit: 0.25rem;
/* Typography */
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* Radii */
--radius: 0.5rem;
}
.dark {
--color-background: 17 24 39;
--color-foreground: 243 244 246;
--color-muted: 31 41 55;
--color-muted-foreground: 156 163 175;
--color-border: 55 65 81;
}
```
## Base Components
### Button
```tsx
// components/ui/button.tsx
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
primary: 'bg-primary-500 text-white hover:bg-primary-600',
secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
outline: 'border border-gray-300 bg-transparent hover:bg-gray-50',
ghost: 'hover:bg-gray-100',
destructive: 'bg-red-500 text-white hover:bg-red-600',
link: 'text-primary-500 underline-offset-4 hover:underline',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4',
lg: 'h-12 px-6 text-lg',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'primary',
size: 'md',
},
}
);
interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
isLoading?: boolean;
}
export function Button({
className,
variant,
size,
isLoading,
children,
disabled,
...props
}: ButtonProps) {
return (
<button
className={cn(buttonVariants({ variant, size }), className)}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Spinner className="mr-2 h-4 w-4" />}
{children}
</button>
);
}
```
### Input
```tsx
// components/ui/input.tsx
import { cn } from '@/lib/utils';
import { forwardRef } from 'react';
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
error?: string;
}
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, error, ...props }, ref) => {
return (
<div className="space-y-1">
<input
ref={ref}
className={cn(
'flex h-10 w-full rounded-md border bg-white px-3 py-2 text-sm',
'placeholder:text-gray-400',
'focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent',
'disabled:cursor-not-allowed disabled:opacity-50',
error ? 'border-red-500' : 'border-gray-300',
className
)}
aria-invalid={!!error}
{...props}
/>
{error && (
<p className="text-sm text-red-500" role="alert">
{error}
</p>
)}
</div>
);
}
);
Input.displayName = 'Input';
```
### Card
```tsx
// components/ui/card.tsx
import { cn } from '@/lib/utils';
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {}
export function Card({ className, ...props }: CardProps) {
return (
<div
className={cn(
'rounded-lg border bg-white shadow-sm',
className
)}
{...props}
/>
);
}
export function CardHeader({ className, ...props }: CardProps) {
return <div className={cn('p-6 pb-0', className)} {...props} />;
}
export function CardTitle({ className, ...props }: CardProps) {
return <h3 className={cn('text-lg font-semibold', className)} {...props} />;
}
export function CardContent({ className, ...props }: CardProps) {
return <div className={cn('p-6', className)} {...props} />;
}
export function CardFooter({ className, ...props }: CardProps) {
return <div className={cn('p-6 pt-0 flex gap-2', className)} {...props} />;
}
```
## Tailwind Config
```javascript
// tailwind.config.js
const { colors, typography, spacing, shadows, radii } = require('./tokens');
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
darkMode: 'class',
theme: {
extend: {
colors: {
primary: colors.primary,
gray: colors.gray,
success: colors.success,
warning: colors.warning,
error: colors.error,
},
fontFamily: typography.fontFamily,
fontSize: typography.fontSize,
spacing: spacing,
boxShadow: shadows,
borderRadius: radii,
},
},
plugins: [],
};
```
## Utility Function
```typescript
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```
## Component Index
```typescript
// components/ui/index.ts
export { Button } from './button';
export { Input } from './input';
export { Card, CardHeader, CardTitle, CardContent, CardFooter } from './card';
export { Badge } from './badge';
export { Avatar } from './avatar';
export { Select } from './select';
export { Checkbox } from './checkbox';
export { Radio } from './radio';
export { Switch } from './switch';
export { Modal } from './modal';
export { Toast } from './toast';
export { Tabs } from './tabs';
export { Dropdown } from './dropdown';
```
+169
View File
@@ -0,0 +1,169 @@
---
name: docker-debugger
description: Debug Docker containers, fix Dockerfile issues, optimize images, and troubleshoot docker-compose. Use when having Docker problems, container issues, or optimizing Docker builds.
---
# Docker Debugger
## Instructions
When debugging Docker issues:
1. **Identify the problem type**: Build, runtime, networking, or performance
2. **Gather information** using diagnostic commands
3. **Analyze logs and errors**
4. **Apply fixes**
## Diagnostic Commands
```bash
# Check running containers
docker ps -a
# View container logs
docker logs <container_id> --tail 100 -f
# Inspect container
docker inspect <container_id>
# Check resource usage
docker stats
# View container processes
docker top <container_id>
# Execute shell in running container
docker exec -it <container_id> /bin/sh
# Check Docker disk usage
docker system df
# View build history
docker history <image_name>
```
## Common Issues & Solutions
### 1. Container exits immediately
```bash
# Check exit code
docker inspect <container_id> --format='{{.State.ExitCode}}'
# View last logs
docker logs <container_id>
```
**Fixes**:
- Ensure CMD/ENTRYPOINT runs a foreground process
- Check for missing dependencies
- Verify environment variables
### 2. Build fails
```dockerfile
# Use multi-stage builds for smaller images
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
```
### 3. Networking issues
```bash
# List networks
docker network ls
# Inspect network
docker network inspect <network_name>
# Check container IP
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>
```
### 4. Volume permission issues
```dockerfile
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
# Set ownership
COPY --chown=appuser:appgroup . .
USER appuser
```
## Dockerfile Best Practices
```dockerfile
# 1. Use specific tags, not :latest
FROM node:20.10-alpine
# 2. Set working directory
WORKDIR /app
# 3. Copy dependency files first (better caching)
COPY package*.json ./
RUN npm ci --only=production
# 4. Copy source after dependencies
COPY . .
# 5. Use non-root user
USER node
# 6. Set proper labels
LABEL maintainer="you@example.com"
LABEL version="1.0"
# 7. Use HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://localhost:3000/health || exit 1
# 8. Expose ports
EXPOSE 3000
# 9. Use exec form for CMD
CMD ["node", "server.js"]
```
## docker-compose Debugging
```yaml
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
# Add for debugging
stdin_open: true
tty: true
# Override command for debugging
command: /bin/sh
volumes:
- .:/app
environment:
- DEBUG=true
```
```bash
# Rebuild without cache
docker-compose build --no-cache
# View logs
docker-compose logs -f app
# Restart single service
docker-compose restart app
```
+182
View File
@@ -0,0 +1,182 @@
---
name: env-setup-wizard
description: Set up environment variables, .env files, and configuration management. Use when configuring environment variables, creating .env files, or managing app configuration.
---
# Environment Setup Wizard
## Instructions
When setting up environment configuration:
1. **Identify required variables** for the project
2. **Create .env structure** with proper organization
3. **Set up type-safe access** to env vars
4. **Add validation** on startup
5. **Document all variables**
## File Structure
```
project/
├── .env # Local development (git-ignored)
├── .env.example # Template (committed to git)
├── .env.local # Local overrides (git-ignored)
├── .env.development # Development defaults
├── .env.production # Production defaults
└── src/
└── lib/
└── env.ts # Type-safe env access
```
## .env.example Template
```bash
# ===================
# Application
# ===================
NODE_ENV=development
APP_URL=http://localhost:3000
PORT=3000
# ===================
# Database
# ===================
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# ===================
# Authentication
# ===================
# Generate with: openssl rand -base64 32
JWT_SECRET=
NEXTAUTH_SECRET=
NEXTAUTH_URL=http://localhost:3000
# ===================
# Third-party APIs
# ===================
# Get from: https://stripe.com/dashboard
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=
STRIPE_WEBHOOK_SECRET=
# Get from: https://resend.com
RESEND_API_KEY=
# ===================
# Storage
# ===================
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
S3_BUCKET_NAME=
```
## Type-Safe Environment (Zod)
```typescript
// src/lib/env.ts
import { z } from 'zod';
const envSchema = z.object({
// App
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
APP_URL: z.string().url(),
PORT: z.coerce.number().default(3000),
// Database
DATABASE_URL: z.string().min(1),
// Auth
JWT_SECRET: z.string().min(32),
NEXTAUTH_SECRET: z.string().min(32),
NEXTAUTH_URL: z.string().url(),
// APIs (optional in dev)
STRIPE_SECRET_KEY: z.string().optional(),
RESEND_API_KEY: z.string().optional(),
});
// Validate on import
const parsed = envSchema.safeParse(process.env);
if (!parsed.success) {
console.error('❌ Invalid environment variables:');
console.error(parsed.error.flatten().fieldErrors);
process.exit(1);
}
export const env = parsed.data;
// Type export for use elsewhere
export type Env = z.infer<typeof envSchema>;
```
## Next.js Specific
```typescript
// src/lib/env.ts for Next.js
import { z } from 'zod';
// Server-side variables
const serverSchema = z.object({
DATABASE_URL: z.string(),
JWT_SECRET: z.string(),
});
// Client-side variables (must start with NEXT_PUBLIC_)
const clientSchema = z.object({
NEXT_PUBLIC_APP_URL: z.string().url(),
NEXT_PUBLIC_STRIPE_KEY: z.string(),
});
export const serverEnv = serverSchema.parse(process.env);
export const clientEnv = clientSchema.parse({
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
NEXT_PUBLIC_STRIPE_KEY: process.env.NEXT_PUBLIC_STRIPE_KEY,
});
```
## T3 Env (Recommended for Next.js)
```typescript
// src/env.mjs
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
NEXT_PUBLIC_APP_URL: z.string().url(),
},
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
},
});
```
## .gitignore
```gitignore
# Environment files
.env
.env.local
.env.*.local
# Keep example
!.env.example
```
## Security Best Practices
1. **Never commit secrets** to git
2. **Use different values** per environment
3. **Rotate secrets regularly**
4. **Use secret managers** in production (Vault, AWS Secrets Manager)
5. **Validate on startup** to fail fast
6. **Prefix client vars** (NEXT_PUBLIC_, VITE_, REACT_APP_)
+324
View File
@@ -0,0 +1,324 @@
---
name: error-boundary-creator
description: Create error boundaries, error handling, and fallback UIs for React applications. Use when implementing error handling, creating fallback components, or setting up error reporting.
---
# Error Boundary Creator
## Instructions
When implementing error handling:
1. **Identify error-prone areas** (async operations, third-party integrations)
2. **Create appropriate error boundaries**
3. **Design fallback UIs**
4. **Set up error reporting**
## Basic Error Boundary
```tsx
'use client';
import { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
// Send to error reporting service
// reportError(error, errorInfo);
}
render() {
if (this.state.hasError) {
return this.props.fallback || <DefaultErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
function DefaultErrorFallback({ error }: { error?: Error }) {
return (
<div role="alert" className="p-4 bg-red-50 border border-red-200 rounded-lg">
<h2 className="text-lg font-semibold text-red-800">Something went wrong</h2>
<p className="text-red-600 mt-1">{error?.message || 'An unexpected error occurred'}</p>
<button
onClick={() => window.location.reload()}
className="mt-4 px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
>
Reload page
</button>
</div>
);
}
```
## Error Boundary with Reset
```tsx
'use client';
import { Component, ReactNode } from 'react';
interface Props {
children: ReactNode;
onReset?: () => void;
}
interface State {
hasError: boolean;
error?: Error;
}
export class ResettableErrorBoundary extends Component<Props, State> {
state: State = { hasError: false };
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
reset = () => {
this.props.onReset?.();
this.setState({ hasError: false, error: undefined });
};
render() {
if (this.state.hasError) {
return (
<div role="alert" className="p-6 text-center">
<h2 className="text-xl font-bold">Oops!</h2>
<p className="text-gray-600 mt-2">{this.state.error?.message}</p>
<button
onClick={this.reset}
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
Try again
</button>
</div>
);
}
return this.props.children;
}
}
```
## react-error-boundary Library
```tsx
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
return (
<div role="alert" className="p-4 bg-red-50 rounded-lg">
<p className="font-medium">Something went wrong:</p>
<pre className="text-sm text-red-600 mt-2">{error.message}</pre>
<button onClick={resetErrorBoundary} className="mt-4 btn-primary">
Try again
</button>
</div>
);
}
// Usage
function App() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => {
// Reset app state here
}}
onError={(error, info) => {
// Log to error reporting service
console.error(error, info);
}}
>
<MyComponent />
</ErrorBoundary>
);
}
```
## Next.js Error Handling
### App Router error.tsx
```tsx
// app/error.tsx (or any route segment)
'use client';
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Log error to reporting service
console.error(error);
}, [error]);
return (
<div className="flex flex-col items-center justify-center min-h-[400px]">
<h2 className="text-2xl font-bold">Something went wrong!</h2>
<button
onClick={reset}
className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-lg"
>
Try again
</button>
</div>
);
}
```
### Global Error (app/global-error.tsx)
```tsx
'use client';
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<div className="flex flex-col items-center justify-center min-h-screen">
<h2 className="text-2xl font-bold">Something went wrong!</h2>
<button onClick={reset} className="mt-4 btn-primary">
Try again
</button>
</div>
</body>
</html>
);
}
```
### Not Found (app/not-found.tsx)
```tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div className="flex flex-col items-center justify-center min-h-[400px]">
<h2 className="text-4xl font-bold">404</h2>
<p className="text-gray-600 mt-2">Page not found</p>
<Link href="/" className="mt-4 text-blue-600 hover:underline">
Go home
</Link>
</div>
);
}
```
## Async Error Handling
```tsx
'use client';
import { useState } from 'react';
interface AsyncState<T> {
data: T | null;
error: Error | null;
isLoading: boolean;
}
function useAsync<T>() {
const [state, setState] = useState<AsyncState<T>>({
data: null,
error: null,
isLoading: false,
});
const execute = async (promise: Promise<T>) => {
setState({ data: null, error: null, isLoading: true });
try {
const data = await promise;
setState({ data, error: null, isLoading: false });
return data;
} catch (error) {
setState({ data: null, error: error as Error, isLoading: false });
throw error;
}
};
return { ...state, execute };
}
// Usage
function DataComponent() {
const { data, error, isLoading, execute } = useAsync<User[]>();
const loadData = () => execute(fetchUsers());
if (isLoading) return <Spinner />;
if (error) return <ErrorMessage error={error} onRetry={loadData} />;
if (!data) return <button onClick={loadData}>Load</button>;
return <UserList users={data} />;
}
```
## Error Reporting Integration
```typescript
// lib/error-reporting.ts
export function reportError(error: Error, context?: Record<string, unknown>) {
// Sentry
// Sentry.captureException(error, { extra: context });
// LogRocket
// LogRocket.captureException(error);
// Custom endpoint
fetch('/api/errors', {
method: 'POST',
body: JSON.stringify({
message: error.message,
stack: error.stack,
context,
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent,
}),
}).catch(console.error);
}
```
## Best Practices
1. **Wrap at route level** for page-level isolation
2. **Wrap third-party components** separately
3. **Provide meaningful fallbacks** with recovery options
4. **Log errors** to monitoring service
5. **Don't catch errors you can't handle**
6. **Test error states** in development
+78
View File
@@ -0,0 +1,78 @@
---
name: git-pr-reviewer
description: Review pull requests for code quality, security issues, and best practices. Use when reviewing PRs, checking code changes, or analyzing diffs before merge.
allowed-tools: Read, Grep, Glob, Bash
---
# Git PR Reviewer
## Instructions
When reviewing a pull request:
1. **Get the diff**: Run `git diff main...HEAD` or `git diff <base-branch>...HEAD`
2. **Analyze changed files**: Identify all modified, added, and deleted files
3. **Review each file** for:
- Logic errors and bugs
- Security vulnerabilities (SQL injection, XSS, hardcoded secrets)
- Performance issues (N+1 queries, unnecessary re-renders, memory leaks)
- Code style and consistency
- Missing error handling
- Test coverage gaps
## Review Checklist
### Security
- [ ] No hardcoded credentials or API keys
- [ ] Input validation on user data
- [ ] Proper authentication/authorization checks
- [ ] No SQL injection vulnerabilities
- [ ] XSS prevention in place
### Code Quality
- [ ] Functions are small and focused
- [ ] No code duplication
- [ ] Clear variable/function naming
- [ ] Proper error handling
- [ ] No unused imports or dead code
### Performance
- [ ] No unnecessary database queries
- [ ] Efficient algorithms used
- [ ] Proper caching where needed
- [ ] No memory leaks
### Testing
- [ ] New code has tests
- [ ] Edge cases covered
- [ ] Tests are meaningful, not just for coverage
## Output Format
```markdown
## PR Review Summary
### Overview
[Brief summary of changes]
### Issues Found
#### Critical
- [Issue description + file:line]
#### Warnings
- [Issue description + file:line]
#### Suggestions
- [Improvement ideas]
### Approval Status
[APPROVE / REQUEST CHANGES / NEEDS DISCUSSION]
```
## Example
```bash
# Review current branch against main
git diff main...HEAD --stat
git diff main...HEAD
```
+325
View File
@@ -0,0 +1,325 @@
---
name: landing-page-optimizer
description: Optimize landing pages for conversions, performance, and SEO. Use when improving landing pages, increasing conversions, or optimizing page performance.
---
# Landing Page Optimizer
## Instructions
When optimizing landing pages:
1. **Audit current page** (speed, UX, conversion elements)
2. **Identify improvement areas**
3. **Implement optimizations**
4. **Set up tracking**
## Above the Fold Checklist
- [ ] **Clear headline** - Value proposition in <5 seconds
- [ ] **Supporting subheadline** - Expand on benefit
- [ ] **Hero image/video** - Relevant, high-quality
- [ ] **Primary CTA** - Contrasting color, action-oriented
- [ ] **Social proof** - Logos, ratings, testimonials
- [ ] **No navigation distractions** - Minimal or hidden nav
## Page Structure Template
```tsx
// Optimal landing page structure
<main>
{/* 1. Hero Section */}
<section className="min-h-[80vh] flex items-center">
<div className="max-w-6xl mx-auto px-4 grid lg:grid-cols-2 gap-12 items-center">
<div>
<Badge>New Feature</Badge>
<h1 className="text-4xl lg:text-6xl font-bold mt-4">
Main Value Proposition
</h1>
<p className="text-xl text-gray-600 mt-6">
Supporting statement that expands on the benefit
</p>
<div className="flex gap-4 mt-8">
<Button size="lg">Primary CTA</Button>
<Button size="lg" variant="outline">Secondary CTA</Button>
</div>
<div className="flex items-center gap-6 mt-8">
<div className="flex -space-x-2">
{avatars.map(a => <Avatar key={a.id} src={a.src} />)}
</div>
<p className="text-sm text-gray-600">
<strong>2,000+</strong> happy customers
</p>
</div>
</div>
<div>
<img src="/hero-image.png" alt="Product preview" />
</div>
</div>
</section>
{/* 2. Social Proof - Logos */}
<section className="py-12 bg-gray-50">
<p className="text-center text-gray-500 mb-8">Trusted by leading companies</p>
<div className="flex justify-center gap-12 opacity-60">
{logos.map(logo => <img key={logo.name} src={logo.src} alt={logo.name} />)}
</div>
</section>
{/* 3. Problem/Solution */}
<section className="py-20">
<div className="max-w-3xl mx-auto text-center">
<h2 className="text-3xl font-bold">The Problem</h2>
<p className="text-xl text-gray-600 mt-4">
Describe the pain point your audience faces
</p>
</div>
</section>
{/* 4. Features/Benefits */}
<section className="py-20 bg-gray-50">
<h2 className="text-3xl font-bold text-center">How It Works</h2>
<div className="grid md:grid-cols-3 gap-8 mt-12 max-w-6xl mx-auto">
{features.map(feature => (
<Card key={feature.title}>
<feature.icon className="w-12 h-12 text-primary-500" />
<h3 className="text-xl font-semibold mt-4">{feature.title}</h3>
<p className="text-gray-600 mt-2">{feature.description}</p>
</Card>
))}
</div>
</section>
{/* 5. Testimonials */}
<section className="py-20">
<h2 className="text-3xl font-bold text-center">What Customers Say</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 mt-12">
{testimonials.map(t => (
<TestimonialCard key={t.name} {...t} />
))}
</div>
</section>
{/* 6. Pricing (if applicable) */}
<section className="py-20 bg-gray-50">
<PricingTable plans={plans} />
</section>
{/* 7. FAQ */}
<section className="py-20">
<h2 className="text-3xl font-bold text-center">FAQ</h2>
<Accordion items={faqs} className="max-w-3xl mx-auto mt-12" />
</section>
{/* 8. Final CTA */}
<section className="py-20 bg-primary-600 text-white text-center">
<h2 className="text-3xl font-bold">Ready to Get Started?</h2>
<p className="text-xl opacity-90 mt-4">Join 2,000+ companies already using our product</p>
<Button size="lg" variant="secondary" className="mt-8">
Start Free Trial
</Button>
<p className="text-sm opacity-75 mt-4">No credit card required</p>
</section>
</main>
```
## CTA Optimization
### Button Best Practices
```tsx
// Good CTAs
<Button>Start Free Trial</Button>
<Button>Get Started Free</Button>
<Button>Try It Free for 14 Days</Button>
<Button>Book a Demo</Button>
// Add urgency/value
<Button>
Get 50% Off Today
<span className="text-sm opacity-75 block">Offer ends midnight</span>
</Button>
// Reduce friction
<div className="text-center">
<Button size="lg">Start Free Trial</Button>
<p className="text-sm text-gray-500 mt-2">
No credit card required Cancel anytime
</p>
</div>
```
### CTA Placement
1. **Hero section** - Primary CTA above fold
2. **After features** - Reinforce value
3. **After testimonials** - Social proof boost
4. **Sticky header/footer** - Always accessible
5. **Exit intent popup** - Last chance
## Performance Optimization
### Image Optimization
```tsx
// Next.js Image component
import Image from 'next/image';
<Image
src="/hero.png"
alt="Product screenshot"
width={1200}
height={800}
priority // Above-fold images
placeholder="blur"
blurDataURL={blurData}
/>
// Lazy load below-fold images
<Image
src="/feature.png"
loading="lazy"
...
/>
```
### Critical CSS
```tsx
// Inline critical styles for above-fold
<head>
<style dangerouslySetInnerHTML={{ __html: criticalCSS }} />
<link rel="preload" href="/fonts/inter.woff2" as="font" crossOrigin="" />
</head>
```
### Performance Targets
| Metric | Target |
|--------|--------|
| LCP | < 2.5s |
| FID/INP | < 100ms |
| CLS | < 0.1 |
| Total Size | < 1MB |
| Time to Interactive | < 3s |
## SEO Optimization
### Meta Tags
```tsx
// app/layout.tsx or pages/_app.tsx
export const metadata = {
title: 'Product Name - Main Benefit | Brand',
description: 'Clear description with keywords. 150-160 chars.',
openGraph: {
title: 'Product Name - Main Benefit',
description: 'Description for social sharing',
images: [{ url: '/og-image.png', width: 1200, height: 630 }],
},
twitter: {
card: 'summary_large_image',
},
};
```
### Structured Data
```tsx
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Product Name",
"applicationCategory": "BusinessApplication",
"offers": {
"@type": "Offer",
"price": "29",
"priceCurrency": "USD"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "1250"
}
})}
</script>
```
## Conversion Tracking
```tsx
// Google Analytics 4 events
const trackCTA = (ctaName: string) => {
gtag('event', 'cta_click', {
cta_name: ctaName,
page_location: window.location.href,
});
};
// Track scroll depth
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
gtag('event', 'section_viewed', {
section_name: entry.target.id,
});
}
});
},
{ threshold: 0.5 }
);
document.querySelectorAll('section[id]').forEach((section) => {
observer.observe(section);
});
}, []);
```
## A/B Testing Elements
Priority elements to test:
1. **Headline copy** - Different value propositions
2. **CTA text** - "Start Free" vs "Get Started" vs "Try Now"
3. **CTA color** - High contrast options
4. **Hero image** - Product vs people vs abstract
5. **Social proof placement** - Above vs below fold
6. **Pricing display** - Monthly vs annual default
7. **Form length** - Email only vs full form
## Mobile Optimization
```tsx
// Thumb-friendly CTAs
<Button className="w-full md:w-auto h-14 text-lg">
Get Started
</Button>
// Sticky mobile CTA
<div className="fixed bottom-0 left-0 right-0 p-4 bg-white border-t md:hidden">
<Button className="w-full">Start Free Trial</Button>
</div>
// Reduce content on mobile
<p className="hidden md:block">
{fullDescription}
</p>
<p className="md:hidden">
{shortDescription}
</p>
```
## Quick Wins Checklist
- [ ] Headline communicates value in 5 seconds
- [ ] CTA button is high contrast and above fold
- [ ] Page loads in under 3 seconds
- [ ] Social proof visible above fold
- [ ] Mobile-optimized with thumb-friendly CTAs
- [ ] No broken images or links
- [ ] Forms have minimal required fields
- [ ] Trust badges near CTAs (security, guarantees)
- [ ] Clear pricing (no hidden fees messaging)
- [ ] Testimonials include photos and titles
+181
View File
@@ -0,0 +1,181 @@
---
name: performance-profiler
description: Profile and optimize application performance including load times, memory usage, and rendering. Use when debugging slow performance, memory leaks, or optimizing app speed.
---
# Performance Profiler
## Instructions
When profiling performance:
1. **Identify the bottleneck type**: Network, rendering, memory, or compute
2. **Measure baseline** before optimizing
3. **Profile with appropriate tools**
4. **Apply optimizations**
5. **Measure improvement**
## Web Performance
### Core Web Vitals
```bash
# Lighthouse CLI
npx lighthouse https://yoursite.com --view
# With specific metrics
npx lighthouse https://yoursite.com --only-categories=performance
```
**Target Metrics**:
| Metric | Good | Needs Work | Poor |
|--------|------|------------|------|
| LCP (Largest Contentful Paint) | < 2.5s | 2.5-4s | > 4s |
| INP (Interaction to Next Paint) | < 200ms | 200-500ms | > 500ms |
| CLS (Cumulative Layout Shift) | < 0.1 | 0.1-0.25 | > 0.25 |
### Bundle Analysis
```bash
# Next.js
ANALYZE=true npm run build
# Webpack
npx webpack-bundle-analyzer stats.json
# Vite
npx vite-bundle-visualizer
```
## React Performance
### React DevTools Profiler
1. Install React DevTools browser extension
2. Open DevTools → Profiler tab
3. Click Record, interact with app, stop recording
4. Analyze flame graph for slow components
### Common React Optimizations
```tsx
// 1. Memoize expensive components
const MemoizedList = React.memo(function List({ items }) {
return items.map(item => <Item key={item.id} {...item} />);
});
// 2. Use useMemo for expensive calculations
const sortedItems = useMemo(() => {
return [...items].sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
// 3. Use useCallback for stable function references
const handleClick = useCallback((id: string) => {
setSelected(id);
}, []);
// 4. Virtualize long lists
import { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
return (
<FixedSizeList
height={400}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>{items[index].name}</div>
)}
</FixedSizeList>
);
}
// 5. Lazy load components
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
```
## Node.js Performance
### Profiling
```bash
# CPU profile
node --prof app.js
node --prof-process isolate-*.log > profile.txt
# Heap snapshot
node --inspect app.js
# Then use Chrome DevTools Memory tab
# Clinic.js (comprehensive)
npx clinic doctor -- node app.js
npx clinic flame -- node app.js
npx clinic bubbleprof -- node app.js
```
### Memory Leak Detection
```javascript
// Add to app for debugging
const used = process.memoryUsage();
console.log({
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)} MB`,
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)} MB`,
external: `${Math.round(used.external / 1024 / 1024)} MB`,
});
```
## Database Performance
```sql
-- PostgreSQL: Analyze slow queries
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
-- Find missing indexes
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
WHERE seq_scan > idx_scan;
```
### Query Optimization
```typescript
// Bad: N+1 query
const users = await db.user.findMany();
for (const user of users) {
const posts = await db.post.findMany({ where: { userId: user.id } });
}
// Good: Single query with include
const users = await db.user.findMany({
include: { posts: true }
});
// Good: Select only needed fields
const users = await db.user.findMany({
select: { id: true, name: true, email: true }
});
```
## Quick Wins Checklist
- [ ] Enable gzip/brotli compression
- [ ] Add caching headers
- [ ] Lazy load images (`loading="lazy"`)
- [ ] Preconnect to external domains
- [ ] Use CDN for static assets
- [ ] Minimize JavaScript bundle
- [ ] Defer non-critical JS
- [ ] Optimize images (WebP, proper sizing)
- [ ] Add database indexes
- [ ] Use connection pooling
+154
View File
@@ -0,0 +1,154 @@
---
name: react-component-generator
description: Generate React components with TypeScript, proper props, hooks, and accessibility. Use when creating new React components, UI elements, or refactoring existing components.
---
# React Component Generator
## Instructions
When creating React components:
1. **Determine component type**: Client or Server component
2. **Define props interface** with TypeScript
3. **Implement with best practices**
4. **Add accessibility attributes**
## Templates
### Client Component
```tsx
'use client';
import { useState, useCallback } from 'react';
import { cn } from '@/lib/utils';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
isLoading?: boolean;
children: React.ReactNode;
}
export function Button({
variant = 'primary',
size = 'md',
isLoading = false,
children,
className,
disabled,
...props
}: ButtonProps) {
const baseStyles = 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2';
const variants = {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
ghost: 'hover:bg-gray-100',
};
const sizes = {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4',
lg: 'h-12 px-6 text-lg',
};
return (
<button
className={cn(baseStyles, variants[variant], sizes[size], className)}
disabled={disabled || isLoading}
aria-busy={isLoading}
{...props}
>
{isLoading ? <span className="animate-spin mr-2">⏳</span> : null}
{children}
</button>
);
}
```
### Server Component
```tsx
import { db } from '@/lib/db';
interface UserListProps {
limit?: number;
}
export async function UserList({ limit = 10 }: UserListProps) {
const users = await db.user.findMany({ take: limit });
if (users.length === 0) {
return <p className="text-gray-500">No users found.</p>;
}
return (
<ul role="list" className="divide-y">
{users.map((user) => (
<li key={user.id} className="py-4">
<span>{user.name}</span>
</li>
))}
</ul>
);
}
```
### Form Component with React Hook Form
```tsx
'use client';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'Min 8 characters'),
});
type FormData = z.infer<typeof schema>;
export function LoginForm({ onSubmit }: { onSubmit: (data: FormData) => void }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<FormData>({
resolver: zodResolver(schema),
});
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<div>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
aria-invalid={!!errors.email}
aria-describedby={errors.email ? 'email-error' : undefined}
{...register('email')}
/>
{errors.email && (
<p id="email-error" role="alert">{errors.email.message}</p>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Loading...' : 'Submit'}
</button>
</form>
);
}
```
## Accessibility Checklist
- [ ] Use semantic HTML elements
- [ ] Add `aria-label` for icon-only buttons
- [ ] Include `role` attributes where needed
- [ ] Ensure keyboard navigation works
- [ ] Add `aria-invalid` and `aria-describedby` for form errors
- [ ] Use `aria-busy` for loading states
+240
View File
@@ -0,0 +1,240 @@
---
name: responsive-layout-builder
description: Build responsive layouts with CSS Grid, Flexbox, and container queries. Use when creating responsive designs, fixing layout issues, or building mobile-first layouts.
---
# Responsive Layout Builder
## Instructions
When building responsive layouts:
1. **Identify the layout pattern** (grid, sidebar, cards, etc.)
2. **Start mobile-first**
3. **Use appropriate CSS technique** (Grid vs Flexbox)
4. **Add breakpoints** for larger screens
5. **Test across viewports**
## Breakpoints
```css
/* Tailwind defaults */
sm: 640px /* Small devices */
md: 768px /* Tablets */
lg: 1024px /* Laptops */
xl: 1280px /* Desktops */
2xl: 1536px /* Large screens */
/* Custom CSS */
@media (min-width: 640px) { }
@media (min-width: 768px) { }
@media (min-width: 1024px) { }
```
## Common Layout Patterns
### 1. Holy Grail Layout
```tsx
// Tailwind CSS
<div className="min-h-screen flex flex-col">
<header className="h-16 bg-white border-b">Header</header>
<div className="flex-1 flex">
<aside className="hidden md:block w-64 bg-gray-50 border-r">
Sidebar
</aside>
<main className="flex-1 p-6">
Main Content
</main>
</div>
<footer className="h-16 bg-white border-t">Footer</footer>
</div>
```
```css
/* Plain CSS */
.layout {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr;
min-height: 100vh;
}
@media (min-width: 768px) {
.layout {
grid-template-columns: 250px 1fr;
}
.header, .footer {
grid-column: 1 / -1;
}
}
```
### 2. Responsive Card Grid
```tsx
// Tailwind - Auto-fit cards
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{items.map(item => (
<Card key={item.id} {...item} />
))}
</div>
// Auto-fill with minimum width
<div className="grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-6">
{items.map(item => (
<Card key={item.id} {...item} />
))}
</div>
```
```css
/* Plain CSS */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
```
### 3. Sidebar Layout
```tsx
// Fixed sidebar, scrollable content
<div className="flex h-screen">
<aside className="w-64 flex-shrink-0 overflow-y-auto border-r bg-gray-50">
<nav className="p-4">Sidebar Nav</nav>
</aside>
<main className="flex-1 overflow-y-auto">
<div className="p-6">Main Content</div>
</main>
</div>
// Collapsible sidebar
<div className="flex h-screen">
<aside className={cn(
"flex-shrink-0 overflow-y-auto border-r bg-gray-50 transition-all",
isOpen ? "w-64" : "w-16"
)}>
<nav className="p-4">...</nav>
</aside>
<main className="flex-1 overflow-y-auto p-6">...</main>
</div>
```
### 4. Hero Section
```tsx
<section className="relative min-h-[60vh] flex items-center justify-center px-4">
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-br from-blue-600 to-purple-700" />
{/* Content */}
<div className="relative z-10 max-w-4xl mx-auto text-center text-white">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold">
Headline Here
</h1>
<p className="mt-6 text-lg md:text-xl opacity-90 max-w-2xl mx-auto">
Subheadline text goes here with more details.
</p>
<div className="mt-8 flex flex-col sm:flex-row gap-4 justify-center">
<button className="px-8 py-3 bg-white text-blue-600 rounded-lg font-semibold">
Primary CTA
</button>
<button className="px-8 py-3 border-2 border-white rounded-lg font-semibold">
Secondary CTA
</button>
</div>
</div>
</section>
```
### 5. Masonry Grid
```tsx
// CSS Columns approach
<div className="columns-1 sm:columns-2 lg:columns-3 gap-6 space-y-6">
{items.map(item => (
<div key={item.id} className="break-inside-avoid">
<Card {...item} />
</div>
))}
</div>
```
### 6. Sticky Header
```tsx
<header className="sticky top-0 z-50 bg-white/80 backdrop-blur-md border-b">
<nav className="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between">
<Logo />
<NavLinks className="hidden md:flex" />
<MobileMenuButton className="md:hidden" />
</nav>
</header>
```
## Container Queries (Modern)
```css
/* Define container */
.card-container {
container-type: inline-size;
}
/* Query the container */
@container (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
}
}
```
```tsx
// Tailwind v3.2+
<div className="@container">
<div className="flex flex-col @md:flex-row">
<img className="w-full @md:w-48" />
<div className="p-4">Content</div>
</div>
</div>
```
## Flexbox vs Grid Decision
| Use Flexbox | Use Grid |
|-------------|----------|
| Navigation bars | Page layouts |
| Card content alignment | Card grids |
| Centering content | Complex 2D layouts |
| Space distribution | Overlapping elements |
| Unknown item count | Defined structure |
## Responsive Typography
```tsx
// Fluid typography with clamp
<h1 className="text-[clamp(2rem,5vw,4rem)]">
Responsive Heading
</h1>
// Tailwind responsive
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl">
Responsive Heading
</h1>
```
## Testing Checklist
- [ ] 320px (small phones)
- [ ] 375px (iPhone)
- [ ] 768px (tablet portrait)
- [ ] 1024px (tablet landscape / laptop)
- [ ] 1280px+ (desktop)
- [ ] Test with actual content (not lorem ipsum)
- [ ] Test with long/short content variations
+207
View File
@@ -0,0 +1,207 @@
---
name: test-coverage-improver
description: Analyze test coverage gaps and generate tests to improve coverage. Use when improving test coverage, finding untested code, or writing missing tests.
---
# Test Coverage Improver
## Instructions
When improving test coverage:
1. **Run coverage report** to identify gaps
2. **Prioritize** critical/complex code paths
3. **Write tests** for uncovered code
4. **Verify coverage improved**
## Generate Coverage Report
```bash
# Jest
npx jest --coverage
# Vitest
npx vitest --coverage
# NYC (Istanbul) for any test runner
npx nyc npm test
# View HTML report
open coverage/lcov-report/index.html
```
## Coverage Targets
| Type | Minimum | Good | Excellent |
|------|---------|------|-----------|
| Lines | 70% | 80% | 90%+ |
| Branches | 60% | 75% | 85%+ |
| Functions | 70% | 80% | 90%+ |
| Statements | 70% | 80% | 90%+ |
## Test Templates
### Unit Test (Jest/Vitest)
```typescript
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { calculateTotal, formatCurrency } from './utils';
describe('calculateTotal', () => {
it('should sum all item prices', () => {
const items = [
{ price: 10, quantity: 2 },
{ price: 5, quantity: 1 },
];
expect(calculateTotal(items)).toBe(25);
});
it('should return 0 for empty array', () => {
expect(calculateTotal([])).toBe(0);
});
it('should handle decimal prices', () => {
const items = [{ price: 10.99, quantity: 1 }];
expect(calculateTotal(items)).toBeCloseTo(10.99);
});
});
```
### Testing Async Functions
```typescript
describe('fetchUser', () => {
it('should return user data', async () => {
const user = await fetchUser(1);
expect(user).toEqual({
id: 1,
name: expect.any(String),
email: expect.stringContaining('@'),
});
});
it('should throw for non-existent user', async () => {
await expect(fetchUser(999)).rejects.toThrow('User not found');
});
});
```
### Mocking Dependencies
```typescript
import { vi } from 'vitest';
import { sendEmail } from './email';
import { createUser } from './user';
vi.mock('./email', () => ({
sendEmail: vi.fn().mockResolvedValue({ success: true }),
}));
describe('createUser', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should send welcome email after creating user', async () => {
await createUser({ name: 'John', email: 'john@test.com' });
expect(sendEmail).toHaveBeenCalledWith({
to: 'john@test.com',
template: 'welcome',
});
});
});
```
### React Component Testing
```tsx
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';
describe('Button', () => {
it('should render children', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('should call onClick when clicked', async () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('should be disabled when loading', () => {
render(<Button isLoading>Submit</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
});
```
### API Route Testing
```typescript
import { createMocks } from 'node-mocks-http';
import handler from './api/users';
describe('GET /api/users', () => {
it('should return users list', async () => {
const { req, res } = createMocks({ method: 'GET' });
await handler(req, res);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toHaveProperty('users');
});
});
```
## Branch Coverage Checklist
Ensure tests cover:
- [ ] If/else branches
- [ ] Ternary operators
- [ ] Switch cases (including default)
- [ ] Try/catch blocks
- [ ] Early returns
- [ ] Nullish coalescing (`??`)
- [ ] Optional chaining results (`?.`)
- [ ] Loop conditions (0, 1, many iterations)
## Coverage Configuration
```javascript
// vitest.config.ts
export default {
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'html', 'lcov'],
exclude: [
'node_modules/',
'**/*.d.ts',
'**/*.test.ts',
'**/types/',
],
thresholds: {
lines: 80,
branches: 75,
functions: 80,
statements: 80,
},
},
},
};
```
## Priority Order for Testing
1. **Critical paths**: Auth, payments, data mutations
2. **Complex logic**: Algorithms, state machines, calculations
3. **Error handlers**: Catch blocks, error boundaries
4. **Edge cases**: Empty arrays, null values, boundaries
5. **Integration points**: API calls, database queries