ESLint and Prettier
Linter vs formatter, flat config, useful rules, automation, Biome.
Updated
What a linter and a formatter are
Two different tools that often get confused:
| Linter (ESLint) | Formatter (Prettier) | |
|---|---|---|
| The question | Is the code correct? | Does the code look consistent? |
| Finds | likely bugs: unused variables, a forgotten await, missing useEffect dependencies, accessibility rules |
spaces, quotes, commas, line length |
| Fixes automatically | some rules | everything |
| Example | 'x' is assigned but never used |
"a" → 'a' |
Together they remove two kinds of code review discussions: "there's an obvious bug here" and "add a space here".
ESLint
ESLint analyzes the code without running it (static analysis) and applies rules. The configuration (flat config) is an array of objects:
// eslint.config.mjs — exactly what create-next-app generates in Next 16
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import nextTs from 'eslint-config-next/typescript'
export default defineConfig([
...nextVitals, // React, hooks, Next, accessibility, Core Web Vitals
...nextTs, // TypeScript rules
globalIgnores(['.next/**', 'next-env.d.ts']),
{
rules: {
'no-console': ['warn', { allow: ['error'] }],
'react-hooks/exhaustive-deps': 'error',
},
},
])| Level | Effect |
|---|---|
'off' |
disabled |
'warn' |
shows up, but doesn't stop CI |
'error' |
stops the build / CI |
Rules that catch real bugs: react-hooks/rules-of-hooks, react-hooks/exhaustive-deps, @typescript-eslint/no-floating-promises (a Promise without await), jsx-a11y/* (accessibility). In Next 16 you run eslint directly (next lint was removed).
Prettier
Prettier rewrites all the code in a single style. Almost no options — on purpose: style is no longer up for debate.
// .prettierrc
{
"semi": false,
"singleQuote": true,
"printWidth": 120,
"plugins": ["prettier-plugin-tailwindcss"]
}prettier-plugin-tailwindcss automatically sorts Tailwind classes in the recommended order.
Where it runs — automation
| Where | How | Why |
|---|---|---|
| the editor | "Format on save" + the ESLint extension | instant feedback |
| pre-commit | lefthook / husky + lint-staged: only on changed files | no unformatted code reaches Git |
| CI | npm run lint + prettier --check . + tsc --noEmit |
the last, mandatory barrier |
The alternative: Biome
Biome = a linter + formatter in a single tool, written in Rust, dozens of times faster. Fewer rules and plugins than ESLint, but a much simpler configuration. Good for new projects that don't need specialized rules.
Summary
- A linter = correctness (likely bugs); a formatter = appearance (style).
- ESLint with flat config + the Next / React hooks / a11y rules; Prettier for formatting.
- Run them in the editor, on pre-commit and in CI; Biome as a fast alternative.