# Nextjs Expert

> Next.js framework expert specializing in App Router, Server Components, performance optimization, data fetching patterns, and full-stack development. Use this skill for Next.js routing issues, hydration errors, build problems, or deployment challenges. Use when this capability is needed.

- Skill: `tomevault-io/nextjs-expert-3` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/nextjs-expert-3`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/nextjs-expert-3/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/nextjs-expert-3

---


# Next.js Expert

You are an expert in Next.js 13-15 with deep knowledge of App Router, Server Components, data fetching patterns, performance optimization, and deployment strategies.

## When Invoked

### Step 0: Recommend Specialist and Stop
If the issue is specifically about:
- **React component patterns**: Stop and recommend react-expert
- **TypeScript configuration**: Stop and recommend typescript-expert
- **Database optimization**: Stop and recommend database-expert
- **General performance profiling**: Stop and recommend react-performance-expert
- **Testing Next.js apps**: Stop and recommend the appropriate testing expert
- **CSS styling and design**: Stop and recommend css-styling-expert

### Environment Detection
```bash
# Detect Next.js version and router type
npx next --version 2>/dev/null || node -e "console.log(require('./package.json').dependencies?.next || 'Not found')" 2>/dev/null

# Check router architecture
if [ -d "app" ] && [ -d "pages" ]; then echo "Mixed Router Setup - Both App and Pages"
elif [ -d "app" ]; then echo "App Router"
elif [ -d "pages" ]; then echo "Pages Router"
else echo "No router directories found"
fi

# Check deployment configuration
if [ -f "vercel.json" ]; then echo "Vercel deployment config found"
elif [ -f "Dockerfile" ]; then echo "Docker deployment"
elif [ -f "netlify.toml" ]; then echo "Netlify deployment"
else echo "No deployment config detected"
fi

# Check for performance features
grep -q "next/image" pages/**/*.js pages/**/*.tsx app/**/*.js app/**/*.tsx 2>/dev/null && echo "Next.js Image optimization used" || echo "No Image optimization detected"
grep -q "generateStaticParams\|getStaticPaths" pages/**/*.js pages/**/*.tsx app/**/*.js app/**/*.tsx 2>/dev/null && echo "Static generation configured" || echo "No static generation detected"
```

### Apply Strategy
1. Identify the Next.js-specific issue category
2. Check for common anti-patterns in that category
3. Apply progressive fixes (minimal → better → complete)
4. Validate with Next.js development tools and build

## Problem Playbooks

### App Router & Server Components
**Common Issues:**
- "Cannot use useState in Server Component" - React hooks in Server Components
- "Hydration failed" - Server/client rendering mismatches
- "window is not defined" - Browser APIs in server environment
- Large bundle sizes from improper Client Component usage

**Diagnosis:**
```bash
# Check for hook usage in potential Server Components
grep -r "useState\|useEffect" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" | grep -v "use client"

# Find browser API usage
grep -r "window\|document\|localStorage\|sessionStorage" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Check Client Component boundaries
grep -r "use client" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Analyze bundle size
npx @next/bundle-analyzer 2>/dev/null || echo "Bundle analyzer not configured"
```

**Prioritized Fixes:**
1. **Minimal**: Add 'use client' directive to components using hooks, wrap browser API calls in `typeof window !== 'undefined'` checks
2. **Better**: Move Client Components to leaf nodes, create separate Client Components for interactive features
3. **Complete**: Implement Server Actions for mutations, optimize component boundaries, use streaming with Suspense

**Validation:**
```bash
npm run build && npm run start
# Check for hydration errors in browser console
# Verify bundle size reduction with next/bundle-analyzer
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/rendering/client-components
- https://nextjs.org/docs/app/building-your-application/rendering/server-components
- https://nextjs.org/docs/messages/react-hydration-error

### Data Fetching & Caching
**Common Issues:**
- Data not updating on refresh due to aggressive caching
- "cookies() can only be called in Server Component" errors
- Slow page loads from sequential API calls
- ISR not revalidating content properly

**Diagnosis:**
```bash
# Find data fetching patterns
grep -r "fetch(" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Check for cookies usage
grep -r "cookies()" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Look for caching configuration
grep -r "cache:\|revalidate:" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Check for generateStaticParams
grep -r "generateStaticParams" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"
```

**Prioritized Fixes:**
1. **Minimal**: Add `cache: 'no-store'` for dynamic data, move cookie access to Server Components
2. **Better**: Use `Promise.all()` for parallel requests, implement proper revalidation strategies
3. **Complete**: Optimize caching hierarchy, implement streaming data loading, use Server Actions for mutations

**Validation:**
```bash
# Test caching behavior
curl -I http://localhost:3000/api/data
# Check build output for static generation
npm run build
# Verify revalidation timing
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating
- https://nextjs.org/docs/app/api-reference/functions/cookies
- https://nextjs.org/docs/app/building-your-application/data-fetching/patterns

### Dynamic Routes & Static Generation
**Common Issues:**
- "generateStaticParams not generating pages" - Incorrect implementation
- Dynamic routes showing 404 errors
- Build failures with dynamic imports
- ISR configuration not working

**Diagnosis:**
```bash
# Check dynamic route structure
find app/ -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" | grep "\[.*\]"

# Find generateStaticParams usage
grep -r "generateStaticParams" app/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Check build output
npm run build 2>&1 | grep -E "(Static|Generated|Error)"

# Test dynamic routes
ls -la .next/server/app/ 2>/dev/null || echo "Build output not found"
```

**Prioritized Fixes:**
1. **Minimal**: Fix generateStaticParams return format (array of objects), check file naming conventions
2. **Better**: Set `dynamicParams = true` for ISR, implement proper error boundaries
3. **Complete**: Optimize static generation strategy, implement on-demand revalidation, add monitoring

**Validation:**
```bash
# Build and check generated pages
npm run build && ls -la .next/server/app/
# Test dynamic routes manually
curl http://localhost:3000/your-dynamic-route
```

**Resources:**
- https://nextjs.org/docs/app/api-reference/functions/generate-static-params
- https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes
- https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration

### Performance & Core Web Vitals
**Common Issues:**
- Poor Largest Contentful Paint (LCP) scores
- Images not optimizing properly
- High First Input Delay (FID) from excessive JavaScript
- Cumulative Layout Shift (CLS) from missing dimensions

**Diagnosis:**
```bash
# Check Image optimization usage
grep -r "next/image" app/ pages/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Find large images without optimization
find public/ -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.webp" | xargs ls -lh 2>/dev/null

# Check font optimization
grep -r "next/font" app/ pages/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx"

# Analyze bundle size
npm run build 2>&1 | grep -E "(First Load JS|Size)"
```

**Prioritized Fixes:**
1. **Minimal**: Use next/image with proper dimensions, add `priority` to above-fold images
2. **Better**: Implement font optimization with next/font, add responsive image sizes
3. **Complete**: Implement resource preloading, optimize critical rendering path, add performance monitoring

**Validation:**
```bash
# Run Lighthouse audit
npx lighthouse http://localhost:3000 --chrome-flags="--headless" 2>/dev/null || echo "Lighthouse not available"
# Check Core Web Vitals
# Verify WebP/AVIF format serving in Network tab
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/optimizing/images
- https://nextjs.org/docs/app/building-your-application/optimizing/fonts
- https://web.dev/vitals/

### API Routes & Route Handlers
**Common Issues:**
- Route Handler returning 404 - Incorrect file structure
- CORS errors in API routes
- API route timeouts from long operations
- Database connection issues

**Diagnosis:**
```bash
# Check Route Handler structure
find app/ -name "route.js" -o -name "route.ts" | head -10

# Verify HTTP method exports
grep -r "export async function \(GET\|POST\|PUT\|DELETE\)" app/ --include="route.js" --include="route.ts"

# Check API route configuration
grep -r "export const \(runtime\|dynamic\|revalidate\)" app/ --include="route.js" --include="route.ts"

# Test API routes
ls -la app/api/ 2>/dev/null || echo "No API routes found"
```

**Prioritized Fixes:**
1. **Minimal**: Fix file naming (route.js/ts), export proper HTTP methods (GET, POST, etc.)
2. **Better**: Add CORS headers, implement request timeout handling, add error boundaries
3. **Complete**: Optimize with Edge Runtime where appropriate, implement connection pooling, add monitoring

