mcpbeat

Nextjs App Router Patterns

wshobson/nextjs-app-router-patterns

Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, implementing SSR/SSG, or optimizing React Server Components.

3k tokens
context cost
the whole folder, loaded on every use
2
files
instructions only
0
copies elsewhere
how many repositories repackaged it
38452
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/wshobson/agents --skill nextjs-app-router-patterns

The instruction itself

10 sections, as written by the author

Next.js App Router Patterns

Comprehensive patterns for Next.js 14+ App Router architecture, Server Components, and modern full-stack React development.

When to Use This Skill

  • Building new Next.js applications with App Router
  • Migrating from Pages Router to App Router
  • Implementing Server Components and streaming
  • Setting up parallel and intercepting routes
  • Optimizing data fetching and caching
  • Building full-stack features with Server Actions

Core Concepts

1. Rendering Modes

| Mode | Where | When to Use |

| --------------------- | ------------ | ----------------------------------------- |

| Server Components | Server only | Data fetching, heavy computation, secrets |

| Client Components | Browser | Interactivity, hooks, browser APIs |

| Static | Build time | Content that rarely changes |

| Dynamic | Request time | Personalized or real-time data |

| Streaming | Progressive | Large pages, slow data sources |

2. File Conventions

app/
├── layout.tsx       # Shared UI wrapper
├── page.tsx         # Route UI
├── loading.tsx      # Loading UI (Suspense)
├── error.tsx        # Error boundary
├── not-found.tsx    # 404 UI
├── route.ts         # API endpoint
├── template.tsx     # Re-mounted layout
├── default.tsx      # Parallel route fallback
└── opengraph-image.tsx  # OG image generation

Quick Start

// app/layout.tsx
import { Inter } from 'next/font/google'
import { Providers } from './providers'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: { default: 'My App', template: '%s | My App' },
  description: 'Built with Next.js App Router',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={inter.className}>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

// app/page.tsx - Server Component by default
async function getProducts() {
  const res = await fetch('https://api.example.com/products', {
    next: { revalidate: 3600 }, // ISR: revalidate every hour
  })
  return res.json()
}

export default async function HomePage() {
  const products = await getProducts()

  return (
    <main>
      <h1>Products</h1>
      <ProductGrid products={products} />
    </main>
  )
}

Detailed patterns and worked examples

Detailed pattern documentation lives in references/details.md. Read that file when the navigation tier above is insufficient.

Best Practices

Do's

  • Start with Server Components - Add 'use client' only when needed
  • Colocate data fetching - Fetch data where it's used
  • Use Suspense boundaries - Enable streaming for slow data
  • Leverage parallel routes - Independent loading states
  • Use Server Actions - For mutations with progressive enhancement

Don'ts

  • Don't pass serializable data - Server → Client boundary limitations
  • Don't use hooks in Server Components - No useState, useEffect
  • Don't fetch in Client Components - Use Server Components or React Query
  • Don't over-nest layouts - Each layout adds to the component tree
  • Don't ignore loading states - Always provide loading.tsx or Suspense

How to use it

Copy the folder

Take wshobson/nextjs-app-router-patterns from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.