Skip to content

deps(dashboard): Next 16, and the four things it broke - #96

Merged
blitzcrieg1 merged 1 commit into
masterfrom
deps/next-16
Aug 23, 2026
Merged

deps(dashboard): Next 16, and the four things it broke#96
blitzcrieg1 merged 1 commit into
masterfrom
deps/next-16

Conversation

@blitzcrieg1

Copy link
Copy Markdown
Owner

Next 16 was declined three times today because it kept arriving attached to an unrelated advisory: sharp in #85, postcss in #91, and as a dependency of TypeScript 7 in #66. Done deliberately here instead.

It closes the four remaining postcss alerts, which were the last ones in the queue.

Four things broke, each needing a decision

1. next lint is gone

It does not warn. It parses the word lint as a project directory:

Invalid project directory provided, no such directory: .../apps/dashboard/lint

package.json now calls eslint . directly, and .eslintrc.json becomes eslint.config.mjseslint-config-next@16 requires eslint 9 and exports a flat config array rather than something extends can consume.

2. Turbopack resolves CSS differently

Turbopack is the default build engine in 16. Both @import "tw-animate-css" and @import "shadcn/tailwind.css" failed with Module not found. Both packages expose CSS through an exportsstyle condition that webpack honoured and Turbopack does not, and their exports maps do not permit the deep path either.

Imports are now relative into node_modules. Ugly, and the file says why. next build --webpack exists and was not taken: opting out of the default engine to keep a prettier import is the wrong trade when the fallback will eventually go away.

3. My own override from earlier today was wrong, and this found it

The brace-expansion: ^5 override I added in #94 broke eslint:

TypeError: expand is not a function
    at Minimatch.braceExpand

eslint 9 pulls minimatch@3, which needs the v1 callable export. next lint had masked this by using Next's vendored copy, so it passed CI at the time and only surfaced once lint went through the eslint CLI.

Override removed. npm now resolves 1.1.18 and 5.0.9 side by side, per consumer, which satisfies the advisory without forcing anything. That is the better fix and I should have scoped it that way originally.

4. A new rule lands on 12 existing effects

react-hooks/set-state-in-effect, new in eslint-config-next@16. Downgraded to warn with the reasoning in the config and tracked in #95.

The shape it flags most often is the hydration guard next-themes documents (useEffect(() => setMounted(true), [])), which exists to avoid a server/client mismatch and has no direct replacement. Twelve behaviour-adjacent refactors inside a framework migration would make this unreviewable.

Verified past the build

A build passing is not a working UI, so I served the dev server against a live orchestrator:

  • CSS resolves: 3 stylesheets, 703 rules, dark theme applied (rgb(9,9,11) ground)
  • Live feed renders: 128 events, filters, MITRE columns, source list
  • Zero console errors

Plus: tsc --noEmit clean, eslint . 0 errors (12 warnings, all #95), 99 tests, static export produces both routes.

🤖 Generated with Claude Code

Next 16 has been declined three times today because it kept arriving attached
to an unrelated advisory: sharp in #85, postcss in #91, and as a dependency of
TypeScript 7 in #66. Done deliberately here instead. It closes the four
remaining postcss alerts, which were the last ones in the queue.

Four things broke and each needed a decision rather than a version number.

`next lint` is gone. It does not warn, it parses the word "lint" as a project
directory and exits 1 with "Invalid project directory provided", which reads
like a broken path rather than a removed command. package.json now calls eslint
directly and .eslintrc.json becomes eslint.config.mjs, because
eslint-config-next 16 needs eslint 9 and exports a flat config array rather
than something `extends` can take.

Turbopack is the default build engine in 16 and resolves CSS differently.
`@import "tw-animate-css"` and `@import "shadcn/tailwind.css"` both failed with
Module not found. Both packages expose their CSS through an exports "style"
condition that webpack honoured and Turbopack does not, and their exports maps
do not permit the deep path either, so the imports are now relative into
node_modules. Ugly, and the comment says why. `next build --webpack` exists as
a fallback and was not taken: opting out of the default engine to keep a
prettier import is the wrong trade.

The `brace-expansion: ^5` override I added earlier today was wrong and this
found it. eslint 9 pulls minimatch 3, which needs the v1 callable export, so
`eslint .` died with "expand is not a function". `next lint` had masked it by
using Next's vendored copy. The override is removed and npm now resolves 1.1.18
and 5.0.9 side by side, per consumer, which satisfies the advisory without
forcing anything.

eslint-config-next 16 adds `react-hooks/set-state-in-effect`, which lands on 12
existing effects. It is downgraded to a warning rather than disabled, with the
reasoning in the config and #95 to work through them. The
pattern it flags most often is the hydration guard next-themes documents, and
refactoring twelve effects inside a framework migration would make the whole
thing unreviewable.

Verified past the build, because a build passing is not a working UI. Served
the dev server against a live orchestrator: CSS resolves (3 stylesheets, 703
rules, dark theme applied), the live feed renders 128 events with filters and
MITRE columns, no console errors. tsc clean, lint 0 errors, 99 tests, static
export produces both routes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@blitzcrieg1
blitzcrieg1 merged commit 6d193c4 into master Aug 23, 2026
9 checks passed
@blitzcrieg1
blitzcrieg1 deleted the deps/next-16 branch August 23, 2026 08:50
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant