Search across all documentation pages
Install and configure ESLint plugins for React, TypeScript, accessibility, Tailwind CSS, and testing.
Quick-reference recipe card — copy-paste ready.
# Core plugins (most included with next/core-web-vitals)
npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks
# TypeScript
npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser
# Imports
npm install --save-dev eslint-plugin-import
# Accessibility
npm install --save-dev eslint-plugin-jsx-a11y
# Tailwind CSS
npm install --save-dev eslint-plugin-tailwindcss
# Testing Library
npm install --save-dev eslint-plugin-testing-libraryWhen to reach for this: When you need rules beyond what next/core-web-vitals provides — Tailwind class ordering, test best practices, or stricter accessibility checks.
// eslint.config.mjs
import { FlatCompat } from "@eslint/eslintrc";
import tailwindcss from "eslint-plugin-tailwindcss";
import { dirname } from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta
What this demonstrates:
react/, jsx-a11y/)next/core-web-vitals already includes eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-next, eslint-plugin-import, and eslint-plugin-jsx-a11ytailwindcss and testing-library are added on topconfigs["flat/recommended"] directly; others need FlatCompatPlugin overview:
| Plugin | Namespace | What It Does |
|---|---|---|
eslint-plugin-react | react/ | JSX best practices, component patterns |
eslint-plugin-react-hooks | react-hooks/ | Hook rules and dependency checking |
@typescript-eslint/eslint-plugin | @typescript-eslint/ | TypeScript-specific rules |
eslint-plugin-import | import/ | Import ordering, no duplicates, no unresolved |
eslint-plugin-jsx-a11y | jsx-a11y/ | Accessibility rules for JSX elements |
eslint-plugin-tailwindcss | tailwindcss/ | Class ordering, no contradicting classes |
eslint-plugin-testing-library | testing-library/ | Best practices for Testing Library |
Tailwind plugin key rules:
{
rules: {
"tailwindcss/classnames-order": "warn", // Sort classes
"tailwindcss/no-custom-classname": "off", // Allow custom classes
"tailwindcss/no-contradicting-classname": "error", // Catch p-4 p-8
"tailwindcss/enforces-negative-arbitrary-values": "warn",
},
}Testing Library plugin (scoped to test files):
{
files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
rules: {
"testing-library/await-async-queries": "error",
"testing-library/no-debugging-utils": "warn",
"testing-library/no-dom-import": "error",
"testing-library/prefer-screen-queries": "warn",
},
}// @typescript-eslint key rules:
// no-unused-vars — catches unused imports and variables
// no-explicit-any — flags `any` type usage
// consistent-type-imports — enforces `import type { X }` syntax
// no-non-null-assertion — flags `obj!.prop` assertions
// prefer-nullish-coalescing — flags `||` where `??` is safer
// These complement tsconfig strict mode but catch
// different things (patterns vs types)Things that will bite you. Each gotcha includes what goes wrong, why it happens, and the fix.
Duplicate plugin registration — Installing eslint-plugin-react manually when next/core-web-vitals already includes it causes conflicts. Fix: Check what the preset includes before adding plugins. Only add plugins not already bundled.
Tailwind plugin requires config — eslint-plugin-tailwindcss needs to find your tailwind.config.* file. If your config is in a non-standard location, the plugin fails silently. Fix: Set the config option in the plugin settings.
Testing plugin on all files — Applying testing-library rules globally flags non-test code. Fix: Always scope with files: ["**/*.test.*"].
Flat config compatibility — Not all plugins support flat config natively. Some need FlatCompat wrapping, which can cause unexpected behavior. Fix: Check the plugin's README for flat config support and use FlatCompat only when needed.
Performance with many plugins — Each plugin adds parsing and rule-checking time. Five or more plugins can noticeably slow down linting. Fix: Use TIMING=1 npx eslint . to profile which rules are slow and disable any you do not need.
Other ways to solve the same problem — and when each is the better choice.
| Alternative | Use When | Don't Use When |
|---|---|---|
| Biome | You want linting + formatting in one fast tool | You need Tailwind or testing-library rules |
next/core-web-vitals only | The bundled plugins are sufficient for your project | You need Tailwind class ordering or test rules |
oxlint | You want blazing-fast linting with common rules | You need plugin-specific rules (Tailwind, testing) |
eslint-plugin-reacteslint-plugin-react-hookseslint-plugin-nexteslint-plugin-importeslint-plugin-jsx-a11yYou do not need to install these separately.
{
files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
rules: {
"testing-library/await-async-queries": "error",
"testing-library/prefer-screen-queries": "warn",
},
}Use the files property to restrict rules to matching globs.
tailwindcss/classnames-order sorts Tailwind classes in the recommended order.tailwindcss/no-contradicting-classname catches conflicts like p-4 p-8.tailwindcss/no-custom-classname flags classes not in the Tailwind config (often turned off).tailwind.config.* in the project root by default.config option in the plugin settings.configs["flat/recommended"] directly.FlatCompat wrapping to work with ESLint 9 flat config.TIMING=1 npx eslint . to find the slowest rules and disable those you do not need."@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/no-explicit-any": "warn",These are included via next/typescript but you can override their severity.
files: ["**/*.test.*", "**/*.spec.*"].react/, @typescript-eslint/, jsx-a11y/, etc.npx eslint --print-config src/app/page.tsx to see all active rules and their sources.jsx-a11y/alt-text requires alt attributes on images.jsx-a11y/anchor-is-valid warns about anchors without valid href.@typescript-eslint catches code patterns (unused vars, floating promises, explicit any).tsconfig strict options catch type-level issues (null checks, implicit any, unchecked index access).