Skip to content

Commit ea2d14f

Browse files
committed
feat: add ESLint 9 flat config support for Next.js 15 with updated dependencies and examples
1 parent dcb2015 commit ea2d14f

File tree

8 files changed

+1124
-632
lines changed

8 files changed

+1124
-632
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [3.0.0] - 2025-05-09
6+
7+
### Added
8+
9+
- Support for Next.js 15 with ESLint 9 flat configuration system
10+
- New flat config export via `@hypetech/eslint-config/flat`
11+
- Example configurations for both Next.js 14 and Next.js 15
12+
- Comprehensive documentation for both configuration types
13+
14+
### Changed
15+
16+
- Updated `ecmaVersion` from 2020 to 2022 in the traditional configuration
17+
- Updated peer dependency for ESLint to require version 9.x or higher
18+
- Added new dependencies: `@eslint/eslintrc` and `@eslint/js` for flat config support
19+
520
## [2.1.0] - 2023-07-24
621

722
### Changed

README.md

Lines changed: 156 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@
22

33
The official HypeTech eslint configuration, part of the Frontend Coding Standards.
44

5+
> **New in v3.0.0**: Support for Next.js 15 with ESLint 9 flat configuration system.
6+
7+
## Configuration Types
8+
9+
This package provides two types of ESLint configurations:
10+
11+
1. **Traditional Configuration** (for ESLint 8.x and Next.js 14 or earlier)
12+
2. **Flat Configuration** (for ESLint 9.x and Next.js 15 or later)
13+
514
## Installation
615

716
The configuration can be installed via your preferred package manager.
817

18+
### For All Configurations
19+
920
With PNPM (preferred):
1021

