# Nextjs Best Practices

> Next.js App Router principles. Server Components, data fetching, routing patterns.

- Skill: `yunaamelia/nextjs-best-practices` (Agent Skill)
- Install (CLI): `npx skillmds add yunaamelia/nextjs-best-practices`
- Raw SKILL.md: https://api.skillmd.com/api/skills/yunaamelia/nextjs-best-practices/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: yunaamelia (https://skillmd.com/u/yunaamelia)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/yunaamelia/nextjs-best-practices

---


# Next.js Best Practices

> Principles for Next.js App Router development.

---

## 1. Server vs Client Components

### Decision Tree

```
Does it need...?
│
├── useState, useEffect, event handlers
│   └── Client Component ('use client')
│
├── Direct data fetching, no interactivity
│   └── Server Component (default)
│
└── Both?
    └── Split: Server parent + Client child
```

### By Default

| Type       | Use                                   |
| ---------- | ------------------------------------- |
| **Server** | Data fetching, layout, static content |
| **Client** | Forms, buttons, interactive UI        |

---

## 2. Data Fetching Patterns

### Fetch Strategy

| Pattern        | Use                      |
| -------------- | ------------------------ |
| **Default**    | Static (cached at build) |
| **Revalidate** | ISR (time-based refresh) |
| **No-store**   | Dynamic (every request)  |

### Data Flow

| Source     | Pattern                      |
| ---------- | ---------------------------- |
| Database   | Server Component fetch       |
| API        | fetch with caching           |
| User input | Client state + server action |

---

## 3. Routing Principles

### File Conventions

| File            | Purpose        |
| --------------- | -------------- |
| `page.tsx`      | Route UI       |
| `layout.tsx`    | Shared layout  |
| `loading.tsx`   | Loading state  |
| `error.tsx`     | Error boundary |
| `not-found.tsx` | 404 page       |

### Route Organization

| Pattern                 | Use                       |
| ----------------------- | ------------------------- |
| Route groups `(name)`   | Organize without URL      |
| Parallel routes `@slot` | Multiple same-level pages |
| Intercepting `(.)`      | Modal overlays            |

---

## 4. API Routes

### Route Handlers

| Method    | Use         |
| --------- | ----------- |
| GET       | Read data   |
| POST      | Create data |
| PUT/PATCH | Update data |
| DELETE    | Remove data |

### Best Practices

- Validate input with Zod
- Return proper status codes
- Handle errors gracefully
- Use Edge runtime when possible

---

## 5. Performance Principles

### Image Optimization

- Use next/image component
- Set priority for above-fold
- Provide blur placeholder
- Use responsive sizes

### Bundle Optimization

- Dynamic imports for heavy components
- Route-based code splitting (automatic)
- Analyze with bundle analyzer

---

## 6. Metadata

### Static vs Dynamic

| Type             | Use               |
| ---------------- | ----------------- |
| Static export    | Fixed metadata    |
| generateMetadata | Dynamic per-route |

### Essential Tags

- title (50-60 chars)
- description (150-160 chars)
- Open Graph images
- Canonical URL

---

## 7. Caching Strategy

### Cache Layers

| Layer      | Control         |
| ---------- | --------------- |
| Request    | fetch options   |
| Data       | revalidate/tags |
| Full route | route config    |

### Revalidation

| Method     | Use                  |
| ---------- | -------------------- |
| Time-based | `revalidate: 60`     |
| On-demand  | `revalidatePath/Tag` |
| No cache   | `no-store`           |

---

## 8. Server Actions

### Use Cases

- Form submissions
- Data mutations
- Revalidation triggers

### Best Practices

- Mark with 'use server'
- Validate all inputs
- Return typed responses
- Handle errors

---

## 9. Anti-Patterns

| ❌ Don't                   | ✅ Do             |
| -------------------------- | ----------------- |
| 'use client' everywhere    | Server by default |
| Fetch in client components | Fetch in server   |
| Skip loading states        | Use loading.tsx   |
| Ignore error boundaries    | Use error.tsx     |
| Large client bundles       | Dynamic imports   |

---

## 10. Project Structure

```
app/
├── (marketing)/     # Route group
│   └── page.tsx
├── (dashboard)/
│   ├── layout.tsx   # Dashboard layout
│   └── page.tsx
├── api/
│   └── [resource]/
│       └── route.ts
└── components/
    └── ui/
```

---

> **Remember:** Server Components are the default for a reason. Start there, add client only when needed.

