ESLint 11 🛡️ Shareable Configs — Extending community rule sets
A shareable config is an npm package that exports an ESLint configuration object or array. It packages a set of rules, plugins, parsers, and language options into a single dependency that a project can import and apply. The ESLint ecosystem has produced dozens of these packages—Airbnb’s style guide, Standard’s minimalist rules, Google’s readability-focused set, and the TypeScript-ESLint project’s recommended, strict, and stylistic tiers. Extending one is the difference between writing a configuration from scratch and adopting a set of rules that a community has already debated, tested, and maintained.
This chapter covers the shareable config package, the naming convention that makes it discoverable, the extends mechanism in the flat config, and the dependency rules that determine whether a config brings its plugins with it or expects the project to install them separately.
Key point: A shareable config is just an npm package that exports a config object or array. The eslint-config- prefix is a convention, not a requirement. The config’s peerDependencies declare the ESLint version it supports, and its dependencies declare the plugins and parsers it needs. The project that extends the config is responsible for installing the peer dependencies.
Why shareable configs exist
The debate problem. Every team that writes an ESLint configuration from scratch eventually debates the same questions: semicolons or no semicolons, single or double quotes, trailing commas or none, strict or permissive. A shareable config encodes a set of answers that a community has already settled on. Extending it replaces the debate with a decision: adopt the config or don’t, and if you don’t, pick a different one. The Node.js reference architecture document lists “minimizing what can be potentially divisive discussions” as the first benefit of using a pre-existing config .
The maintenance problem. A hand-written configuration accumulates rules over time. A new ESLint version introduces new recommended rules, a new TypeScript version introduces new syntax, and a new framework version introduces new patterns. A shareable config is maintained by its authors, and the project that extends it receives the updates when it bumps the dependency version. The Node.js document notes that “these configs can change over time” and recommends “time in your regular workflow to review these changes” .
The ecosystem problem. The ESLint documentation describes the extension mechanism as a first-class feature: “You can also add community plugins, configurations, and parsers to extend the functionality of ESLint” . The shareable config is the package that bundles those extensions into a single import.
a. The naming convention and the package structure
The ESLint documentation recommends two naming conventions for a shareable config. A standalone package begins with eslint-config-, such as eslint-config-myconfig. A scoped package uses the @scope/eslint-config prefix, such as @scope/eslint-config or @scope/eslint-config-myconfig .
The package exports the config from its main entry point, which is index.js by default. The export can be a single config object or an array of config objects. The documentation recommends an array for most cases, but notes that a single object is also valid .
// index.js
export default [
{
rules: {
semi: [2, "always"],
},
},
];
The package.json declares the ESLint dependency in peerDependencies. The recommended form is a >= range with the lowest supported version, such as "eslint": ">= 9" . The peer dependency means the project installs ESLint, and the shareable config uses whatever version the project provides. A config that depends on a plugin or a custom parser declares those packages in dependencies, because they are implementation details of the config, not choices for the project .
The keywords field should include eslint and eslintconfig so that the package is discoverable in the npm search .
b. The extends mechanism in the flat config
The flat config uses the extends key inside a configuration object. The key accepts a config object, a config array, or a string that references a named config from a plugin. The defineConfig helper flattens the extended configs into the array .
// eslint.config.js
import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
export default defineConfig([
{
files: ["**/*.js"],
extends: [myconfig],
rules: {
"no-unused-vars": "warn",
},
},
]);
The files key scopes the extended config to the matching files. The extends array applies the imported config first, and the rules object after it overrides the specific rules that the project wants to change . The override order is the array order: later objects take precedence over earlier ones for the files they match.
The documentation notes a limitation: “It’s not possible to use shareable configs with the ESLint CLI --config flag” . The --config flag is for a local configuration file, not for a shareable package.
c. The community rule sets
The most widely used shareable configs fall into three categories: style guides, framework-specific configs, and the TypeScript-ESLint tiers.
Airbnb is the strictest and most comprehensive. It enforces semicolons, single quotes, and a large set of React best practices. It requires several peer dependencies, including eslint-plugin-react, eslint-plugin-import, and eslint-plugin-jsx-a11y . The TypeScript variant is eslint-config-airbnb-typescript, which adds the TypeScript parser and the type-aware rules .
Standard is the minimalist option. It has no semicolons, enforces single quotes, and focuses on JavaScript correctness rather than React-specific patterns. Its peer dependencies are eslint-plugin-import, eslint-plugin-n, and eslint-plugin-promise .
Google focuses on readability and clarity for large codebases. It has fewer dependencies than Airbnb and does not include React-specific rules .
TypeScript-ESLint provides a tiered set of configs. The recommended config is the base, the recommended-type-checked config adds rules that require type information, the strict config adds more opinionated rules, and the stylistic config adds rules about code patterns that do not affect program logic . The recommended config also disables core ESLint rules that conflict with the TypeScript rules .
The choice between these configs is a decision about strictness and framework. A React project that wants a comprehensive rule set starts with Airbnb. A Node.js project that wants minimal rules starts with Standard. A TypeScript project starts with the TypeScript-ESLint recommended config and adds stylistic if the team wants the additional pattern rules.
Complete Example Session
// ============================================
// PART 1: THE SHAREABLE CONFIG PACKAGE
// ============================================
// index.js
export default [
{
rules: {
semi: [2, "always"],
quotes: [2, "single"],
},
},
];
// ============================================
// PART 2: THE PACKAGE.JSON
// ============================================
{
"name": "eslint-config-myconfig",
"main": "index.js",
"peerDependencies": {
"eslint": ">= 9"
},
"keywords": ["eslint", "eslintconfig"]
}
// ============================================
// PART 3: THE PROJECT CONFIG
// ============================================
// eslint.config.js
import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
export default defineConfig([
{
files: ["**/*.js"],
extends: [myconfig],
},
]);
// ============================================
// PART 4: THE OVERRIDE
// ============================================
import { defineConfig } from "eslint/config";
import myconfig from "eslint-config-myconfig";
export default defineConfig([
{
files: ["**/*.js"],
extends: [myconfig],
rules: {
"no-unused-vars": "warn",
},
},
]);
# ============================================
# PART 5: THE AIRBNB INSTALL
# ============================================
npm install --save-dev eslint-config-airbnb eslint-plugin-react eslint-plugin-import eslint-plugin-jsx-a11y
# ============================================
# PART 6: THE STANDARD INSTALL
# ============================================
npm install --save-dev eslint-config-standard eslint-plugin-import eslint-plugin-n eslint-plugin-promise
// ============================================
// PART 7: THE TYPESCRIPT-ESLINT CONFIG
// ============================================
import tseslint from "typescript-eslint";
export default defineConfig([
{
files: ["**/*.ts"],
extends: [tseslint.configs.recommended],
},
]);
// ============================================
// PART 8: THE STRICT TIER
// ============================================
import tseslint from "typescript-eslint";
export default defineConfig([
{
files: ["**/*.ts"],
extends: [tseslint.configs.strict],
},
]);
// ============================================
// PART 9: THE TYPE-CHECKED TIER
// ============================================
import tseslint from "typescript-eslint";
export default defineConfig([
{
files: ["**/*.ts"],
extends: [tseslint.configs.recommendedTypeChecked],
},
]);
// ============================================
// PART 10: THE DECISION
// ============================================
// React + strict → airbnb
// Minimal Node → standard
// TypeScript → typescript-eslint recommended + stylistic
The ten parts covered the shareable config package, the package.json, the project config, the override, the Airbnb install, the Standard install, the TypeScript-ESLint config, the strict tier, the type-checked tier, and the decision.
Quick Reference
Shareable config package
| Item | Value |
|---|---|
| Naming convention | eslint-config-<name> or @scope/eslint-config |
| Entry point | index.js |
| Export | Config object or array |
| ESLint dependency | peerDependencies with >= |
| Plugin dependencies | dependencies |
| Keywords | eslint, eslintconfig |
The extends mechanism
| Location | Syntax |
|---|---|
| Flat config | extends: [config] inside an object |
| Scoped to files | files key on the same object |
| Override | rules after extends |
CLI --config | Not supported for shareable configs |
Community configs
| Config | Style | Peer dependencies |
|---|---|---|
| Airbnb | Strict, semicolons, React | eslint-plugin-react, import, jsx-a11y |
| Standard | No semicolons, minimalist | eslint-plugin-import, n, promise |
| Readability-focused | Few | |
| TypeScript-ESLint | Tiered (recommended, strict, stylistic) | typescript-eslint |
TypeScript-ESLint tiers
| Config | Includes |
|---|---|
recommended | Correctness rules, disables conflicting core rules |
recommendedTypeChecked | Recommended + type-aware rules |
strict | Recommended + more opinionated rules |
stylistic | Pattern rules, no logic impact |
Best Practices
✅ Do This:
// Use extends inside a scoped object
{ files: ["**/*.js"], extends: [myconfig] } // ✅
// Declare ESLint as a peer dependency
{ "peerDependencies": { "eslint": ">= 9" } } // ✅
# Install the peer dependencies the config requires
npm install --save-dev eslint-config-airbnb eslint-plugin-react // ✅
// Override the specific rules the team disagrees with
{ extends: [myconfig], rules: { "no-console": "off" } } // ✅
❌ Don’t Do This:
// Import the config but do not apply it
import myconfig from "eslint-config-myconfig" // ❌ (not extended)
# Use the CLI --config flag for a shareable config
eslint --config eslint-config-myconfig // ❌
// Put the plugins in peerDependencies when the config requires them
{ "peerDependencies": { "eslint-plugin-react": "*" } } // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Config does not apply | Imported but not extended | Add extends: [config] |
| Plugin not found | Peer dependency not installed | Install the plugin |
| ESLint version mismatch | The config’s peer dependency is narrower | Check the config’s peerDependencies |
| Overrides not applied | The override object comes before the extends | Put the override after the extends |
CLI --config fails | Shareable configs are not supported by the flag | Use the flat config file |
Real-World Examples
1. The package export
export default [{ rules: { semi: [2, "always"] } }]
2. The peer dependency
{ "peerDependencies": { "eslint": ">= 9" } }
3. The extends
{ files: ["**/*.js"], extends: [myconfig] }
4. The override
{ extends: [myconfig], rules: { "no-console": "off" } }
5. Airbnb install
npm install --save-dev eslint-config-airbnb eslint-plugin-react
6. Standard install
npm install --save-dev eslint-config-standard eslint-plugin-import
7. TypeScript-ESLint recommended
extends: [tseslint.configs.recommended]
8. TypeScript-ESLint strict
extends: [tseslint.configs.strict]
9. Type-checked tier
extends: [tseslint.configs.recommendedTypeChecked]
10. The decision
React strict → airbnb; minimal → standard; TypeScript → tseslint
Visual
The shareable config package
┌─────────────────────────────────────────────────────────────┐
│ eslint-config-myconfig │
│ ├── index.js ← exports the config │
│ ├── package.json ← peerDependencies: eslint │
│ └── dependencies ← plugins the config needs │
└─────────────────────────────────────────────────────────────┘
The extends flow
┌─────────────────────────────────────────────────────────────┐
│ eslint.config.js │
│ import myconfig from "eslint-config-myconfig" │
│ │ │
│ ▼ │
│ { files: ["**/*.js"], extends: [myconfig] } │
│ │ │
│ ▼ │
│ The config's rules are applied to matching files. │
│ The project's rules override after the extends. │
└─────────────────────────────────────────────────────────────┘
The community configs
┌─────────────────────────────────────────────────────────────┐
│ Airbnb → strict, semicolons, React │
│ Standard → no semicolons, minimalist │
│ Google → readability, large codebases │
│ tseslint → recommended → strict → stylistic │
└─────────────────────────────────────────────────────────────┘
The TypeScript-ESLint tiers
┌─────────────────────────────────────────────────────────────┐
│ recommended │
│ └── recommendedTypeChecked (adds type-aware rules) │
│ └── strict (adds opinionated rules) │
│ └── strictTypeChecked (adds type-aware strict)│
│ │
│ stylistic (adds pattern rules, independent of the tiers) │
└─────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Shareable config | npm package exporting a config object or array |
| Naming | eslint-config-<name> or @scope/eslint-config |
| ESLint dependency | peerDependencies with >= |
| Plugin dependency | dependencies |
| Application | extends: [config] in the flat config |
CLI --config | Not supported for shareable configs |
| Airbnb | Strict, React, many peer dependencies |
| Standard | Minimalist, no semicolons |
| TypeScript-ESLint | Tiered: recommended, strict, stylistic |
Key takeaways:
- A shareable config is an npm package that exports a config object or array. The naming convention (
eslint-config-or@scope/eslint-config) makes it discoverable, but the export is what matters. The package is imported ineslint.config.jsand applied with theextendskey . - The peer dependency declares the ESLint version. The config does not bundle ESLint; it expects the project to provide it. The
>=range inpeerDependenciesis the supported version contract. The plugins and parsers that the config needs are independencies, because they are implementation details . - The community rule sets are a decision about strictness and framework. Airbnb is the strictest and the most React-oriented. Standard is the minimalist JavaScript option. Google is the readability-focused option. The TypeScript-ESLint tiers are the base for any TypeScript project, with
recommendedas the starting point andstrictandstylisticas the additional layers . - The override is the escape hatch. A project that extends a config and disagrees with a specific rule adds the rule to the
rulesobject after theextends. The override order is the array order, and the project’s rule wins for the files it matches . - The CLI
--configflag does not work with shareable configs. The flag is for a local configuration file. The shareable config is applied through theextendskey in the flat config file .
Remember: A shareable config is a community’s answer to the style debate. Extending one replaces the debate with a dependency, and the dependency comes with a maintenance contract: the config’s authors update it, the project bumps the version, and the rules evolve. The naming convention makes it discoverable, the peer dependency declares the ESLint version, and the extends key applies it. The override is the project’s way to disagree with a specific rule without abandoning the config. And the CLI --config flag is the one place where a shareable config does not work.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!