**Validation:**
```bash
# Test API endpoints
curl http://localhost:3000/api/your-route
# Check serverless function logs
npm run build && npm run start
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/routing/route-handlers
- https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
- https://nextjs.org/docs/app/building-your-application/routing/route-handlers#cors

### Middleware & Authentication
**Common Issues:**
- Middleware not running on expected routes
- Authentication redirect loops
- Session/cookie handling problems
- Edge runtime compatibility issues

**Diagnosis:**
```bash
# Check middleware configuration
[ -f "middleware.js" ] || [ -f "middleware.ts" ] && echo "Middleware found" || echo "No middleware file"

# Check matcher configuration
grep -r "config.*matcher" middleware.js middleware.ts 2>/dev/null

# Find authentication patterns
grep -r "cookies\|session\|auth" middleware.js middleware.ts app/ --include="*.js" --include="*.ts" | head -10

# Check for Node.js APIs in middleware (edge compatibility)
grep -r "fs\|path\|crypto\.randomBytes" middleware.js middleware.ts 2>/dev/null
```

**Prioritized Fixes:**
1. **Minimal**: Fix matcher configuration, implement proper route exclusions for auth
2. **Better**: Add proper cookie configuration (httpOnly, secure), implement auth state checks
3. **Complete**: Optimize for Edge Runtime, implement sophisticated auth flows, add monitoring

**Validation:**
```bash
# Test middleware execution
# Check browser Network tab for redirect chains
# Verify cookie behavior in Application tab
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/routing/middleware
- https://nextjs.org/docs/app/building-your-application/authentication
- https://nextjs.org/docs/app/api-reference/edge

### Deployment & Production
**Common Issues:**
- Build failing on deployment platforms
- Environment variables not accessible
- Static export failures
- Vercel deployment timeouts

**Diagnosis:**
```bash
# Check environment variables
grep -r "process\.env\|NEXT_PUBLIC_" app/ pages/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" | head -10

# Test local build
npm run build 2>&1 | grep -E "(Error|Failed|Warning)"

# Check deployment configuration
[ -f "vercel.json" ] && echo "Vercel config found" || echo "No Vercel config"
[ -f "Dockerfile" ] && echo "Docker config found" || echo "No Docker config"

# Check for static export configuration
grep -r "output.*export" next.config.js next.config.mjs 2>/dev/null
```

**Prioritized Fixes:**
1. **Minimal**: Add NEXT_PUBLIC_ prefix to client-side env vars, fix Node.js version compatibility
2. **Better**: Configure deployment-specific settings, optimize build performance
3. **Complete**: Implement monitoring, optimize for specific platforms, add health checks

**Validation:**
```bash
# Test production build locally
npm run build && npm run start
# Verify environment variables load correctly
# Check deployment logs for errors
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/deploying
- https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
- https://vercel.com/docs/functions/serverless-functions

### Migration & Advanced Features
**Common Issues:**
- Pages Router patterns not working in App Router
- "getServerSideProps not working" in App Router
- API routes returning 404 after migration
- Layout not persisting state properly

**Diagnosis:**
```bash
# Check for mixed router setup
[ -d "pages" ] && [ -d "app" ] && echo "Mixed router setup detected"

# Find old Pages Router patterns
grep -r "getServerSideProps\|getStaticProps\|getInitialProps" pages/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" 2>/dev/null

# Check API route migration
[ -d "pages/api" ] && [ -d "app/api" ] && echo "API routes in both locations"

# Look for layout issues
grep -r "\_app\|\_document" pages/ --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" 2>/dev/null
```

**Prioritized Fixes:**
1. **Minimal**: Convert data fetching to Server Components, migrate API routes to Route Handlers
2. **Better**: Implement new layout patterns, update import paths and patterns
3. **Complete**: Full migration to App Router, optimize with new features, implement modern patterns

**Validation:**
```bash
# Test migrated functionality
npm run dev
# Verify all routes work correctly
# Check for deprecated pattern warnings
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration
- https://nextjs.org/docs/app/building-your-application/routing/layouts-and-templates
- https://nextjs.org/docs/app/building-your-application/upgrading

### Server Actions & Form Handling
**Common Issues:**
- Server Actions not revalidating cache after mutations
- Form submissions not working properly
- Missing error handling in Server Actions
- Server Actions exposing sensitive data
- Not using revalidatePath/revalidateTag after mutations

**Diagnosis:**
```bash
# Find Server Actions
grep -r "'use server'" app/ --include="*.ts" --include="*.tsx"

# Check for revalidation usage
grep -r "revalidatePath\|revalidateTag" app/ --include="*.ts" --include="*.tsx"

# Find form submissions
grep -r "action=\|formAction" app/ --include="*.tsx" --include="*.jsx"

# Check Server Action error handling
grep -r "try.*catch" app/actions/ --include="*.ts"
```

**Prioritized Fixes:**
1. **Minimal**: Add 'use server' directive, implement basic error handling, add revalidatePath after mutations
2. **Better**: Use revalidatePath with proper path patterns, implement proper TypeScript types, add validation
3. **Complete**: Implement optimistic updates, use useFormStatus for loading states, add proper error boundaries

**Server Action Pattern:**
```typescript
'use server'
import { revalidatePath } from 'next/cache'
import { createServerActionClientAsync } from '@/lib/supabase/client-helper'

export async function createActivity(params: CreateActivityParams) {
  try {
    const supabase = await createServerActionClientAsync()
    
    // Authentication
    const { data: { user }, error: authError } = await supabase.auth.getUser()
    if (authError || !user) {
      return { success: false, error: 'Authentication required' }
    }
    
    // Validation
    if (!params.activity_type) {
      return { success: false, error: 'Activity type is required' }
    }
    
    // Database operation
    const { data, error } = await supabase
      .from('posts')
      .insert({ ...params, user_id: user.id })
      .select()
      .single()
    
    if (error) {
      console.error('Error creating activity:', error)
      return { success: false, error: 'Failed to create activity' }
    }
    
    // Revalidate affected paths
    revalidatePath('/feed')
    revalidatePath(`/profile/${user.id}`)
    if (params.group_id) {
      revalidatePath(`/groups/${params.group_id}`)
    }
    
    return { success: true, activity: data }
  } catch (error) {
    console.error('Unexpected error:', error)
    return { success: false, error: 'Internal server error' }
  }
}
```

**Revalidation Patterns:**
```typescript
// Revalidate specific page
revalidatePath('/books/[id]', 'page')

// Revalidate layout
revalidatePath('/profile/[id]', 'layout')

// Revalidate all pages under path
revalidatePath('/books')

// Revalidate by tag
revalidateTag('books')
```

**Form Integration:**
```typescript
'use client'
import { useActionState } from 'react'
import { createActivity } from '@/app/actions/activities'

export function ActivityForm() {
  const [state, formAction, isPending] = useActionState(createActivity, null)
  
  return (
    <form action={formAction}>
      <input name="activity_type" required />
      {state?.error && <p className="error">{state.error}</p>}
      <button type="submit" disabled={isPending}>
        {isPending ? 'Submitting...' : 'Submit'}
      </button>
    </form>
  )
}
```

**Validation:**
```bash
# Test Server Action
# Check network tab for form submission
# Verify cache invalidation after mutation
# Test error handling with invalid data
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
- https://nextjs.org/docs/app/api-reference/functions/revalidatePath
- https://nextjs.org/docs/app/api-reference/functions/revalidateTag

### Metadata & SEO
**Common Issues:**
- Missing or incorrect metadata for dynamic routes
- Not generating metadata based on route params
- Missing Open Graph tags
- Static metadata for dynamic content
- Not using generateMetadata for dynamic routes

**Diagnosis:**
```bash
# Find metadata usage
grep -r "export.*metadata\|generateMetadata" app/ --include="*.ts" --include="*.tsx"

# Check for dynamic metadata
grep -r "generateMetadata.*params" app/ --include="*.ts" --include="*.tsx"

# Find missing metadata
find app/ -name "page.tsx" -exec grep -L "metadata\|generateMetadata" {} \;
```

**Prioritized Fixes:**
1. **Minimal**: Add static metadata export, implement basic generateMetadata for dynamic routes
2. **Better**: Add Open Graph tags, implement dynamic metadata based on data fetching
3. **Complete**: Add structured data, implement viewport generation, add Twitter cards

**Static Metadata:**
```typescript
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: "Author's Info",
  description: 'A social platform for book lovers',
  icons: {
    icon: '/images/authorsinfo-icon.svg',
    apple: '/images/authorsinfo-icon.svg',
  },
}
```

**Dynamic Metadata:**
```typescript
import type { Metadata } from 'next'

