Skip to main content
ClaudeWave
Skill171 repo starsupdated 1mo ago

Next.js App Router & Server Components

Build Next.js 15 applications using App Router, Server Components, Client Components, Server Actions, and streaming. Apply when creating pages, handling data fetching, implementing routes, or optimizing performance.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/ThamJiaHe/claude-code-handbook /tmp/next.js-app-router-server-components && cp -r /tmp/next.js-app-router-server-components/skills/examples/nextjs-app-router- ~/.claude/skills/next.js-app-router-server-components
Then start a new Claude Code session; the skill loads automatically.

nextjs-app-router-skill.md

# Next.js App Router & Server Components

Systematic Next.js 15 development with App Router, Server Components, and performance optimization.

## Overview

This Skill enforces:
- Server Components by default (use client only when needed)
- Proper data fetching patterns
- File-based routing with App Router
- Server Actions for mutations
- Streaming and Suspense boundaries
- Performance optimization
- Route handlers and middleware

Apply when building Next.js pages, implementing routes, or optimizing performance.

## Server vs Client Components

**Default: Server Components** (no directive needed)
**When needed: Client Components** (add `'use client'`)

### Decision Tree

```
Does component need browser APIs?
├─ YES → Client Component ('use client')
└─ NO → Server Component (default)

Does component need event handlers?
├─ YES → Client Component
└─ NO → Server Component

Does component need state or effects?
├─ YES → Client Component
└─ NO → Server Component

Does component fetch data?
├─ YES → Server Component (preferred)
└─ NO → Check other criteria
```

## Server Components (Default)

### Benefits

- Runs on server only
- Zero JavaScript sent to browser
- Direct database access
- Access to secrets
- Better SEO
- Faster initial load

### Example

```tsx
// app/users/page.tsx
// No 'use client' = Server Component
import { db } from '@/lib/db';

export default async function UsersPage() {
  // Direct database query (server-only)
  const users = await db.user.findMany();

  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}
```

### Data Fetching in Server Components

```tsx
// ✅ GOOD: Async component with await
export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 3600 }  // Cache for 1 hour
  });
  const result = await data.json();

  return <div>{result.title}</div>;
}

// ✅ GOOD: Parallel data fetching
export default async function Page() {
  const [users, posts] = await Promise.all([
    fetch('https://api.example.com/users').then(r => r.json()),
    fetch('https://api.example.com/posts').then(r => r.json())
  ]);

  return (
    <div>
      <Users data={users} />
      <Posts data={posts} />
    </div>
  );
}

// ❌ BAD: useEffect in Server Component
export default function Page() {
  useEffect(() => {
    // This doesn't work in Server Components!
    fetchData();
  }, []);
}
```

## Client Components

### When to Use

Add `'use client'` when you need:
- Event handlers (onClick, onChange, etc.)
- State (useState, useReducer)
- Effects (useEffect, useLayoutEffect)
- Browser APIs (localStorage, window, navigator)
- Custom hooks that use above
- Interactive UI (modals, dropdowns, forms with validation)

### Example

```tsx
// app/components/Counter.tsx
'use client';

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}
```

### Composing Server and Client

```tsx
// app/page.tsx (Server Component)
import { Counter } from './components/Counter';  // Client Component

export default async function Page() {
  const data = await fetch('https://api.example.com/stats');
  const stats = await data.json();

  return (
    <div>
      <h1>Dashboard</h1>
      <p>Server-rendered stats: {stats.total}</p>
      
      {/* Client Component embedded in Server Component */}
      <Counter />
    </div>
  );
}
```

## File-Based Routing

### App Router Structure

```
app/
├── layout.tsx          # Root layout (wraps all pages)
├── page.tsx            # Home page (/)
├── about/
│   └── page.tsx        # About page (/about)
├── blog/
│   ├── page.tsx        # Blog list (/blog)
│   └── [slug]/
│       └── page.tsx    # Blog post (/blog/post-1)
├── dashboard/
│   ├── layout.tsx      # Nested layout
│   ├── page.tsx        # Dashboard (/dashboard)
│   └── settings/
│       └── page.tsx    # Settings (/dashboard/settings)
└── api/
    └── users/
        └── route.ts    # API route (/api/users)
```

### Layouts

**Root Layout** (required):

```tsx
// app/layout.tsx
export default function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <nav>Navigation</nav>
        {children}
        <footer>Footer</footer>
      </body>
    </html>
  );
}
```

**Nested Layout**:

```tsx
// app/dashboard/layout.tsx
export default function DashboardLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <aside>Sidebar</aside>
      <main>{children}</main>
    </div>
  );
}
```

### Dynamic Routes

```tsx
// app/blog/[slug]/page.tsx
export default async function BlogPost({
  params
}: {
  params: { slug: string };
}) {
  const post = await getPost(params.slug);

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

// Generate static params at build time
export async function generateStaticParams() {
  const posts = await getAllPosts();

  return posts.map(post => ({
    slug: post.slug
  }));
}
```

### Catch-All Routes

```tsx
// app/docs/[...slug]/page.tsx
export default function DocsPage({
  params
}: {
  params: { slug: string[] };
}) {
  // /docs/a/b/c → params.slug = ['a', 'b', 'c']
  return <div>Docs: {params.slug.join('/')}</div>;
}
```

## Server Actions

### Form Mutations

```tsx
// app/actions.ts
'use server';

import { revalidatePath } from 'next/cache';

export async function createUser(formData: FormData) {
  const name = formData.get('name') as string;
  const email = formData.get('email') as string;

  // Validate
  if (!name || !email) {
    return { error: 'Name and email required' };
  }

  // Create user
  await db.user.create({
    data: { name, email }
  });

  // Revalidate c
API DevelopmentSkill

Build REST APIs with proper error handling, status codes, request validation, response formatting, and rate limiting. Apply when creating API routes, handling errors, validating input, or designing API responses.

API Security HardeningSkill

Harden REST and GraphQL APIs against common attack vectors. Apply when building API endpoints, implementing authentication, handling file uploads, or exposing APIs to external consumers.

AWS Cloud InfrastructureSkill

Deploy Node.js applications on AWS using EC2, RDS, and managed services with security best practices. Apply when setting up AWS infrastructure, configuring databases, managing security, or optimizing costs.

Build Error ResolverSkill

Rapidly fix build failures, type errors, and lint issues with minimal diffs. Apply when builds fail, TypeScript reports errors, or CI/CD pipelines break. Focuses on getting the build green fast.

Cybersecurity Threat ModelingSkill

STRIDE-based threat modeling for application architecture. Apply when designing new systems, reviewing architecture, or assessing security posture of existing applications.

Docker ContainerizationSkill

Production-ready Docker patterns for multi-stage builds, security hardening, and orchestration. Apply when creating Dockerfiles, docker-compose configs, or deploying containerized applications.

Git WorkflowSkill

Enforces Conventional Commits, PR standards, merge conflict resolution, and branch management. Apply when committing code, opening PRs, resolving conflicts, managing branches, or handling Git operations.

Google Cloud Platform & APIsSkill

Deploy Node.js applications on Google Cloud with Cloud Run, Cloud Firestore, and Google APIs. Implement OAuth2 authentication and manage service accounts. Apply when building serverless applications, integrating Google services, or deploying to GCP.