Starting a fresh Next.js project the other day, I was happy to see that configuring eslint
was part of the bootstrapping process. Where things fell short for me, was the lack of a prompt asking me which style guide I’d like to use.
I’m sure the out of the box option is sufficient enough, and definitely better than nothing, which still seems to be the norm for most people. Browsing some of the created files and seeing a file full of double quotes sent me into a frenzy to figure out how I can bring my beloved Airbnb style guide into the mix.
Create Next.js app
When creating my app with the create-next-app
script, I went with the following configuration:
% npx create-next-app@latest
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like to use `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to customize the default import alias (@/*)? … No
Creating a new Next.js app in /private/tmp/my-app.
ZshBecause I went with TypeScript, there is a bit of additional setup, but not much.
Reinitializing ESLint
To get things moving in the right direction, I reinitialized eslint
. When answering the prompts, I lied and told it I wasn’t using TypeScript, as saying your project is using TypeScript will strip the Airbnb style guide option from the list of “popular” style guides:
% npm init @eslint/config
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No
✔ Where does your code run? · browser, node
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · airbnb
✔ What format do you want your config file to be in? · JSON
Checking peerDependencies of eslint-config-airbnb@latest
The config that you've selected requires the following dependencies:
eslint-plugin-react@^7.28.0 eslint-config-airbnb@latest eslint@^7.32.0 || ^8.2.0 eslint-plugin-import@^2.25.3 eslint-plugin-jsx-a11y@^6.5.1 eslint-plugin-react-hooks@^4.3.0
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm
Installing eslint-plugin-react@^7.28.0, eslint-config-airbnb@latest, eslint@^7.32.0 || ^8.2.0, eslint-plugin-import@^2.25.3, eslint-plugin-jsx-a11y@^6.5.1, eslint-plugin-react-hooks@^4.3.0
added 4 packages, and audited 376 packages in 2s
137 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Successfully created .eslintrc.json file in /private/tmp/my-app
ZshSo close, yet so far
By choosing the JSON config file format, the .eslintrc.json
generated by create-next-app
will be wiped clean in favor of a configuration based on the initialization options.
If you were to try to run npm run lint
at this point, you’d be greeted with a whole mess of errors:
% npm run lint
> my-app@0.1.0 lint
> next lint
⚠ The Next.js plugin was not detected in your ESLint configuration. See https://nextjs.org/docs/basic-features/eslint#migrating-existing-config
./src/app/layout.tsx
1:13 Error: Parsing error: Unexpected token {
./src/app/page.tsx
1:19 Error: Strings must use singlequote. quotes
5:5 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
5:5 Error: JSX not allowed in files with extension '.tsx' react/jsx-filename-extension
6:7 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
7:9 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
9:11 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
11:9 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
12:11 Error: 'React' must be in scope when using JSX react/react-in-jsx-scope
18:15 Error: `{" "}` must be placed on a new line react/jsx-one-expression-per-line
# And on and on...
ZshReconfiguring ESLint
Since the out of the box configuration isn’t perfect, I created a mash up of what we got from create-next-app
, what npm init @eslint/config
generated, and some additional stuff to support TypeScript:
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"airbnb",
"airbnb/hooks",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended",
"next/core-web-vitals"
],
"parser": "@typescript-eslint/parser",
"plugins": [
"react"
],
"rules": {
"react/jsx-filename-extension": [
2,
{ "extensions": [".js", ".jsx", ".ts", ".tsx"] }
]
}
}
.eslintrc.jsonInstalling missing dependencies
With our config ready to go, we still need to install one more package before things will work. This will give us the TypeScript ESLint parser:
% npm install --save-dev @typescript-eslint/eslint-plugin
added 12 packages, and audited 388 packages in 995ms
145 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Zshchore: making the linter happy
At this point, running the linter will yield a bunch of errors based on the Airbnb style guide.
% npm run lint
> my-app@0.1.0 lint
> next lint
./src/app/layout.tsx
1:31 Error: Strings must use singlequote. quotes
2:23 Error: Strings must use singlequote. quotes
3:8 Error: Strings must use singlequote. quotes
5:33 Error: Strings must use singlequote. quotes
8:10 Error: Strings must use singlequote. quotes
9:16 Error: Strings must use singlequote. quotes
./src/app/page.tsx
1:19 Error: Strings must use singlequote. quotes
18:15 Error: `{" "}` must be placed on a new line react/jsx-one-expression-per-line
18:16 Error: Strings must use singlequote. quotes
49:25 Error: Curly braces are unnecessary here. react/jsx-curly-brace-presence
49:26 Error: Strings must use singlequote. quotes
50:17 Error: `{" "}` must be placed on a new line react/jsx-one-expression-per-line
50:18 Error: Strings must use singlequote. quotes
55:24 Error: Curly braces are unnecessary here. react/jsx-curly-brace-presence
55:25 Error: Strings must use singlequote. quotes
66:25 Error: Curly braces are unnecessary here. react/jsx-curly-brace-presence
66:26 Error: Strings must use singlequote. quotes
67:18 Error: `{" "}` must be placed on a new line react/jsx-one-expression-per-line
67:19 Error: Strings must use singlequote. quotes
72:24 Error: Curly braces are unnecessary here. react/jsx-curly-brace-presence
72:25 Error: Strings must use singlequote. quotes
83:25 Error: Curly braces are unnecessary here. react/jsx-curly-brace-presence
# And then some...
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
ZshFinally, I went through and cleaned up things by hand. You could certainly use something like prettier
or even ESLint’s --fix
option. I prefer a bit more control, so I go about it the old fashioned way.