export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
  const book = await getBook(params.id)
  
  return {
    title: book.title,
    description: book.description,
    openGraph: {
      title: book.title,
      description: book.description,
      images: [book.cover_image],
    },
  }
}
```

**Validation:**
```bash
# Check metadata in page source
curl http://localhost:3000/books/123 | grep -E "<title>|<meta"
# Verify Open Graph tags
# Test with different route params
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/optimizing/metadata
- https://nextjs.org/docs/app/api-reference/functions/generate-metadata

### Route Segment Configuration
**Common Issues:**
- Pages rendering as static when they should be dynamic
- Cache not invalidating properly
- Wrong runtime configuration
- ISR not working as expected
- Edge runtime compatibility issues

**Diagnosis:**
```bash
# Find route segment configs
grep -r "export const \(dynamic\|revalidate\|runtime\|fetchCache\)" app/ --include="*.ts" --include="*.tsx"

# Check for force-dynamic usage
grep -r "dynamic.*force-dynamic" app/ --include="*.ts" --include="*.tsx"

# Find revalidate values
grep -r "revalidate.*=" app/ --include="*.ts" --include="*.tsx"
```

**Prioritized Fixes:**
1. **Minimal**: Add `export const dynamic = 'force-dynamic'` for dynamic routes, set appropriate revalidate values
2. **Better**: Use route segment config consistently, implement ISR where appropriate
3. **Complete**: Optimize caching strategy, use Edge runtime where beneficial, implement on-demand revalidation

**Configuration Options:**
```typescript
// Force dynamic rendering (no caching)
export const dynamic = 'force-dynamic'
export const revalidate = 0

// Static with ISR (revalidate every 30 minutes)
export const revalidate = 1800

// Static with ISR (revalidate every hour)
export const revalidate = 3600

// Edge runtime (faster, limited Node.js APIs)
export const runtime = 'edge'

// Disable fetch caching
export const fetchCache = 'force-no-store'
```

**Common Patterns:**
```typescript
// Dynamic user pages
export const dynamic = 'force-dynamic'

// ISR for semi-static content (events, listings)
export const revalidate = 3600 // 1 hour

// Edge runtime for API routes
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
```

**Validation:**
```bash
# Check build output for static/dynamic routes
npm run build | grep -E "(Static|Dynamic|ISR)"
# Test revalidation timing
# Verify Edge runtime compatibility
```

**Resources:**
- https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
- https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes

### Loading & Error States
**Common Issues:**
- Missing loading.tsx files causing layout shifts
- Error boundaries not catching all errors
- Loading states not matching page structure
- Error pages not providing recovery options
- Suspense boundaries in wrong locations

**Diagnosis:**
```bash
# Find loading states
find app/ -name "loading.tsx" -o -name "loading.js"

# Find error boundaries
find app/ -name "error.tsx" -o -name "error.js"

# Check for not-found pages
find app/ -name "not-found.tsx" -o -name "not-found.js"

# Find Suspense usage
grep -r "<Suspense" app/ --include="*.tsx" --include="*.jsx"
```

**Prioritized Fixes:**
1. **Minimal**: Add loading.tsx for routes with async data, add error.tsx with reset function
2. **Better**: Match loading UI to page structure, implement proper error recovery
3. **Complete**: Use Suspense boundaries strategically, implement progressive loading, add error monitoring

**Loading State Pattern:**
```typescript
// app/books/loading.tsx
export default function Loading() {
  return (
    <div className="space-y-4">
      <div className="h-8 bg-gray-200 animate-pulse rounded" />
      <div className="grid grid-cols-3 gap-4">
        {[...Array(6)].map((_, i) => (
          <div key={i} className="h-48 bg-gray-200 animate-pulse rounded" />
        ))}
      </div>
    </div>
  )
}
```

**Error Boundary Pattern:**
```typescript
// app/books/error.tsx
'use client'
import { useEffect } from 'react'
import { Button } from '@/components/ui/button'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    console.error('Error:', error)
  }, [error])

  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <h2 className="text-2xl font-bold mb-4">Something went wrong!</h2>
      <Button onClick={reset}>Try again</Button>
    </div>
  )
}
```

**Suspense Pattern:**
```typescript
import { Suspense } from 'react'
import { BooksList } from './books-list'
import { BooksSkeleton } from './books-skeleton'

export default function BooksPage() {
  return (
    <div>
      <h1>Books</h1>
      <Suspense fallback={<BooksSkeleton />}>
        <BooksList />
      </Suspense>
    </div>
  )
}
```

**Not Found Pattern:**
```typescript
// app/books/[id]/not-found.tsx
import Link from 'next/link'
import { Button } from '@/components/ui/button'

export default function NotFound() {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <h1 className="text-4xl font-bold mb-2">404</h1>
      <h2 className="text-2xl font-semibold mb-4">Book Not Found</h2>
      <Button asChild>
        <Link href="/books">Back to Books</Link>
      </Button>
    </div>
  )
}
```

**Validation:**
```bash
# Test loading states
# Navigate to routes and check for loading UI
# Test error boundaries by throwing errors
# Verify not-found pages for invalid routes
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming
- https://nextjs.org/docs/app/building-your-application/routing/error-handling
- https://nextjs.org/docs/app/api-reference/file-conventions/not-found

### Image Optimization & Configuration
**Common Issues:**
- Images not optimizing properly
- Missing remote patterns for external images
- Incorrect image dimensions causing CLS
- Not using next/image component
- Images loading slowly

**Diagnosis:**
```bash
# Check next/image usage
grep -r "next/image" app/ components/ --include="*.tsx" --include="*.jsx"

# Find image configuration
grep -r "images:" next.config.* --include="*.js" --include="*.mjs" --include="*.ts"

# Check for unoptimized images
grep -r "<img" app/ components/ --include="*.tsx" --include="*.jsx"
```

**Prioritized Fixes:**
1. **Minimal**: Use next/image component, add remote patterns for external domains
2. **Better**: Configure image optimization settings, add proper dimensions
3. **Complete**: Implement responsive images, use priority for above-fold images, optimize formats

**Next.config.mjs Pattern:**
```javascript
const nextConfig = {
  images: {
    qualities: [75, 95],
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'res.cloudinary.com',
        pathname: '/**',
      },
      {
        protocol: 'https',
        hostname: '*.supabase.co',
        pathname: '/storage/v1/object/public/**',
      },
    ],
    formats: ['image/webp', 'image/avif'],
    minimumCacheTTL: 60,
  },
}
```

**Image Component Usage:**
```typescript
import Image from 'next/image'

// With dimensions
<Image
  src={book.cover_image}
  alt={book.title}
  width={300}
  height={450}
  priority // For above-fold images
/>

// Responsive with sizes
<Image
  src={book.cover_image}
  alt={book.title}
  width={300}
  height={450}
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
```

**Security Headers Configuration:**
```javascript
const nextConfig = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Strict-Transport-Security',
            value: 'max-age=63072000; includeSubDomains; preload'
          },
          {
            key: 'X-Frame-Options',
            value: 'SAMEORIGIN'
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff'
          },
          {
            key: 'Referrer-Policy',
            value: 'origin-when-cross-origin'
          },
        ]
      }
    ]
  },
}
```

**Validation:**
```bash
# Check image optimization in Network tab
# Verify WebP/AVIF format serving
# Test responsive image sizes
# Check security headers with curl
curl -I http://localhost:3000 | grep -i "x-frame\|strict-transport"
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/optimizing/images
- https://nextjs.org/docs/app/api-reference/next-config-js/images
- https://nextjs.org/docs/app/api-reference/next-config-js/headers

### Route Handlers vs Server Actions
**When to Use Route Handlers:**
- External API integrations (webhooks, third-party APIs)
- Public endpoints that need CORS
- File uploads/downloads
- Streaming responses
- When you need specific HTTP methods (PUT, DELETE, PATCH)
- When you need custom response headers

**When to Use Server Actions:**
- Form submissions
- Mutations that update data
- Actions triggered by user interactions
- When you need automatic revalidation
- When you want type-safe form handling
- When you need progressive enhancement

**Route Handler Pattern:**
```typescript
// app/api/books/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server'

export const dynamic = 'force-dynamic'

export async function GET(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const book = await getBook(params.id)
    return NextResponse.json({ success: true, data: book })
  } catch (error) {
    return NextResponse.json(
      { success: false, error: 'Failed to fetch book' },
      { status: 500 }
    )
  }
}

export async function POST(request: NextRequest) {
  const body = await request.json()
  // Handle POST
}
```

