@drazenbebic/eslint-config-next 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +126 -0
  3. package/index.js +87 -0
  4. package/package.json +80 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Drazen Bebic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # @drazenbebic/eslint-config-next
2
+
3
+ > Opinionated, shareable [ESLint flat config](https://eslint.org/docs/latest/use/configure/configuration-files) for personal Next.js projects.
4
+
5
+ It composes the official [`eslint-config-next`](https://www.npmjs.com/package/eslint-config-next) (Core Web Vitals + TypeScript) with Prettier, import sorting, unused-import removal, and [`perfectionist`](https://perfectionist.dev/) sorting — so a new Next.js app gets a consistent, batteries-included lint setup from a single dependency.
6
+
7
+ > **Heads up:** this is a personal config tuned to my own preferences. You're welcome to use it, but it will change to suit my projects, not yours. Pin a version if that matters to you.
8
+
9
+ ## What's inside
10
+
11
+ - **`eslint-config-next/core-web-vitals`** and **`eslint-config-next/typescript`** — the official Next.js rules.
12
+ - **Prettier** via [`eslint-plugin-prettier`](https://github.com/prettier/eslint-plugin-prettier) (`prettier/prettier` runs as an ESLint rule, and conflicting stylistic rules are turned off by `eslint-config-prettier`).
13
+ - **`simple-import-sort`** — deterministic import/export ordering grouped as: side-effects → React/Next/node builtins → third-party → `@/` alias → relative.
14
+ - **`unused-imports`** — auto-removes unused imports and warns on unused vars.
15
+ - **`perfectionist`** — alphabetical sorting of JSX props, named imports/exports, union/intersection types, arrays, and more.
16
+ - A few hand-picked core rules: `no-console` (allowing `warn`/`error`), `curly: all`, and `padding-line-between-statements` (blank lines around `if`/`for`/`try`/`return`).
17
+ - Default ignores: `.next/**`, `out/**`, `build/**`, `next-env.d.ts`.
18
+
19
+ ## Requirements
20
+
21
+ - **Node.js** `>= 20`
22
+ - **ESLint** `^9 || ^10` (flat config only — there is no `.eslintrc` support)
23
+ - **Next.js** (`next`) `>= 15` — already in your app; required because this config extends `eslint-config-next`, whose parser loads from `next`
24
+ - **Prettier** `^3`
25
+ - **TypeScript** `>= 5` (optional, only if your project uses it)
26
+
27
+ The ESLint plugins themselves ship as dependencies of this package, so you don't install them separately — only the peers above. In a real Next.js project `next` is already present, so you typically only add `eslint` and `prettier`.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pnpm add -D @drazenbebic/eslint-config-next eslint prettier
33
+ # add typescript if your project uses it:
34
+ pnpm add -D typescript
35
+ ```
36
+
37
+ <details>
38
+ <summary>npm / yarn</summary>
39
+
40
+ ```bash
41
+ npm install -D @drazenbebic/eslint-config-next eslint prettier typescript
42
+ # or
43
+ yarn add -D @drazenbebic/eslint-config-next eslint prettier typescript
44
+ ```
45
+
46
+ </details>
47
+
48
+ ## Usage
49
+
50
+ Create an `eslint.config.mjs` (flat config) at the root of your project:
51
+
52
+ ```js
53
+ import config from '@drazenbebic/eslint-config-next';
54
+
55
+ export default config;
56
+ ```
57
+
58
+ That's it. The default export is a flat-config array, so you can spread it and add your own overrides on top.
59
+
60
+ ### Adding project-specific overrides
61
+
62
+ Because the config is a plain array, anything you add **after** the spread wins:
63
+
64
+ ```js
65
+ import { globalIgnores } from 'eslint/config';
66
+
67
+ import config from '@drazenbebic/eslint-config-next';
68
+
69
+ const eslintConfig = [
70
+ ...config,
71
+
72
+ // Ignore generated files (e.g. Sanity TypeGen output).
73
+ globalIgnores(['sanity.types.ts']),
74
+
75
+ // Tweak or disable rules for your project.
76
+ {
77
+ rules: {
78
+ 'no-console': 'off',
79
+ },
80
+ },
81
+ ];
82
+
83
+ export default eslintConfig;
84
+ ```
85
+
86
+ > **Note:** This config no longer ignores `sanity.types.ts` by default — add the `globalIgnores` line above in projects that use Sanity TypeGen.
87
+
88
+ ### Prettier
89
+
90
+ `prettier/prettier` runs inside ESLint, so formatting issues show up as lint errors and are fixable with `eslint --fix`. Add your own `.prettierrc` to control formatting (this config does not impose a Prettier style on your project). A typical `package.json`:
91
+
92
+ ```json
93
+ {
94
+ "scripts": {
95
+ "lint": "next lint",
96
+ "lint:fix": "eslint . --fix"
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### The `@/` import group
102
+
103
+ The import-sort rules put imports matching `^@/` in their own group, which assumes you use the `@/*` path alias (the Next.js default). If you use a different alias, override `simple-import-sort/imports` in your project config.
104
+
105
+ ## Releasing (maintainer notes)
106
+
107
+ This package uses [release-please](https://github.com/googleapis/release-please) with **Conventional Commits**. Versions, the changelog, and the GitHub release are derived from commit messages on `main`:
108
+
109
+ - `feat: …` → minor bump
110
+ - `fix: …` / `perf: …` → patch bump
111
+ - `feat!: …` or a `BREAKING CHANGE:` footer → major bump (minor while pre-1.0)
112
+
113
+ When release-please's "Version Packages" PR is merged, the `release-please` workflow publishes to npm with [provenance](https://docs.npmjs.com/generating-provenance-statements) using [npm trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC) — there is no long-lived `NPM_TOKEN` secret to manage.
114
+
115
+ **One-time bootstrap** (because npm can only attach a trusted publisher to a package that already exists):
116
+
117
+ 1. Publish once manually to claim the name and create the package:
118
+ ```bash
119
+ npm publish --access public
120
+ ```
121
+ 2. On npmjs.com → the package's **Settings → Trusted Publisher**, add this repo's GitHub Actions workflow (`.github/workflows/release-please.yml`).
122
+ 3. From then on, merging the release-please PR publishes hands-free via OIDC.
123
+
124
+ ## License
125
+
126
+ [MIT](./LICENSE)
package/index.js ADDED
@@ -0,0 +1,87 @@
1
+ import { defineConfig, globalIgnores } from 'eslint/config';
2
+ import nextVitals from 'eslint-config-next/core-web-vitals';
3
+ import nextTs from 'eslint-config-next/typescript';
4
+ import pluginPerfectionist from 'eslint-plugin-perfectionist';
5
+ import prettierRecommended from 'eslint-plugin-prettier/recommended';
6
+ import simpleImportSort from 'eslint-plugin-simple-import-sort';
7
+ import pluginUnusedImports from 'eslint-plugin-unused-imports';
8
+
9
+ const PERFECTIONIST_DEFAULT_ARGS = {
10
+ type: 'alphabetical',
11
+ order: 'asc',
12
+ };
13
+
14
+ const PERFECTIONIST_DEFAULT_CONFIG = ['error', PERFECTIONIST_DEFAULT_ARGS];
15
+
16
+ const eslintConfig = defineConfig([
17
+ ...nextVitals,
18
+ ...nextTs,
19
+ prettierRecommended,
20
+ {
21
+ settings: {
22
+ react: {
23
+ version: '19',
24
+ },
25
+ },
26
+ plugins: {
27
+ perfectionist: pluginPerfectionist,
28
+ 'unused-imports': pluginUnusedImports,
29
+ 'simple-import-sort': simpleImportSort,
30
+ },
31
+ rules: {
32
+ 'prettier/prettier': 'error',
33
+ 'unused-imports/no-unused-imports': 'warn',
34
+ 'unused-imports/no-unused-vars': 'warn',
35
+ 'no-console': ['warn', { allow: ['warn', 'error'] }],
36
+ curly: ['error', 'all'],
37
+ 'padding-line-between-statements': [
38
+ 'error',
39
+ { blankLine: 'always', prev: '*', next: 'if' },
40
+ { blankLine: 'always', prev: 'if', next: '*' },
41
+ { blankLine: 'always', prev: '*', next: 'for' },
42
+ { blankLine: 'always', prev: 'for', next: '*' },
43
+ { blankLine: 'always', prev: '*', next: 'try' },
44
+ { blankLine: 'always', prev: 'try', next: '*' },
45
+ { blankLine: 'always', prev: '*', next: 'return' },
46
+ ],
47
+ 'simple-import-sort/exports': 'error',
48
+ 'simple-import-sort/imports': [
49
+ 'error',
50
+ {
51
+ groups: [
52
+ // 1. Side effect imports (e.g. import 'style.css')
53
+ ['^\\u0000'],
54
+ // 2. React, Next.js, and other node built-ins
55
+ ['^react', '^next', '^node:'],
56
+ // 3. Third-party packages (starting with a letter or @)
57
+ ['^@?\\w'],
58
+ // 4. Internal imports (using your @/ alias)
59
+ ['^@/'],
60
+ // 5. Relative imports (starting with .)
61
+ ['^\\.'],
62
+ ],
63
+ },
64
+ ],
65
+ 'perfectionist/sort-jsx-props': PERFECTIONIST_DEFAULT_CONFIG,
66
+ 'perfectionist/sort-exports': PERFECTIONIST_DEFAULT_CONFIG,
67
+ 'perfectionist/sort-named-exports': PERFECTIONIST_DEFAULT_CONFIG,
68
+ 'perfectionist/sort-named-imports': PERFECTIONIST_DEFAULT_CONFIG,
69
+ 'perfectionist/sort-intersection-types': PERFECTIONIST_DEFAULT_CONFIG,
70
+ 'perfectionist/sort-array-includes': PERFECTIONIST_DEFAULT_CONFIG,
71
+ 'perfectionist/sort-union-types': PERFECTIONIST_DEFAULT_CONFIG,
72
+ 'perfectionist/sort-arrays': [
73
+ 'error',
74
+ {
75
+ ...PERFECTIONIST_DEFAULT_ARGS,
76
+ useConfigurationIf: {
77
+ matchesAstSelector: 'TSAsExpression > ArrayExpression',
78
+ },
79
+ },
80
+ ],
81
+ },
82
+ },
83
+ // Default ignores carried over from eslint-config-next.
84
+ globalIgnores(['.next/**', 'out/**', 'build/**', 'next-env.d.ts']),
85
+ ]);
86
+
87
+ export default eslintConfig;
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@drazenbebic/eslint-config-next",
3
+ "version": "1.0.0",
4
+ "description": "Opinionated, shareable ESLint flat config for personal Next.js projects (Next + TypeScript + Prettier + import sorting + perfectionist).",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslintconfig",
8
+ "eslint-config",
9
+ "eslintconfig-next",
10
+ "next",
11
+ "nextjs",
12
+ "react",
13
+ "typescript",
14
+ "prettier",
15
+ "perfectionist",
16
+ "flat-config"
17
+ ],
18
+ "homepage": "https://github.com/drazenbebic/eslint-config-next#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/drazenbebic/eslint-config-next/issues"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/drazenbebic/eslint-config-next.git"
25
+ },
26
+ "license": "MIT",
27
+ "author": {
28
+ "name": "Drazen Bebic",
29
+ "email": "drazen.bebic@outlook.com",
30
+ "url": "https://www.bebic.dev"
31
+ },
32
+ "type": "module",
33
+ "exports": {
34
+ ".": "./index.js"
35
+ },
36
+ "main": "./index.js",
37
+ "sideEffects": false,
38
+ "files": [
39
+ "index.js"
40
+ ],
41
+ "scripts": {
42
+ "lint": "eslint .",
43
+ "lint:fix": "eslint . --fix",
44
+ "format": "prettier --write .",
45
+ "format:check": "prettier --check .",
46
+ "test": "node --test"
47
+ },
48
+ "dependencies": {
49
+ "eslint-config-next": "^16.2.9",
50
+ "eslint-config-prettier": "^10.1.8",
51
+ "eslint-plugin-perfectionist": "^5.9.1",
52
+ "eslint-plugin-prettier": "^5.5.6",
53
+ "eslint-plugin-simple-import-sort": "^13.0.0",
54
+ "eslint-plugin-unused-imports": "^4.4.1"
55
+ },
56
+ "peerDependencies": {
57
+ "eslint": "^9.0.0 || ^10.0.0",
58
+ "next": ">=15.0.0",
59
+ "prettier": "^3.0.0",
60
+ "typescript": ">=5.0.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "typescript": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "devDependencies": {
68
+ "eslint": "^10.6.0",
69
+ "next": "^16.2.9",
70
+ "prettier": "^3.9.0",
71
+ "typescript": "^6.0.3"
72
+ },
73
+ "engines": {
74
+ "node": ">=20"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
78
+ },
79
+ "packageManager": "pnpm@11.5.2"
80
+ }