Skip to content

Upgrade website to Next.js 16 - #157

Merged
abernier merged 1 commit into
mainfrom
next-16
Aug 9, 2026
Merged

Upgrade website to Next.js 16#157
abernier merged 1 commit into
mainfrom
next-16

Conversation

@abernier

@abernier abernier commented Aug 9, 2026

Copy link
Copy Markdown
Member

Follows the official v16 upgrade guide. apps/website is the only Next app in the repo — the demos are Vite.

next 15.5.22 → 16.3.0, eslint-config-next to match, eslint ^8 → ^9. React stays at 19.2.8 (already what 16 wants).

What actually changed

Turbopack is the default for next dev and next build. There is no webpack config to migrate and no experimental.turbopack block, so next.config.mjs is untouched.

next lint is removed. pnpm lint now runs the ESLint CLI directly, and .eslintrc.jsoneslint.config.mjs: @next/eslint-plugin-next only ships flat config as of 16, which is what pushes eslint to 9.

tsconfig.json and apps/website/{AGENTS,CLAUDE}.md are written by next dev itself. Committed so the tree stays clean rather than dirtying on every dev start. (agentRules: false in next.config.mjs turns the two md files off if you'd rather not have them — the root AGENTS.md is untouched either way.) The one substantive tsconfig change is .next/dev/types/**/*.ts in include: dev and build no longer share an output directory, which is also what lets them run at the same time now.

Breaking changes that turned out to be no-ops here

  • Async request APIsparams was already awaited in examples/[examplename]; no cookies/headers/draftMode, no searchParams on the server.
  • No middleware (→ proxy), no serverRuntimeConfig/publicRuntimeConfig, no AMP, no parallel routes, no revalidateTag/unstable_* cache APIs, no sitemap or OG image generators.
  • next/image defaults (qualities, imageSizes, minimumCacheTTL, local IPs, redirects) don't apply — output: "export" with images.unoptimized.
  • Scroll behaviour — nothing sets scroll-behavior: smooth, so the dropped override changes nothing.

One thing left as a warning

react-hooks/set-state-in-effect is new in eslint-plugin-react-hooks 7 and fires 6 times: Nav's sidebar/search sync (5) and use-mobile (1). Both seed state from the DOM or the URL on mount. Untangling those is a refactor of its own, not part of a framework bump, so the rule is warn in eslint.config.mjs with a comment saying why. Worth its own PR.

Verified locally

  • next build — 162 routes prerendered, clean, with and without BASE_PATH; out/index.html still carries the build-time --md-sys-color-* payload.
  • tsc --noEmit clean; pnpm lint 0 errors.
  • next dev + / and /examples/aquarium both 200.
  • pnpm lint:versions (syncpack) clean.

CI on a PR runs lint:metadata, lint:versions and the Playwright snapshots — none of which touch the Next build — so the build above is the local check that matters.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RWwhRu6Twf7pHHnyFm87xa

Turbopack is now the default bundler for both `next dev` and `next build`;
the app has no webpack config, so nothing to opt out of. `params` was already
awaited everywhere, and there is no middleware, no runtime config and no AMP,
so the rest of the v16 breaking changes are no-ops here. `output: "export"`
still produces the same 162 prerendered routes, `BASE_PATH` included.

`next lint` is gone in 16: `pnpm lint` runs the ESLint CLI directly, and
`.eslintrc.json` becomes `eslint.config.mjs` — `@next/eslint-plugin-next`
only ships flat config now, which needs ESLint 9.

`react-hooks/set-state-in-effect` is new in eslint-plugin-react-hooks 7 and
fires on `Nav`'s sidebar/search sync and `use-mobile`, both of which seed
state from the DOM or the URL on mount. Untangling them is a refactor of its
own, so it is a warning here rather than a blocker.

`tsconfig.json` and `apps/website/{AGENTS,CLAUDE}.md` are written by
`next dev` itself — committed so the tree stays clean. `.next/dev/types` is
where dev-mode route types live now that dev and build no longer share an
output directory, which is also what lets them run concurrently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWwhRu6Twf7pHHnyFm87xa
@abernier
abernier merged commit 2487116 into main Aug 9, 2026
2 checks passed
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