---
id: "packages/eslint-config"
title: "eslint-config"
description: "The shared ESLint presets of the Active packages, for Node and tooling code, React libraries and Next.js applications."
url: "/packages/eslint-config"
locale: "en"
revision: "26a1bf2d137d1201"
---

# eslint-config

`@workspace/eslint-config` is the lint half of the shared [development basis](/development-basis).
It holds ESLint 10 flat-config presets: one baseline for every kind of code, two React
specialisations built on it, and an optional plugin for a resource data layer. Your repository
imports a preset in its `eslint.config.mjs` and adds only what is its own.

The package decides **which rules run and how they report**. Your repository decides **when a lint
run fails**, through the warning threshold in its `lint` script. Read both halves before you trust
a green run.

## What the presets check

| Category | Comes from | In which presets |
| --- | --- | --- |
| JavaScript correctness | `@eslint/js` recommended rules | all |
| TypeScript | `typescript-eslint` recommended rules, without type information | all |
| Unused code | `no-unused-vars`, with names that start with `_` allowed | all |
| No conflict with the formatter | `eslint-config-prettier` switches every formatting rule off | all |
| Environment variables | `turbo/no-undeclared-env-vars`: every variable a file reads is in `turbo.json` | all |
| Text and naming conventions | no em-dash (U+2014) in JSX text; a `catch` binding is `err`, not `e` or `error` | all, except in test files |
| React correctness and DOM safety | a curated set of `@eslint-react` rules | `react-internal`, `next-js` |
| Rules of hooks | `eslint-plugin-react-hooks` recommended rules | `react-internal`, `next-js` |
| Next.js | `@next/eslint-plugin-next` recommended and Core Web Vitals rules | `next-js` |
| A resource data layer | `resources/select-required` and `resources/no-raw-where-spread` | only where you wire `resource-rules` |

Test files (`__tests__/`, `*.test.*`, `*.spec.*`) may use `any` and are exempt from the text and
naming conventions.

This is an overview by category, not a rule list. The exact rules are in the package itself: its
`README.md` and `docs/API.md` travel with every copy, and
[Checks and troubleshooting](/packages/eslint-config/checks) shows how to print the rules ESLint
applies to a file.

## Every finding is a warning

The presets include `eslint-plugin-only-warn`, which reports every rule as a **warning**. That
includes the rules the presets configure as `error`, and the rules your own repository adds.
Nothing in a lint run is reported as an error, except a file ESLint cannot parse.

So a lint run fails in three cases only:

| Situation | Exit code |
| --- | --- |
| more warnings than `--max-warnings` allows | 1 |
| a file that does not parse | 1 |
| a configuration ESLint cannot load | 2 |

**A passing lint run does not mean zero findings.** With the usual threshold of 100, a run with 100
warnings passes. Read the count in the summary line, and fix the warnings your own work
introduces: the room under the threshold is not permission.

## The package and your repository

| The package decides | Your repository decides |
| --- | --- |
| the rules of each preset and their options | which preset each package or app imports |
| that every finding is a warning | the `--max-warnings` threshold in each `lint` script |
| the files every preset ignores (`dist/`, and the Next.js output in `next-js`) | its own `ignores`, and stricter or tool-specific rules in a trailing block |
| the plugins and their versions (`dependencies` of the package) | the `eslint` and `typescript` versions it installs |
| the resource rules themselves | the files they apply to |
| nothing about how often lint runs | the scripts and checks that run lint, and what they require |

The shared development standard sets the threshold at 100 for every `lint` script and lists what
a repository may add; see [Local additions](/packages/eslint-config/local-additions).

## How you receive it

`eslint-config` is maintained in Foundation and reaches your repository by
[managed source transfer](/receiving-packages), on its own or in the same set as other packages. It
is in development: no version of it is recorded as a release in Foundation, so it comes on the
`development` channel. See [Getting started](/packages/eslint-config/getting-started).

## What it does not do

- **No formatting.** Whitespace, quotes and import order are Prettier's; see the
  [development basis](/development-basis).
- **No type checking.** The TypeScript rules run without type information, so lint needs no
  `tsconfig`. Types are checked by `tsc` with [typescript-config](/packages/typescript-config).
- **No legacy configuration.** Flat config only; an `.eslintrc` file is not read.
