Skip to content

build(deps): upgrade to Next.js 16 - #12

Merged
EliRobinson merged 1 commit into
mainfrom
worktree-next16-upgrade
Sep 1, 2026
Merged

EliRobinson merged 1 commit into
mainfrom
worktree-next16-upgrade

Conversation

@EliRobinson

Copy link
Copy Markdown
Owner

Upgrades the template from Next.js 15.5.20 to 16.3.4.

Changes

Change Why
next 15.5.20 → 16.3.4, react/react-dom → 19.2.8, @types/react, @types/react-dom, eslint-config-next → 16.3.4 The upgrade itself. Next 16's App Router requires React 19.2.
Dropped --turbopack from the dev script Turbopack is the default for both dev and build in 16. There is no webpack config here, so nothing needs the --webpack escape hatch.
Rewrote eslint.config.mjs to import eslint-config-next/core-web-vitals and eslint-config-next/typescript directly The only real break. @next/eslint-plugin-next now ships flat config only, and the old FlatCompat.extends('next/core-web-vitals', 'next/typescript') call throws TypeError: Converting circular structure to JSON against it.
Removed @eslint/eslintrc FlatCompat was its last consumer.
tsconfig.json: jsxreact-jsx, .next/dev/types/**/*.ts added to include Written by next build itself. dev and build use separate output directories in 16.
AGENTS.md gained a nextjs-agent-rules block Generated and re-added by next dev. Committing it keeps the tree clean; deleting it just re-creates an uncommitted change.
"Next.js 15" → "Next.js 16" in README.md, AGENTS.md, src/app/page.tsx, e2e/example.spec.ts Copy.

Breaking changes that did not apply

Checked each item in the version 16 upgrade guide against the tree. None of these are present: middleware (→ proxy), images.domains, AMP, serverRuntimeConfig/publicRuntimeConfig, synchronous params/searchParams/cookies()/headers()/draftMode(), parallel routes needing default.js, next/legacy/image, unstable_ cache imports, single-argument revalidateTag, experimental_ppr, experimental.dynamicIO/useCache, removed devIndicators options. next lint was never used — the lint script already called eslint directly. next.config.ts already used the stable top-level turbopack key.

Node is already on 24 via .nvmrc, above the new 20.9 floor.

Verification

All run in the worktree against 16.3.4:

  • pnpm type-check — clean
  • pnpm lint — clean
  • pnpm format:check — clean
  • pnpm test — 2/2
  • pnpm build — succeeds, both routes prerendered static
  • pnpm test:e2e --project=chromium — 4/4, including the @elirobinson/ai-patterns contract checks (touch targets, visible focus, WCAG AA contrast) in light and dark
  • pnpm dev — Next 16.3.4 boots, home page renders, no browser console errors and no dev-indicator errors

After the ESLint rewrite I confirmed the Next rules still fire by linting a throwaway file with a bare <img>; @next/next/no-img-element caught it. The same 20 files are linted before and after.

Visual diff

The only rendered change is one card label: "Next.js 15" → "Next.js 16". Layout, spacing, type, and color are untouched, and the design system contract E2E specs pass unchanged. Skipping a before/after screenshot pair for a one-word text delta.

🤖 Generated with Claude Code

Next.js 15.5.20 -> 16.3.4, with React 19.2.8 and the matching @types and
eslint-config-next majors.

Turbopack is the default bundler in 16, so `next dev --turbopack` loses the
flag. The build already ran through Turbopack and there is no webpack config
here, so nothing needs `--webpack`.

The one real break was ESLint. @next/eslint-plugin-next now ships flat config
only, and the old `FlatCompat.extends('next/core-web-vitals', 'next/typescript')`
call throws a circular-structure error against it. The two configs are imported
directly as flat arrays instead, which drops the last consumer of
@eslint/eslintrc. Verified the Next rules still fire (no-img-element) and that
the same 20 files are linted as before.

tsconfig changes are the ones `next build` writes itself: `jsx` must be
`react-jsx` in 16, and `.next/dev/types` joins `include` now that dev and build
write to separate output directories.

The nextjs-agent-rules block in AGENTS.md is generated and re-added by
`next dev`; committing it keeps the tree clean.

None of the other version 16 breaking changes apply — no middleware, no
images.domains, no AMP, no serverRuntimeConfig/publicRuntimeConfig, no sync
params or searchParams, no parallel routes, and `next lint` was never used.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EliRobinson
EliRobinson merged commit aaafb8f into main Sep 1, 2026
3 checks passed
@EliRobinson
EliRobinson deleted the worktree-next16-upgrade branch September 1, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant