🧪 Skills

Nextjs

Next.js 15/16 App Router patterns — async APIs, caching semantics, Turbopack, Server Components, Route Handlers, and migration from v14

v1.1.0
❤️ 3
⬇️ 1.8k
👁 2
Share

Description


name: nextjs description: Next.js 15/16 App Router patterns — async APIs, caching semantics, Turbopack, Server Components, Route Handlers, and migration from v14 version: 1.0.0 tags:

  • nextjs
  • react
  • web-development
  • frontend
  • midos

Next.js App Router Production Patterns

Description

Production Next.js patterns for the App Router era (v15/v16). Covers the critical breaking changes from v14 (async request APIs, uncached-by-default semantics), Turbopack performance improvements, React 19 integration, Route Handler caching strategies, and Server/Client Component boundaries. Validated against official releases with 0.96 confidence.

Usage

Install this skill to get production-ready Next.js patterns including:

  • Async cookies(), headers(), params, searchParams migration from v14
  • Explicit cache configuration for Route Handlers (uncached by default in v15+)
  • Turbopack setup (76% faster startup, 96% faster HMR)
  • Server Component patterns for data fetching
  • Complete migration checklist from v14 to v15/v16

When working on Next.js projects, this skill provides context for:

  • Avoiding the most common hydration and async API errors
  • Configuring staleTime for the client router cache
  • Using instrumentation.js for APM and observability setup
  • Choosing when to use force-static vs force-dynamic vs revalidate

Key Patterns

Breaking Change: Async Request APIs

CRITICAL: cookies(), headers(), params, and searchParams are now async.

// WRONG (Next.js 14 style)
export function AdminPanel() {
  const cookieStore = cookies(); // Synchronous -- no longer works
  const token = cookieStore.get('token');
  return <div>Token: {token?.value}</div>;
}

// CORRECT (Next.js 15+ style)
export async function AdminPanel() {
  const cookieStore = await cookies(); // Must await
  const token = cookieStore.get('token');
  return <div>Token: {token?.value}</div>;
}

Automated migration (handles ~95% of cases):

npx @next/codemod@canary next-async-request-api

All affected APIs: cookies(), headers(), draftMode(), params, searchParams -- all must be awaited.

Breaking Change: Caching Semantics

GET Route Handlers and fetch() are uncached by default in v15+.

// Next.js 14: cached automatically (dangerous assumption)
export async function GET() {
  const data = await fetch('https://api.example.com/data');
  return Response.json(data);
}

// Next.js 15+: explicitly opt into caching
export const revalidate = 60; // Cache for 60 seconds
export async function GET() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 60 }
  });
  return Response.json(await data.json());
}

// Or: cache forever
export const dynamic = 'force-static';

// Or: never cache (user-specific data)
export const dynamic = 'force-dynamic';

Restore v14 client router cache behavior if needed:

// next.config.js
module.exports = {
  experimental: {
    staleTimes: { dynamic: 30, static: 180 },
  },
};

Server Component with Async APIs

// app/dashboard/page.tsx
import { cookies, headers } from 'next/headers';

export default async function Dashboard() {
  const cookieStore = await cookies();
  const headersList = await headers();
  const token = cookieStore.get('session');
  const userAgent = headersList.get('user-agent');
  return <div><h1>Dashboard</h1><p>Session: {token?.value}</p></div>;
}

Dynamic Route with Params

// app/blog/[slug]/page.tsx
interface PageProps {
  params: Promise<{ slug: string }>;
}

export default async function BlogPost({ params }: PageProps) {
  const { slug } = await params;  // Must await in v15+
  const post = await fetch(`https://api.com/posts/${slug}`);
  return <article>{/* ... */}</article>;
}

Turbopack (Development Performance)

next dev --turbo   # Enable Turbopack (default in dev for v15+)
next build         # Still uses Webpack for production

Performance gains: 76% faster local server startup, 96% faster HMR, 45% faster initial route compilation.

instrumentation.js (Observability)

// instrumentation.js (project root)
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    const { setupMonitoring } = await import('./monitoring');
    setupMonitoring(); // DataDog, Sentry, New Relic, etc.
  }
}

Common Pitfalls

Pitfall 1: Forgetting await

const cookieStore = cookies();          // Wrong -- Object is possibly 'Promise'
const cookieStore = await cookies();    // Correct

Pitfall 2: Caching user-specific data

// WRONG: caches data that differs per user
export const revalidate = 3600;
export async function GET(request: Request) {
  const userId = request.headers.get('x-user-id');
  const data = await getUserData(userId); // Different per user!
  return Response.json(data);
}

// CORRECT
export const dynamic = 'force-dynamic';

Pitfall 3: App Router requires React 19

npm install next@latest react@latest react-dom@latest

Migration Checklist: v14 to v15/v16

  • Run: npx @next/codemod@canary upgrade latest
  • Run: npx @next/codemod@canary next-async-request-api
  • Audit GET Route Handlers: add explicit revalidate or dynamic
  • Upgrade to Node.js 18.18+
  • Test client router cache behavior (add staleTimes config if needed)
  • Test with Turbopack: next dev --turbo
  • Run production build: next build && next start
  • Verify all dynamic routes resolve params correctly

Tools & References


Published by MidOS — MCP Community Library

Reviews (0)

Sign in to write a review.

No reviews yet. Be the first to review!

Comments (0)

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts!

Compatible Platforms

Pricing

Free

Related Configs