rembrembdocs

ESLint Plugin

Last updated April 23, 2026

Next.js provides an ESLint configuration package, eslint-config-next, that makes it easy to catch common issues in your application. It includes the @next/eslint-plugin-next plugin along with recommended rule-sets from eslint-plugin-react and eslint-plugin-react-hooks.

The package provides two main configurations:

Additionally, for TypeScript projects:

Setup ESLint

Get linting working quickly with the ESLint CLI (flat config):

  1. Install ESLint and the Next.js config:

    pnpm

    pnpm

    npm

    npm

    yarn

    yarn

    bun

    bun

    Terminal

    pnpm add -D eslint eslint-config-next
    
  2. Create eslint.config.mjs with the Next.js config:

    eslint.config.mjs

    import { defineConfig, globalIgnores } from 'eslint/config'
    import nextVitals from 'eslint-config-next/core-web-vitals'
     
    const eslintConfig = defineConfig([
      ...nextVitals,
      // Override default ignores of eslint-config-next.
      globalIgnores([
        // Default ignores of eslint-config-next:
        '.next/**',
        'out/**',
        'build/**',
        'next-env.d.ts',
      ]),
    ])
     
    export default eslintConfig
    
  3. Run ESLint:

    pnpm

    pnpm

    npm

    npm

    yarn

    yarn

    bun

    bun

    Terminal

    pnpm exec eslint .
    

Reference

The eslint-config-next package includes the recommended rule-sets from the following ESLint plugins:

Rules

The @next/eslint-plugin-next rules included are:

Enabled in recommended configRuleDescription
@next/next/google-font-displayEnforce font-display behavior with Google Fonts.
@next/next/google-font-preconnectEnsure preconnect is used with Google Fonts.
@next/next/inline-script-idEnforce id attribute on next/script components with inline content.
@next/next/next-script-for-gaPrefer next/script component when using the inline script for Google Analytics.
@next/next/no-assign-module-variablePrevent assignment to the module variable.
@next/next/no-async-client-componentPrevent Client Components from being async functions.
@next/next/no-before-interactive-script-outside-documentPrevent usage of next/script's beforeInteractive strategy outside of pages/_document.js.
@next/next/no-css-tagsPrevent manual stylesheet tags.
@next/next/no-document-import-in-pagePrevent importing next/document outside of pages/_document.js.
@next/next/no-duplicate-headPrevent duplicate usage of <Head> in pages/_document.js.
@next/next/no-head-elementPrevent usage of <head> element.
@next/next/no-head-import-in-documentPrevent usage of next/head in pages/_document.js.
@next/next/no-html-link-for-pagesPrevent usage of <a> elements to navigate to internal Next.js pages.
@next/next/no-img-elementPrevent usage of <img> element due to slower LCP and higher bandwidth.
@next/next/no-page-custom-fontPrevent page-only custom fonts.
@next/next/no-script-component-in-headPrevent usage of next/script in next/head component.
@next/next/no-styled-jsx-in-documentPrevent usage of styled-jsx in pages/_document.js.
@next/next/no-sync-scriptsPrevent synchronous scripts.
@next/next/no-title-in-document-headPrevent usage of <title> with Head component from next/document.
@next/next/no-typosPrevent common typos in Next.js's data fetching functions
@next/next/no-unwanted-polyfillioPrevent duplicate polyfills from Polyfill.io.

We recommend using an appropriate integration to view warnings and errors directly in your code editor during development.

next lint removal

Starting with Next.js 16, next lint is removed.

As part of the removal, the eslint option in your Next config file is no longer needed and can be safely removed.

Examples

Specifying a root directory within a monorepo

If you're using @next/eslint-plugin-next in a project where Next.js isn't installed in your root directory (such as a monorepo), you can tell @next/eslint-plugin-next where to find your Next.js application using the settings property in your eslint.config.mjs:

eslint.config.mjs

import { defineConfig } from 'eslint/config'
import eslintNextPlugin from '@next/eslint-plugin-next'
 
const eslintConfig = defineConfig([
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    plugins: {
      next: eslintNextPlugin,
    },
    settings: {
      next: {
        rootDir: 'packages/my-app/',
      },
    },
  },
])
 