1122
```bash
@@ -21,24 +32,46 @@ yarn add -D @hypetech/eslint-config
2132
With NPM:
2233

2334
```bash
24-
npm install --dev @hypetech/prettier-config
35+
npm install --save-dev @hypetech/eslint-config
2536
```
2637

27-
To inform eslint of this configuration, you have to add the `eslint` property to your `package.json` file:
38+
### Additional Dependencies for Next.js 15 (Flat Config)
39+
40+
If you're using Next.js 15 with ESLint 9 flat configuration, you'll need these additional dependencies:
41+
42+
```bash
43+
pnpm add -D eslint@^9.0.0 @eslint/eslintrc@^3.0.0 @eslint/js@^9.0.0
44+
# or
45+
yarn add -D eslint@^9.0.0 @eslint/eslintrc@^3.0.0 @eslint/js@^9.0.0
46+
# or
47+
npm install --save-dev eslint@^9.0.0 @eslint/eslintrc@^3.0.0 @eslint/js@^9.0.0
48+
```
49+
50+
## Usage
51+
52+
### Traditional Configuration (ESLint 8.x, Next.js 14 or earlier)
53+
54+
To use the traditional configuration, you have several options:
55+
56+
#### Option 1: Via package.json
57+
58+
Add the `eslint` property to your `package.json` file:
2859

2960
```json
3061
"eslintConfig": {
3162
"extends": "@hypetech/eslint-config"
3263
}
3364
```
3465

35-
Instead of manually editing your `package.json`, you can also utilize the `npm pkg` subcommand:
66+
You can use the `npm pkg` subcommand to add this automatically:
3667

3768
```bash
3869
npm pkg set eslintConfig.extends=@hypetech/eslint-config
3970
```
4071

41-
Alternatively, you can also create a `.eslintrc.cjs` file in your project root and add the following content:
72+
#### Option 2: Via .eslintrc.js or .eslintrc.cjs
73+
74+
Create a `.eslintrc.js` file (or `.eslintrc.cjs` if your package uses `"type": "module"`) in your project root:
4275

4376
```js
4477
module.exports = {
@@ -47,21 +80,136 @@ module.exports = {
4780
}
4881
```
4982

50-
> Notice: You should add configuration to your `package.json` if you are creating a library, and use a `.eslintrc.cjs` file if you are creating an application. And you should avoid both ways in the same project.
51-
52-
## Extending
83+
#### Option 3: Extending the configuration
5384

54-
To extend the configuration, you will have to create a `.eslintrc.js` file (or `.eslintrc.cjs` if your package is a `"type": "module"`) and import the HypeTech configuration using `require`:
85+
To customize the configuration, create a `.eslintrc.js` or `.eslintrc.cjs` file:
5586

5687
```js
5788
module.exports = {
5889
...require('@hypetech/eslint-config'),
5990
rules: {
91+
// Your custom rules here
6092
'no-console': 'warn',
6193
},
6294
}
6395
```
6496

97+
> **Best Practice**: Use `package.json` for libraries and `.eslintrc.js`/`.eslintrc.cjs` for applications. Avoid using both methods in the same project.
98+
99+
### Flat Configuration (ESLint 9.x, Next.js 15 or later)
100+
101+
Next.js 15 uses ESLint 9 with the new flat configuration system. Here's how to use our flat config:
102+
103+
#### Option 1: Basic Usage
104+
105+
Create an `eslint.config.mjs` file in your project root:
106+
107+
```js
108+
// eslint.config.mjs
109+
import hypeConfig from '@hypetech/eslint-config/flat';
110+
111+
export default hypeConfig;
112+
```
113+
114+
#### Option 2: Extending the Configuration
115+
116+
To customize the configuration, you can extend it in your `eslint.config.mjs` file:
117+
118+
```js
119+
// eslint.config.mjs
120+
import { dirname } from "path";
121+
import { fileURLToPath } from "url";
122+
import { FlatCompat } from "@eslint/eslintrc";
123+
import js from "@eslint/js";
124+
import hypeConfig from '@hypetech/eslint-config/flat';
125+
126+
const __filename = fileURLToPath(import.meta.url);
127+
const __dirname = dirname(__filename);
128+
129+
const compat = new FlatCompat({
130+
baseDirectory: __dirname,
131+
recommendedConfig: js.configs.recommended,
132+
});
133+
134+
const eslintConfig = [
135+
...hypeConfig,
136+
// Your custom configurations here
137+
{
138+
files: ["**/*.ts", "**/*.tsx"],
139+
rules: {
140+
// Your custom rules here
141+
"no-console": "warn",
142+
},
143+
},
144+
];
145+
146+
export default eslintConfig;
147+
```
148+
149+
#### Option 3: Adding Additional Plugins
150+
151+
To add additional plugins to the configuration:
152+
153+
```js
154+
// eslint.config.mjs
155+
import { dirname } from "path";
156+
import { fileURLToPath } from "url";
157+
import { FlatCompat } from "@eslint/eslintrc";
158+
import js from "@eslint/js";
159+
import hypeConfig from '@hypetech/eslint-config/flat';
160+
161+
const __filename = fileURLToPath(import.meta.url);
162+
const __dirname = dirname(__filename);
163+
164+
const compat = new FlatCompat({
165+
baseDirectory: __dirname,
166+
recommendedConfig: js.configs.recommended,
167+
});
168+
169+
const eslintConfig = [
170+
...hypeConfig,
171+
// Add additional plugins using FlatCompat
172+
...compat.extends("plugin:tailwindcss/recommended"),
173+
// Your custom rules
174+
{
175+
files: ["**/*.ts", "**/*.tsx"],
176+
rules: {
177+
"no-console": "warn",
178+
},
179+
},
180+
];
181+
182+
export default eslintConfig;
183+
```
184+
185+
## Migration Guide
186+
187+
### Migrating from ESLint 8 to ESLint 9 (Next.js 14 to Next.js 15)
188+
189+
1. **Install required dependencies**:
190+
```bash
191+
npm install --save-dev eslint@^9.0.0 @eslint/eslintrc@^3.0.0 @eslint/js@^9.0.0
192+
```
193+
194+
2. **Create a new flat config file**:
195+
Create an `eslint.config.mjs` file in your project root:
196+
```js
197+
import hypeConfig from '@hypetech/eslint-config/flat';
198+
199+
export default hypeConfig;
200+
```
201+
202+
3. **Remove old configuration**:
203+
If you have an existing `.eslintrc.js`, `.eslintrc.cjs`, or `eslintConfig` in your `package.json`, you can remove it or keep it for backward compatibility with tools that don't yet support the flat config system.
204+
205+
4. **Update your VS Code settings** (optional):
206+
If you're using VS Code, update your settings to work with the new flat config:
207+
```json
208+
{
209+
"eslint.experimental.useFlatConfig": true
210+
}
211+
```
212+
65213
# Contributing
66214
67215
Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change.

eslint.config.mjs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { dirname } from "path";
2+
import { fileURLToPath } from "url";
3+
import { FlatCompat } from "@eslint/eslintrc";
4+
import js from "@eslint/js";
5+
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = dirname(__filename);
8+
9+
const compat = new FlatCompat({
10+
baseDirectory: __dirname,
11+
recommendedConfig: js.configs.recommended,
12+
});
13+
14+
// Import the existing configuration
15+
const existingConfig = require("./index.js");
16+
17+
const eslintConfig = [
18+
...compat.config({
19+
extends: [
20+
"plugin:react/recommended",
21+
"plugin:@typescript-eslint/recommended",
22+
"plugin:react-hooks/recommended",
23+
"prettier",
24+
"plugin:prettier/recommended",
25+
],
26+
plugins: ["@typescript-eslint", "import", "unused-imports"],
27+
parserOptions: {
28+
ecmaVersion: 2020,
29+
sourceType: "module",
30+
ecmaFeatures: {
31+
jsx: true,
32+
},
33+
},
34+
}),
35+
{
36+
files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
37+
rules: {
38+
// Copy rules from the existing configuration
39+
"@typescript-eslint/no-empty-interface": "error",
40+
"@typescript-eslint/explicit-module-boundary-types": "off",
41+
"@typescript-eslint/no-unused-vars": "off",
42+
"@typescript-eslint/no-var-requires": "off",
43+
"@typescript-eslint/padding-line-between-statements": [
44+
"error",
45+
{
46+
blankLine: "always",
47+
prev: ["const", "let", "var", "export", "interface", "type"],
48+
next: "*",
49+
},
50+
{
51+
blankLine: "any",
52+
prev: ["const", "let", "var"],
53+
next: ["const", "let", "var"],
54+
},
55+
{ blankLine: "always", prev: "*", next: ["interface", "type"] },
56+
],
57+
"import/order": [
58+
"error",
59+
{
60+
"newlines-between": "always",
61+
alphabetize: { order: 'asc', caseInsensitive: true },
62+
// Custom groups for sorting
63+
pathGroups: [
64+
"@/",
65+
"types",
66+
"config",
67+
"lib",
68+
"app",
69+
"components",
70+
"pages",
71+
"res",
72+
].map(function (path) {
73+
return {
74+
pattern: path + "/**",
75+
group: "external",
76+
position: "after",
77+
};
78+
}),
79+
pathGroupsExcludedImportTypes: ["builtin"],
80+
},
81+
],
82+
"padding-line-between-statements": "off",
83+
"prettier/prettier": "error",
84+
"react/react-in-jsx-scope": "off",
85+
"unused-imports/no-unused-imports-ts": "error",
86+
"unused-imports/no-unused-vars-ts": [
87+
"warn",
88+
{
89+
vars: "all",
90+
varsIgnorePattern: "^_",
91+
args: "after-used",
92+
argsIgnorePattern: "^_",
93+
},
94+
],
95+
},
96+
},
97+
{
98+
settings: {
99+
react: {
100+
version: "detect",
101+
},
102+
},
103+
},
104+
];
105+
106+
export default eslintConfig;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Example .eslintrc.js for a Next.js 14 project
2+
module.exports = {
3+
root: true,
4+
extends: '@hypetech/eslint-config',
5+
rules: {
6+
// Add any project-specific rules here
7+
'no-console': 'warn',
8+
},
9+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Example eslint.config.mjs for a Next.js 15 project
2+
import { dirname } from "path";
3+
import { fileURLToPath } from "url";
4+
import { FlatCompat } from "@eslint/eslintrc";
5+
import js from "@eslint/js";
6+
import hypeConfig from '../../eslint.config.mjs';
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = dirname(__filename);
10+
11+
const compat = new FlatCompat({
12+
baseDirectory: __dirname,
13+
recommendedConfig: js.configs.recommended,
14+
});
15+
16+
const eslintConfig = [
17+
...hypeConfig,
18+
// Project-specific configurations
19+
{
20+
files: ["**/*.ts", "**/*.tsx"],
21+
rules: {
22+
// Add any project-specific rules here
23+
"no-console": "warn",
24+
},
25+
},
26+
];
27+
28+
export default eslintConfig;

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = {
99
],
1010
plugins: ["@typescript-eslint", "import", "unused-imports"],
1111
parserOptions: {
12-
ecmaVersion: 2020,
12+
ecmaVersion: 2022, // Updated to support newer JavaScript features in Next.js 15
1313
sourceType: "module",
1414
ecmaFeatures: {
1515
jsx: true,
@@ -38,7 +38,7 @@ module.exports = {
3838
"error",
3939
{
4040
"newlines-between": "always",
41-
// alphabetize: { order: 'asc', caseInsensitive: true },
41+
alphabetize: { order: 'asc', caseInsensitive: true },
4242
// Custom groups for sorting
4343
pathGroups: [
4444
"@/",

0 commit comments

Comments
 (0)