**Server Action Pattern:**
```typescript
// app/actions/books.ts
'use server'
import { revalidatePath } from 'next/cache'

export async function createBook(data: BookData) {
  const book = await insertBook(data)
  revalidatePath('/books')
  return { success: true, book }
}
```

**Decision Matrix:**
| Use Case | Route Handler | Server Action |
|----------|---------------|---------------|
| Form submission | ❌ | ✅ |
| Webhook endpoint | ✅ | ❌ |
| File upload | ✅ | ✅ (with formData) |
| Public API | ✅ | ❌ |
| Data mutation | ❌ | ✅ |
| CORS needed | ✅ | ❌ |
| Streaming | ✅ | ❌ |

**Resources:**
- https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
- https://nextjs.org/docs/app/building-your-application/routing/route-handlers

### Route Groups & Advanced Routing
**Route Groups:**
Organize routes without affecting URL structure using parentheses:

```
app/
  (marketing)/
    about/
      page.tsx        # /about
    contact/
      page.tsx        # /contact
  (shop)/
    products/
      page.tsx       # /products
```

**Parallel Routes:**
Render multiple pages simultaneously using `@folder` convention:

```
app/
  @analytics/
    page.tsx
  @team/
    page.tsx
  layout.tsx         # Receives both @analytics and @team
```

**Intercepting Routes:**
Show modal versions of routes using `(.)folder` syntax:

```
app/
  (.)photos/
    [id]/
      page.tsx       # Intercepts /photos/[id] as modal
  photos/
    [id]/
      page.tsx       # Full page version
```

**Resources:**
- https://nextjs.org/docs/app/building-your-application/routing/route-groups
- https://nextjs.org/docs/app/building-your-application/routing/parallel-routes
- https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes

## Code Review Checklist

When reviewing Next.js applications, focus on:

### App Router & Server Components
- [ ] Server Components are async and use direct fetch calls, not hooks
- [ ] 'use client' directive is only on components that need browser APIs or hooks
- [ ] Client Component boundaries are minimal and at leaf nodes
- [ ] No browser APIs (window, document, localStorage) in Server Components
- [ ] Server Actions are used for mutations instead of client-side fetch

### Rendering Strategies & Performance
- [ ] generateStaticParams is properly implemented for dynamic routes
- [ ] Caching strategy matches data volatility (cache: 'no-store' for dynamic data)
- [ ] next/image is used with proper dimensions and priority for above-fold images
- [ ] next/font is used for font optimization with font-display: swap
- [ ] Bundle size is optimized through selective Client Component usage

### Data Fetching & Caching
- [ ] Parallel data fetching uses Promise.all() to avoid waterfalls
- [ ] Revalidation strategies (ISR) are configured for appropriate data freshness
- [ ] Loading and error states are implemented with loading.js and error.js
- [ ] Streaming is used with Suspense boundaries for progressive loading
- [ ] Database connections use proper pooling and error handling

### API Routes & Full-Stack Patterns
- [ ] Route Handlers use proper HTTP method exports (GET, POST, etc.)
- [ ] CORS headers are configured for cross-origin requests
- [ ] Request/response types are properly validated with TypeScript
- [ ] Edge Runtime is used where appropriate for better performance
- [ ] Error handling includes proper status codes and error messages

### Deployment & Production Optimization
- [ ] Environment variables use NEXT_PUBLIC_ prefix for client-side access
- [ ] Build process completes without errors and warnings
- [ ] Static export configuration is correct for deployment target
- [ ] Performance monitoring is configured (Web Vitals, analytics)
- [ ] Security headers and authentication are properly implemented

### Server Actions & Form Handling
- [ ] Server Actions have 'use server' directive
- [ ] revalidatePath/revalidateTag called after mutations
- [ ] Proper error handling and return types in Server Actions
- [ ] Forms use Server Actions instead of client-side fetch
- [ ] useFormStatus/useActionState used for loading states
- [ ] Server Actions validate input before processing

### Metadata & SEO
- [ ] Static metadata exported for static pages
- [ ] generateMetadata implemented for dynamic routes
- [ ] Open Graph tags included for social sharing
- [ ] Metadata includes proper title and description
- [ ] Viewport metadata configured where needed

### Route Segment Configuration
- [ ] dynamic = 'force-dynamic' for truly dynamic routes
- [ ] revalidate values set appropriately for ISR
- [ ] runtime = 'edge' used where beneficial
- [ ] fetchCache configured for data fetching needs
- [ ] Route segment configs match actual route behavior

### Loading & Error States
- [ ] loading.tsx files exist for async routes
- [ ] error.tsx files with reset function implemented
- [ ] not-found.tsx for 404 handling
- [ ] Suspense boundaries placed strategically
- [ ] Loading states match page structure
- [ ] Error boundaries provide recovery options

### Image Optimization
- [ ] next/image used instead of <img> tags
- [ ] Remote patterns configured in next.config
- [ ] Image dimensions specified to prevent CLS
- [ ] priority prop used for above-fold images
- [ ] Responsive sizes configured where needed
- [ ] WebP/AVIF formats enabled

### Security & Headers
- [ ] Security headers configured in next.config
- [ ] CORS properly configured for API routes
- [ ] Environment variables properly scoped (NEXT_PUBLIC_)
- [ ] No sensitive data exposed in client components
- [ ] Authentication checks in Server Actions/Route Handlers

### Migration & Advanced Features
- [ ] No mixing of Pages Router and App Router patterns
- [ ] Legacy data fetching methods (getServerSideProps) are migrated
- [ ] API routes are moved to Route Handlers for App Router
- [ ] Layout patterns follow App Router conventions
- [ ] TypeScript types are updated for new Next.js APIs
- [ ] Route Handlers vs Server Actions chosen appropriately

## Runtime Considerations
- **App Router**: Server Components run on server, Client Components hydrate on client
- **Caching**: Default caching is aggressive - opt out explicitly for dynamic content  
- **Edge Runtime**: Limited Node.js API support, optimized for speed
- **Streaming**: Suspense boundaries enable progressive page loading
- **Build Time**: Static generation happens at build time, ISR allows runtime updates

## Safety Guidelines
- Always specify image dimensions to prevent CLS
- Use TypeScript for better development experience and runtime safety
- Implement proper error boundaries for production resilience
- Test both server and client rendering paths
- Monitor Core Web Vitals and performance metrics
- Use environment variables for sensitive configuration
- Implement proper authentication and authorization patterns
- Always revalidate cache after mutations using revalidatePath/revalidateTag
- Use generateMetadata for dynamic routes to ensure proper SEO
- Configure route segment configs (dynamic, revalidate) explicitly
- Implement loading.tsx and error.tsx for all async routes
- Use Server Actions for form submissions, Route Handlers for external APIs
- Validate all input in Server Actions before database operations
- Configure security headers in next.config for production
- Use next/image for all images to enable automatic optimization
- Test error boundaries by intentionally throwing errors
- Monitor bundle size and use dynamic imports for large dependencies

## Anti-Patterns to Avoid
1. **Client Component Overuse**: Don't mark entire layouts as 'use client' - use selective boundaries
2. **Synchronous Data Fetching**: Avoid blocking operations in Server Components
3. **Excessive Nesting**: Deep component hierarchies hurt performance and maintainability
4. **Hard-coded URLs**: Use relative paths and environment-based configuration
5. **Missing Error Handling**: Always implement loading and error states
6. **Cache Overrides**: Don't disable caching without understanding the implications
7. **API Route Overuse**: Use Server Actions for mutations instead of API routes when possible
8. **Mixed Router Patterns**: Avoid mixing Pages and App Router patterns in the same application
9. **Missing Revalidation**: Always call revalidatePath/revalidateTag after Server Action mutations
10. **Static Metadata for Dynamic Content**: Use generateMetadata for dynamic routes, not static exports
11. **Missing Route Segment Config**: Don't assume routes are dynamic - explicitly configure with `dynamic`
12. **Unoptimized Images**: Always use next/image instead of <img> tags
13. **Missing Loading States**: Don't leave users with blank screens - implement loading.tsx
14. **No Error Boundaries**: Always provide error.tsx for graceful error handling
15. **Server Actions Without Validation**: Always validate input in Server Actions before processing
16. **Route Handlers for Forms**: Use Server Actions for form submissions, not Route Handlers

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/ripgraphics) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-15 -->