export default eslintConfig

rootDir can be a path (relative or absolute), a glob (i.e. "packages/*/"), or an array of paths and/or globs.

Disabling rules

If you would like to modify or disable any rules provided by the supported plugins (react, react-hooks, next), you can directly change them using the rules property in your eslint.config.mjs:

eslint.config.mjs

import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  {
    rules: {
      'react/no-unescaped-entities': 'off',
      '@next/next/no-page-custom-font': 'off',
    },
  },
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

With Core Web Vitals

Enable the eslint-config-next/core-web-vitals configuration in your ESLint config.

eslint.config.mjs

import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

eslint-config-next/core-web-vitals upgrades certain lint rules in @next/eslint-plugin-next from warnings to errors to help improve your Core Web Vitals metrics.

The eslint-config-next/core-web-vitals configuration is automatically included for new applications built with Create Next App.

With TypeScript

In addition to the Next.js ESLint rules, create-next-app --typescript will also add TypeScript-specific lint rules with eslint-config-next/typescript to your config:

eslint.config.mjs

import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import nextTs from 'eslint-config-next/typescript'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

Those rules are based on plugin:@typescript-eslint/recommended. See typescript-eslint > Configs for more details.

With Prettier

ESLint also contains code formatting rules, which can conflict with your existing Prettier setup. We recommend including eslint-config-prettier in your ESLint config to make ESLint and Prettier work together.

First, install the dependency:

pnpm

pnpm

npm

npm

yarn

yarn

bun

bun

Terminal

pnpm add -D eslint-config-prettier

Then, add prettier to your existing ESLint config:

eslint.config.mjs

import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import prettier from 'eslint-config-prettier/flat'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  prettier,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

Running lint on staged files

If you would like to use ESLint with lint-staged to run the linter on staged git files, add the following to the .lintstagedrc.js file in the root of your project:

.lintstagedrc.js

const path = require('path')
 
const buildEslintCommand = (filenames) =>
  `eslint --fix ${filenames
    .map((f) => `"${path.relative(process.cwd(), f)}"`)
    .join(' ')}`
 
module.exports = {
  '*.{js,jsx,ts,tsx}': [buildEslintCommand],
}

Migrating existing config

If you already have ESLint configured in your application, there are two approaches to integrate Next.js linting rules, depending on your setup.

Using the plugin directly

Use @next/eslint-plugin-next directly if you have any of the following already configured:

In these cases, use @next/eslint-plugin-next directly to avoid conflicts:

First, install the plugin:

pnpm

pnpm

npm

npm

yarn

yarn

bun

bun

Terminal

pnpm add -D @next/eslint-plugin-next

Then add it to your ESLint config:

eslint.config.mjs

import { defineConfig } from 'eslint/config'
import nextPlugin from '@next/eslint-plugin-next'
 
const eslintConfig = defineConfig([
  // Your other configurations...
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    plugins: {
      '@next/next': nextPlugin,
    },
    rules: {
      ...nextPlugin.configs.recommended.rules,
    },
  },
])
 
export default eslintConfig

This approach eliminates the risk of collisions or errors that can occur when the same plugins or parsers are imported across multiple configurations.

Adding to existing config

If you're adding Next.js to an existing ESLint setup, spread the Next.js config into your array:

eslint.config.mjs

import nextConfig from 'eslint-config-next/core-web-vitals'
// Your other config imports...
 
const eslintConfig = [
  // Your other configurations...
  ...nextConfig,
]
 
export default eslintConfig

When you spread ...nextConfig, you're adding multiple config objects that include file patterns, plugins, rules, ignores, and parser settings. ESLint applies configs in order, so later rules can override earlier ones for matching files.

Good to know: This approach works well for straightforward setups. If you have a complex existing config with specific file patterns or plugin configurations that conflict, consider using the plugin directly (as shown above) for more granular control.

VersionChanges
v16.0.0next lint and the eslint next.config.js option were removed in favor of the ESLint CLI. A codemod is available to help you migrate.

Was this helpful?