@homer0/eslint-plugin
v14.2.2
Published
My custom configurations for ESLint.
Readme
@homer0/eslint-plugin
My custom configurations for ESLint
Installation
pnpm add @homer0/eslint-plugin --save-dev
# or
npm install @homer0/eslint-plugin --save-devRequirements
| Package | Minimum Version and notes |
| ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| Node | >=20.19 |
| ESLint | >=9.39.1 - with flat config |
| TypeScript | >=5 - with ESM |
Usage
Import the plugin in your ESLint config, and add it to the extends list:
// eslint.config.js
import { defineConfig } from 'eslint/config';
import eslintPlugin from '@homer0/eslint-plugin';
export default defineConfig([
files: ['src/**/*.ts'],
extends: [
eslintPlugin.configs.node,
eslintPlugin.configs.esm,
],
]);Or, you can create a config with your desired presets:
// eslint.config.js
import { defineConfig } from 'eslint/config';
import { createConfig } from '@homer0/eslint-plugin/create';
export default defineConfig([
createConfig({
importUrl: import.meta.url, // to configure TS paths resolution
extends: ['node-ts-with-prettier'],
}),
]);Configurations
Originally, all configurations were based on Airbnb's base config, with some customizations on top of it. But now, since Airbnb hasn't published a flat config version yet (as of November 2025), I added an airbnb folder inside the project and copied their rules (except for the deprecated ones), in flat config format.
The airbnb folder is temporary (I think), as I eventually plan to review all the rules and create my own base config from scratch.
So, for now, my configs are still based on Airbnb's base rules, with some customization, minus the rules that are deprecated or moved to the stylistic plugin (as I leave all my formatting to Prettier).
Now, there are three main types of configurations:
- environment-specific: They are meant to be used as a base for your projects, like
nodeorbrowser. - feature-specific: They are meant to be added on top of those base configs, like
esm,jsdoc, and/ortesting. - combined: To cover the most common cases, these features combine both environment and features, like
node-ts, andnode-ts-testing.
Environment and combined configurations include a Prettier version with the suffix -with-prettier. They add the Prettier's config that takes care of disabling all the ESLint rules that may conflict with Prettier's formatting.
| Name | Type | Description | Prettier version |
| --------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| browser | environment | For browser-based projects; it's like the one for node, but with the browser globals and without the eslint-plugin-n. | ✅ |
| node | environment | For Node.js and the tooling outside browser-based projects. It uses the eslint-plugin-n's recommended config. | ✅ |
| node-ts | combined | For Node.js projects using TypeScript; it extends the node config and adds TypeScript support. | ✅ |
| node-ts-tests | combined | Extends node-ts and disables a few rules for acceptable scenarios in testing environments (like no-magic-numbers). | ✅ |
| tests | feature | It disables a few rules for acceptable scenarios in testing environments (like no-magic-numbers). | ❌ |
| esm | feature | For projects using ESM modules; it sets the sourceType to module and customizes a few rules accordingly (mostly around the eslint-plugin-import-x). Important: Don't use this config with a TypeScript based config, just leave the extensions validation to the TS compiler. | ❌ |
| ts | feature | For TypeScript projects; it adds TypeScript support on top of any other config. | ❌ |
| jsdoc | feature | For projects using JSDoc comments; it adds rules from the eslint-plugin-jsdoc. | ❌ |
Frameworks and libraries
Here are a few special configs and tools for specific frameworks and libraries I use.
Next.js
If you are working on a Next.js project, there's a custom export and config creator for it, but it requires you to install their config:
pnpm add eslint-config-next --save-dev
# or
npm install eslint-config-next --save-devThen, you can import the plugin in your config and use it like this:
// eslint.config.js
import { defineConfig } from 'eslint/config';
import eslintPlugin from '@homer0/eslint-plugin/nextjs';
export default defineConfig([
files: ['src/**/*.ts'],
extends: [
eslintPlugin.configs['nextjs-with-prettier'],
],
]);Yes, it has a Prettier version too!
Or, like with the other configs, you can use a config creator:
// eslint.config.js
import { defineConfig } from 'eslint/config';
import { createNextjsConfig } from '@homer0/eslint-plugin/nextjs/create';
export default defineConfig([
createNextjsConfig({
importUrl: import.meta.url, // to configure TS paths resolution
// These are the options and their default values:
prettier: true,
}),
]);React
If you are working with just React (no Next), there's also a custom export and config creator for it, and it also requires some plugins to be installed:
pnpm add eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y --save-dev
# or
npm install eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y --save-devBut different from the Next.js config, this is not a base config, so you'd have to use it on top of another config, like node-ts or browser.
// eslint.config.js
import { defineConfig } from 'eslint/config';
import plugin from '@homer0/eslint-plugin';
import reactPlugin from '@homer0/eslint-plugin/react';
export default defineConfig([
files: ['src/**/*.ts'],
extends: [
eslintPlugin.configs['node-with-prettier'],
reactPlugin.configs.react,
eslintPlugin.configs.esm.
],
]);Or, you can use the config creator:
// eslint.config.js
import { defineConfig } from 'eslint/config';
import { createReactConfig } from '@homer0/eslint-plugin/react/create';
export default defineConfig([
createReactConfig({
importUrl: import.meta.url, // to configure TS paths resolution
baseConfig: 'node', // 'node' | 'browser', default is 'node'
// These are the options and their default values:
esm: true,
jsdoc: false,
prettier: true,
tests: false,
ts: true,
}),
]);Config creator features
When using the config creators (like createConfig or createNextjsConfig), you get a few extra features besides the TS path resolution setup.
files: Files inclusion
While this option behaves similarly to ESLint's native files option, it has some extra capabilities to make your life easier. You can set the values to:
- A glob pattern string (like
src/**/*.ts). allto include all JS/TS files in your project (basically, it resolves to**/*.{js,jsx,the-rest}).all-inside:<path>to include all JS/TS files inside a specific folder (likeall-inside:srcresolves tosrc/**/*.{js,jsx,the-rest}).
And you can send an array of those values too.
Custom tsconfig.json
There are two options for working with custom tsconfig.json files:
tsConfigName: If yourtsconfig.jsonfile has a different name (liketsconfig.app.json), you can specify it here. Default istsconfig.json.tsConfigPath: If yourtsconfig.jsonfile is not in the root folder, you can specify its path here. Default is./(the root folder).
Those are two different options because you normally have either a custom name on the root, like tsconfig.production.json, or a custom path, like tests/tsconfig.json.
Extraneous dependencies
The no-extraneous-dependencies rule from eslint-plugin-import-x (and previously the original eslint-plugin-import) is very useful to avoid importing packages that are not listed in your package.json dependencies... but it's always a pain to configure properly, and when you are bundling, it's very common to just disable it altogether.
So, with the config creators, you can use the extraneousDependencies option to easily configure it according to your situation. The option is an object with the following keys:
devFiles: An array of glob patterns for files that are considered development files that are allowed to importdevDependencies. By default, it includes a big list, from the airbnb config, of all major JS/TS tools config files (likewebpack.config.js,jest.config.ts, etc).bundledDependencies: A list of packages paths that are bundled in your project's build process. For example, if you are bundlingurijsin your build, you can add it here, and the rule will allow importing it without listing it in yourdependencies.
ignoreUnresolved: Ignore unresolved imports
With the migration to ESM, and the use of custom path mappings in TypeScript, it's common to have some imports that ESLint can't resolve properly, even if they work fine at runtime or when compiled with TypeScript. To avoid having to manually override the import-x/no-unresolved, or turn it off completely, you can use the ignoreUnresolved option in the config creators, and it will automatically add those exceptions for you, while keeping the rule with the base configuration.
Ignore files
With the new flat config, .eslintignore files are not supported anymore, and you now need a workaround to load the patterns from those files into your config.
Built into the config creators is a feature that automatically loads .eslintignore and/or .gitignore patterns into your config, so you don't have to worry about it.
By default, the feature will crawl upwards from your config file location until it finds a .gitignore file and load all the patterns from all the .eslintignores it finds along the way, and the ones from the .gitignore file.
Note: It uses
.eslintignores(with ansat the end) as the default ignore file name, to avoid the "deprecated" warning from ESLint when it finds a.eslintignorefile.
The option is loadIgnoreFile, and it can be:
| Type | Description |
| -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| true | Load all the .eslintignore files it finds until it sees a .gitignore, and then load that too. This is the default behavior. |
| false | Disable the feature. |
| number | Specify how many levels upwards it should look for ignore files. |
| object | Customize the behavior with more options (see below). |
And if you use an object, here are the available options:
| Key | Type | Description |
| ------------------ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| limit | false \| number \| '.gitignore' | Defines the behavior for how many levels upwards it should look for ignore files. If false, it will only look in the directory of the config file. If '.gitignore', it will look until it finds a .gitignore file. Otherwise, it will look up to the specified number of levels. Default is '.gitignore'. |
| includeGitignore | boolean | Whether to include patterns from the .gitignore file when (and if) found. Default is true. |
| ignoreFileName | string | Optional. If you want to use a different ignore file name instead of .eslintignores, you can specify it here. |
Rules
Instead of listing the rules here, you can check all the files inside any rules directory outside airbnb (like src/rules/es6.ts or src/react/rules/style.ts) and you'll see all the customizations I made, with a comment explaining why I took that decision, and a link to the relevant documentation.
Contributing
No, thanks :)
