Skip to content

[P1.7] Next.js 16 prep: bump eslint-config-next + @next/eslint-plugin-next to v16 #932

@frano-m

Description

@frano-m

Parent: #884 (Next.js 16 Upgrade Plan)

Scope

Bump eslint-config-next (and the underlying @next/eslint-plugin-next) to v16. Because eslint-config-next@16 declares peerDependencies: { eslint: ">=9.0.0" }, this issue also absorbs the ESLint 9 bump and the cascading plugin updates it requires.

Why this is a single PR, not split

The ESLint 9 bump cannot stand alone — multiple plugins in the current stack are incompatible with ESLint 9 (or stale enough to be a forward-compat risk) and have to be updated together. Splitting them creates an unworkable intermediate state.

Tasks

Core bump

  • eslint: ^8.57.1^9 (required by eslint-config-next@16).
  • eslint-config-next: ^15.5.13^16.
  • @next/eslint-plugin-next: ^15.5.13^16.
  • Drop the ESLINT_USE_FLAT_CONFIG=true env-var prefix from the lint script — ESLint 9 makes flat config the default. Restore script to eslint ..

Plugin cascade required by ESLint 9 (or for forward-compat with 10)

  • eslint-plugin-sonarjs: ^0.25.1^1 (minimum for ESLint 9 compat; current v0.25 uses context.getScope which ESLint 9 removed). v4 is latest but has more rule-set changes; v1 is the lowest-risk upgrade. Decide v1 vs v4 in the PR.

  • Replace eslint-plugin-typescript-sort-keys with eslint-plugin-perfectionist (see side-quest investigation: #884 comment). The current plugin is abandoned (last release Oct 2024, stuck at v3.3.0, peer: eslint: ^7 || ^8). Migration is mechanical:

    - "typescript-sort-keys/interface": ["error", "asc", { caseSensitive: false }],
    - "typescript-sort-keys/string-enum": ["error", "asc", { caseSensitive: false }],
    + "perfectionist/sort-interfaces": "error",
    + "perfectionist/sort-enums": "error",

    perfectionist defaults already match our settings (alphabetical, asc, ignoreCase: true).

  • Bump eslint-plugin-sort-destructure-keys v2 → v3. v3.0.0 (Feb 2026) extends the peer range from 5 - 9 to 5 - 10. Pure version bump — same rule, same options.

  • Replace eslint-plugin-eslint-comments with @eslint-community/eslint-plugin-eslint-comments. The original plugin's last release was Jun 2022 and the rule code uses old ESLint internals that risk breaking under ESLint 10. The community fork is actively maintained (latest: 4.7.1, last release Mar 2026), explicitly supports eslint: ^6 || ^7 || ^8 || ^9 || ^10, and is drop-in (rule names unchanged — still eslint-comments/require-description, etc.).

Other minor plugin freshness (group with bump)

  • @typescript-eslint/eslint-plugin: ^8.50.0^8.59 (minor; already supports 9+10).
  • eslint-plugin-jsdoc: ^61.5.0^63 (already supports 9+10).
  • eslint-plugin-react-hooks: ^5.2.0^7 (major bump; rule names and defaults may have changed — verify behavior).

Flat config adjustments

  • Update eslint.config.mjs for any v16 rule renames / new defaults from eslint-config-next@16.
  • Direct-import the perfectionist flat config (or use its named exports) instead of going through FlatCompat.
  • Direct-import the sonarjs flat config (current setup uses FlatCompat — may need adjustment for v1+).
  • Verify the @eslint-community/eslint-plugin-eslint-comments config path works through FlatCompat or direct import.

Verification

Forward-compat note

After this issue lands, the stack should be fully compatible with both ESLint 9 and 10. No further plugin work should be needed when we decide to bump to ESLint 10 down the road.

Depends on

Acceptance

  • ESLint 9 + flat config (no env-var prefix) runs cleanly.
  • All v16 Next-specific rules in effect.
  • All plugins on versions that officially support eslint: ^9 || ^10.
  • No silenced/disabled rules without a justification comment.
  • All plugin replacements behave equivalently to their predecessors (no semantic regressions in lint output).

Part of #884.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions