skills/nextjs-upgrade/SKILL.md
Assess and upgrade a Next.js project after resolving the target release from current official documentation. Includes tested automation and breaking-change guidance for the Next.js 15 to 16 migration. Use when the user says 'upgrade Next.js', 'migrate to Next.js 16', 'update my Next.js app', 'run the Next.js codemod', 'my Next.js version is outdated', or when a migration plan or baseline build comparison is needed.
npx skillsauth add b-open-io/prompts nextjs-upgradeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Resolve the requested target from the current Next.js release and upgrade guides, then compare it with the installed project. The bundled upgrade-path script is specifically tested for Next.js 15 to 16. Use its detection and measurement scripts for other targets, but derive migration steps from the matching official guide instead of presenting the v16 plan as current.
Scanning package.json, checking lock files, parsing build output — that's pure mechanics, not reasoning. These scripts handle it so you don't have to reconstruct the project state from scratch every time.
For a Next.js 15 to 16 migration, run the bundled scripts in this order. For any other target, run detection and measurement, then use the matching live upgrade guide and codemod documentation.
bash <skill-path>/scripts/detect-nextjs.sh /path/to/project
Returns JSON:
{
"nextjs_version": "15.1.0",
"react_version": "18.3.1",
"typescript_version": "5.7.2",
"has_typescript": true,
"package_manager": "bun",
"node_required": "",
"node_current": "20.11.0",
"router": {
"app_router": true,
"pages_router": false,
"app_dir": "app",
"pages_dir": ""
},
"linter": "eslint",
"formatter": "prettier",
"css_framework": "tailwind",
"tailwind_version": "3.4.0",
"next_config_file": "next.config.ts",
"uses_src_dir": false,
"turbopack": { "flag_in_scripts": true },
"react_compiler": { "installed": false, "version": "" },
"middleware": {
"has_middleware_file": true,
"middleware_path": "middleware.ts",
"has_proxy_file": false,
"proxy_path": ""
},
"scripts": {
"build": "next build",
"dev": "next dev --turbopack",
"lint": "next lint"
}
}
Pipe detect output or run standalone:
bash <skill-path>/scripts/detect-nextjs.sh /path/to/project \
| bash <skill-path>/scripts/check-upgrade-path.sh
Returns an ordered upgrade plan:
{
"from_version": "15.1.0",
"target_version": "16",
"package_manager": "bun",
"complexity": "medium",
"steps": [
{
"priority": 2,
"action": "bun add next@latest react@latest react-dom@latest && bun add -D @types/react@latest @types/react-dom@latest",
"reason": "Upgrade Next.js to v16, React to 19.2, and matching type definitions"
},
{
"priority": 3,
"action": "bunx @next/codemod@canary upgrade latest",
"reason": "Primary upgrade codemod: updates turbopack config, migrates middleware→proxy, removes unstable_ prefixes"
}
],
"codemods": [...],
"breaking_changes": ["--turbopack flag no longer needed", "middleware.ts must be renamed to proxy.ts"],
"notes": ["React Compiler provides automatic memoization — recommended"]
}
Execute steps in priority order. Each step has the exact command or action to perform.
Run before and after upgrading to quantify improvement:
bash <skill-path>/scripts/measure-build.sh /path/to/project
Returns:
{
"success": true,
"duration_ms": 18432,
"package_manager": "bun",
"build_command": "bun run build",
"warnings": [],
"errors": [],
"typescript_errors": [],
"bundle_sizes": {
"next_dir_size": "24M",
"first_load_js_summary": "First Load JS shared by all: 102 kB",
"route_table": ["○ /", "○ /about", "ƒ /api/posts"]
}
}
Run this before making changes to capture a baseline, then run again after to report the improvement.
| Field | What to do |
|---|---|
| linter: "eslint" | Plan Biome migration — next lint is removed in v16 |
| turbopack.flag_in_scripts: true | Remove --turbopack from package.json scripts |
| middleware.has_middleware_file: true | Rename to proxy.ts, update function export |
| router.app_router: true | Async Dynamic API codemod applies |
| node_current < 20.9 | Node.js upgrade required before anything else |
| complexity | Meaning |
|---|---|
| low | No breaking changes, minor version bump |
| medium | 1-2 breaking changes, run primary codemod |
| high | 3+ breaking changes or jumping multiple major versions |
Execute the steps array in order — priority 1 steps must complete before priority 2, etc.
| Field | Meaning |
|---|---|
| success: false | Build failed — check errors and typescript_errors |
| warnings | Non-fatal issues to address |
| bundle_sizes.first_load_js_summary | Key metric for before/after comparison |
| bundle_sizes.route_table | Per-route sizes for identifying large pages |
detect-nextjs.sh — understand current statemeasure-build.sh — capture baseline build time and bundle sizescheck-upgrade-path.sh — get the ordered step listmeasure-build.sh again — report the improvement to the userWhen asked to update a Next.js project, always run detect first. Never assume the router type, package manager, or linter — the project state determines the migration path.
# Before
bash <skill-path>/scripts/measure-build.sh . > /tmp/build-before.json
# ... make changes ...
# After
bash <skill-path>/scripts/measure-build.sh . > /tmp/build-after.json
# Report delta
node -e "
const before = require('/tmp/build-before.json');
const after = require('/tmp/build-after.json');
const pct = Math.round((1 - after.duration_ms / before.duration_ms) * 100);
console.log('Build time: ' + before.duration_ms + 'ms → ' + after.duration_ms + 'ms (' + pct + '% faster)');
"
{
"dev": "next dev --turbopack", → "next dev"
"build": "next build",
"lint": "next lint" → "biome check ."
}
experimental.turbopack → top-level turbopackreactCompiler: true (stable in v16)cacheComponents: true (replaces experimental.ppr)images.domains → images.remotePatterns// Before
const cookieStore = cookies()
const { slug } = params
// After
const cookieStore = await cookies()
const { slug } = await props.params
// middleware.ts → proxy.ts
export function proxy(request: Request) { // was: middleware
return NextResponse.next()
}
tools
This skill should be used when a Claude Code session needs to keep working after Anthropic usage runs out, or when the user asks to run the Claude Code harness on GPT-5.6 Sol. Trigger phrases include "my Anthropic usage ran out", "I'm out of Claude usage", "usage limit reached, what now", "keep working on another model", "run Claude Code on GPT-5.6 Sol", "use GPT-5.6 Sol as the model", "set up claudex", "claudex isn't working", "route the harness through CLIProxyAPI", or "bill against my ChatGPT/Codex subscription". It stands up a local proxy so the Claude Code CLI runs on OpenAI's Codex backend as an escape hatch, and diagnoses that setup when it drifts. macOS + Homebrew.
testing
This skill should be used when the user asks to "open Visual Wayfinder", "answer a Wayfinder ticket visually", "turn this decision into a configurator", "show Wayfinder choices as a dashboard", "prototype the Wayfinder questionnaire", or wants interactive choice cards, tradeoff controls, rankings, ranges, toggles, and consequence previews for one active Wayfinder decision. It wraps the Wayfinder skill and JSON Render; it never replaces the tracker or resolves more than the active decision.
development
This skill should be used when the user asks to "make a visual proposal", "write this up so I can share it", "present these options visually", "diagram the trade-offs", "turn this plan into something reviewable", or requests a shareable design pitch, architecture proposal, RFC, options comparison, or visual roadmap for work that has not been built. It produces one self-contained, theme-aware HTML page led by grounded diagrams. Use visual-review instead for completed code changes; do not use this skill for internal task tracking.
tools
This skill should be used when the user asks to "add plugin settings", "make a plugin configurable", "store per-project plugin configuration", "use settings.local.json", "create a plugin state file", "expose skill settings in Agent Master", or "add a skill interface". Distinguishes official Claude Code settings from project-owned configuration and documents bOpen Agent Master skill interface discovery.