1. Omid Sayfun
  2. /
  3. Notebook
  • Home
  • About
  • Notebook
  • Token Usage
  • Whisper Usage
Tools
  • Agent Knowledge Base

My go-to Next.js ESlint config

March 10, 2024 · Updated on August 09, 2026

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.

I write short, practical notes like this one. Get the next one by email:

Unsubscribe anytime.

Install eslint-config-next

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-dev

Then, you can set up your initial ESLint configuration file by running:

npx eslint --init

Extend next/core-web-vitals, then layer @vercel/style-guide on top

ESLint 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.

On ESLint 9, the same config becomes a flat array

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.

Join My Newsletter

Occasional notes on software, tools, and things I learn. No spam.

Unsubscribe anytime.

Continue Reading

  • Embeddings rot too. Running pgvector in production.Aug 28, 2026
  • Stop shipping retrieval changes on vibesAug 25, 2026
  • Your RAG is confidently wrong without hybrid searchAug 21, 2026
  • Stop tuning everything. pgvector has three knobs that matter.Aug 18, 2026
  • Your agent's knowledge base is lying to you. Run these 14 checks.Aug 18, 2026