ESLint is a static analysis tool that flags problematic patterns and style violations in JavaScript and TypeScript code. A Next.js project gets a good part of that for free from eslint-config-next, but the default setup stops short of type-aware rules and import resolution. This is the config I use instead.
As of Next.js 11, ESLint is integrated right out of the box. For existing projects, or if you need to set it up manually, it's two commands:
pnpm install eslint eslint-config-next --save-devThen, you can set up your initial ESLint configuration file by running:
npx eslint --initESLint offers a wide range of community-established patterns and practices known as the "recommended" config. This configuration is a curated list of rules that aim to catch common bugs and enforce a consistent coding style.
My go-to config looks something like this:
const { resolve } = require("node:path");
const project = resolve(process.cwd(), "tsconfig.json");
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: [
"eslint:recommended",
"prettier",
"next",
"next/core-web-vitals",
require.resolve("@vercel/style-guide/eslint/next"),
],
globals: {
React: true,
JSX: true,
window: true,
},
env: {
node: true,
},
plugins: [],
settings: {
"import/resolver": {
typescript: {
project,
},
},
},
ignorePatterns: [
// Ignore dotfiles
".*.js",
"node_modules/",
],
overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }],
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
},
rules: {
"no-unused-vars": "off",
},
};
I use an .eslintrc.js file so the config can run JavaScript, which is what makes the require.resolve line work. @vercel/style-guide does the heavy lifting here: it adds the TypeScript, React, and import rules that eslint-config-next leaves out. On an existing codebase, expect a large batch of warnings and errors on the first run.
ESLint 9 reads eslint.config.js and expects an array instead of an object. eslint-config-next still ships in eslintrc format, so the shortest path is to wrap it with FlatCompat and keep the rest as plain objects:
const { FlatCompat } = require("@eslint/eslintrc");
const compat = new FlatCompat();
module.exports = [
...compat.extends("next/core-web-vitals"),
{
rules: {
"no-unused-vars": "off",
},
},
];Everything else from the config above carries over unchanged.
Occasional notes on software, tools, and things I learn. No spam.
Unsubscribe anytime.