P PasteCode
Playbook

Prompt-to-PR: Migrate Next.js 14 to 16

Step-by-step SOP for migrating a Next.js 14 App Router project to Next.js 16 — Turbopack, React 19, async APIs, and caching changes covered.

CursorClaude CodeCodexWindsurf Next.jsTypeScript
.md .json Difficulty: Hard Updated Jun 8, 2026

Next.js 16 ships React 19, async params and searchParams, overhauled fetch caching, and Turbopack as the default dev bundler. This playbook keeps the agent focused on breaking changes and prevents it from rewriting working code.

1. Requirement

Upgrade next from 14.x to 16.x (and react/react-dom to 19.x) with zero functionality regressions. Address every breaking change surfaced by the official codemod and any residual issues not caught by it.

2. First Prompt

First Prompt
Migrate this project from Next.js 14 to Next.js 16. Follow these steps exactly.
Step 1 — run the official codemod:
npx @next/codemod@latest upgrade latest --yes
Step 2 — manual fixes the codemod does not cover:
a. `params` and `searchParams` in page.tsx/layout.tsx files are now Promises.
Await them: `const { id } = await params;`
Do NOT destructure params in the function signature.
b. `cookies()`, `headers()`, `draftMode()` are now async.
Add `await` before every call.
c. `fetch()` is no longer cached by default in Route Handlers.
Where caching is intentional, add `{ next: { revalidate: N } }`.
d. Remove any `export const dynamic = 'force-dynamic'` that is now the default.
e. Replace `<Image>` with the new `onLoad` prop signature if present.
Step 3 — update package.json:
"next": "^16.0.0"
"react": "^19.0.0"
"react-dom": "^19.0.0"
"@types/react": "^19.0.0"
"@types/react-dom": "^19.0.0"
Do not change any business logic, UI, or database code.
List every file you changed and why.

3. Expected File Changes

package.json (next, react, react-dom, @types/react*)
src/app/**/page.tsx (await params / searchParams)
src/app/**/layout.tsx (await params where used)
src/app/api/**/route.ts (await cookies/headers; fetch cache opts)
src/middleware.ts (if it uses deprecated config keys)
next.config.ts (remove deprecated options)

4. Review Checklist

  • package.json pins next to ^16.0.0 and React to ^19.0.0.
  • Every page/layout that destructures params now awaits it first.
  • No synchronous cookies() or headers() calls remain in Server Components.
  • fetch calls that previously relied on implicit caching have an explicit revalidate or no-store option.
  • next.config.ts has no deprecated experimental.appDir or swcMinify keys.
  • TypeScript compiles with bun tsc --noEmit — zero errors.
  • The agent did not rewrite any UI components or business logic.

5. Test Commands

Terminal window
# Install updated deps
bun install
# Type-check
bun tsc --noEmit
# Dev build (Turbopack default in Next.js 16)
bun dev
# Production build — catches async-params errors at compile time
bun run build
# Run existing test suite
bun test

6. Common Failures

  • params.id used before await — TypeScript error: Property 'id' does not exist on type 'Promise<...>'. The agent sometimes awaits params in one file and not another.
  • cookies() not awaited — runtime error: cookies() was called outside of a Server Component. Add await.
  • Turbopack incompatible webpack pluginnext dev errors on a custom webpack() config. Turbopack ignores webpack plugins; migrate or conditionally gate them.
  • @types/react version conflict — peer-dep mismatch between old component libraries and React 19 types. Pin @types/react to 19 and override if needed.
  • useFormState removed — replaced by useActionState from react. The codemod usually catches this but confirm.

7. Fix Prompt

Fix Prompt
TypeScript reports: "Property 'slug' does not exist on type
'Promise<{ slug: string }>'" in src/app/blog/[slug]/page.tsx.
The page function signature must be:
export default async function Page({ params }: { params: Promise<{ slug: string }> })
Then at the top of the function body:
const { slug } = await params;
Apply the same fix to every other page or layout that destructures params
without awaiting. List every file changed.

8. PR Description

PR description
## Chore: Migrate Next.js 14 → 16 + React 19
**Breaking changes addressed**:
- `params` / `searchParams` are now `Promise`s — awaited in all pages/layouts
- `cookies()` / `headers()` are now async — awaited in all Server Components
- Fetch caching defaults changed — explicit `revalidate` added where needed
- Removed deprecated `next.config.ts` keys (`swcMinify`, `experimental.appDir`)
**Tooling**: dev server now uses Turbopack by default (`next dev --turbopack`).
Run `bun run build` to confirm zero type errors before merging.