eslint-config-nick2bad4u
Shared ESM-only ESLint flat config for Nick2bad4u TypeScript/JavaScript repositories.
This package centralizes the lint stack used across those repositories: TypeScript-aware
ESLint configuration, Markdown/JSON/YAML/TOML/CSS-adjacent linting, package
checks, prose checks, and project-specific plugin presets. Consumers bring
eslint and typescript as peer dependencies; this package brings the ESLint
plugins and parsers that the shared config enables.
Requirements
| Tool | Supported range | Why it is required |
|---|---|---|
| Node.js | ^22.22.3 || ^24.16.0 || >=26.3.0 |
Runtime for ESLint, the config package, and repository scripts. |
| ESLint | ^10.0.0 |
Peer dependency supplied by each consuming project. |
| TypeScript | ^5.0.0 || ^6.0.3 |
Peer dependency used by TypeScript-aware lint rules. |
Repository development also expects npm >=11.0.0; consumers can use the package
with whatever package manager their project supports.
Install
npm install --save-dev eslint-config-nick2bad4u eslint typescript
Keep eslint and typescript installed in the consuming project to keep peer
dependency resolution explicit and predictable.
Quick start
Create eslint.config.mjs in the consuming project:
import nick2bad4u from "eslint-config-nick2bad4u";
export default [...nick2bad4u.configs.all];
The spread is intentional. Every preset is an ESLint flat-config array, so spreading it lets you append local overrides without replacing the shared config:
import nick2bad4u from "eslint-config-nick2bad4u";
export default [
...nick2bad4u.configs.all,
{
name: "Local overrides",
rules: {
"no-console": "off",
},
},
];
If you prefer named imports, use presets:
import { presets } from "eslint-config-nick2bad4u";
export default [...presets.all];
For migration steps from an existing handwritten config, see the migration guide.
Documentation
Long-form project documentation lives in docs/.
| Guide | Use it for |
|---|---|
| Configuration | createConfig(), presets, plugin replacement, and environment variables. |
| Migration | Moving a project from a handwritten flat config to this package. |
| Contributing | Local development workflow and pull request expectations. |
| Maintainer guide | Rule, preset, dependency, and release maintenance. |
| Support | Issue triage and reproduction details. |
| Security | Private vulnerability reporting. |
| Code of conduct | Participation standards for the project. |
Configuration
Use createConfig() when a project needs to customize root resolution, import
resolver project paths, or plugin replacement/disabling while keeping the shared
defaults:
import {
allowDefaultProjectFilePatternPresets,
createConfig,
} from "eslint-config-nick2bad4u";
export default createConfig({
allowDefaultProjectFilePatterns:
allowDefaultProjectFilePatternPresets.rootScriptFiles,
rootDirectory: import.meta.dirname,
});
| Option | Type | Default | Use it when |
|---|---|---|---|
allowDefaultProjectFilePatterns |
readonly string[] |
Root JS/CJS/MJS globs | Root config files are intentionally outside the nearest tsconfig.json; keep this list tiny and avoid broad globs. |
rootDirectory |
string |
process.cwd() |
ESLint runs outside the project root or a monorepo package needs its own root. |
tsconfigPaths |
readonly string[] |
["./tsconfig.eslint.json"] |
Import resolver project paths; this does not replace TypeScript parser project-service discovery of tsconfig.json. |
plugins |
Readonly<Record<string, unknown>> |
{} |
You need to dogfood a local plugin build or disable packaged plugin rules by namespace. |
An example copy-paste config is available at
examples/eslint.config.create.mjs.
Detailed configuration examples live in the
configuration guide.
Available presets
All presets are available from the default export as nick2bad4u.configs.* and
from the named presets export.
| Preset | Purpose |
|---|---|
all |
Full shared config, including packaged Typefest and Etc-Misc source-rule sections. |
recommended |
Alias for all; provided for familiar preset naming. |
base |
Shared config without explicit source-rule plugin sections. |
withoutActionlint |
Full shared config without Actionlint rules. |
withoutCopilot |
Full shared config without Copilot rules. |
withoutDocusaurus2 |
Full shared config without Docusaurus 2 plugin rules. |
withoutEtcMisc |
Full shared config without the Etc-Misc source-rule section. |
withoutFileProgress2 |
Full shared config without File Progress 2 rules. |
withoutGitHubActions2 |
Full shared config without GitHub Actions 2 rules. |
withoutGithubActions2 |
Deprecated alias for withoutGitHubActions2. |
withoutImmutable2 |
Full shared config without Immutable 2 rules. |
withoutRemark |
Full shared config without Remark plugin rules. |
withoutRepo |
Full shared config without Repo plugin rules. |
withoutRuntimeCleanup |
Full shared config without Runtime Cleanup plugin rules. |
withoutSdl2 |
Full shared config without SDL 2 rules. |
withoutSecretlint |
Full shared config without Secretlint plugin rules. |
withoutStylelint2 |
Full shared config without Stylelint 2 rules. |
withoutTestSignal |
Full shared config without Test Signal plugin rules. |
withoutTombi |
Full shared config without Tombi plugin rules. |
withoutTsconfig |
Full shared config without tsconfig-validation rules. |
withoutTsdocRequire2 |
Full shared config without TSDoc Require 2 rules. |
withoutTypedoc |
Full shared config without TypeDoc rules. |
withoutTypefest |
Full shared config without the Typefest source-rule section. |
withoutVite |
Full shared config without Vite plugin rules. |
withoutWriteGoodComments2 |
Full shared config without Write Good Comments 2 rules. |
withoutYamllint |
Full shared config without Yamllint plugin rules. |
Use a without* preset when a repository does not use that surface or when it
needs to provide a local build of that plugin for dogfooding.
TypeScript project setup
The TypeScript parser uses projectService, so typed linting follows
TypeScript's normal nearest-tsconfig.json lookup from rootDirectory or
process.cwd(). That tsconfig.json should include every TypeScript-aware file
ESLint can lint: source, tests, scripts, dotfiles, examples, and docs tooling.
{
"$schema": "https://www.schemastore.org/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noEmit": true
},
"exclude": ["node_modules/**", "dist/**", "coverage/**", ".cache/**"],
"include": ["**/*", "**/.*"]
}
If a repository keeps a separate tsconfig.eslint.json, that file can still be
useful for tsconfigPaths and import resolution, but it does not make the
parser project service pick that file instead of tsconfig.json. Put
lint-visible files in the nearest tsconfig.json, or opt the root
files into allowDefaultProjectFilePatterns. The shared default already covers
root-only js, mjs, and cjs files, including dotfiles.
Override the default when a project wants a different root-only fallback:
import {
allowDefaultProjectFilePatternPresets,
createConfig,
} from "eslint-config-nick2bad4u";
export default createConfig({
allowDefaultProjectFilePatterns:
allowDefaultProjectFilePatternPresets.rootConfigFiles,
rootDirectory: import.meta.dirname,
});
allowDefaultProjectFilePatternPresets.defaultRootFiles matches the packaged
default. rootScriptFiles adds ts, mts, and cts for projects that know
those root files are outside tsconfig.json; rootConfigFiles and
rootMjsFiles are also available for narrower projects.
The "**/.*" include matters because dotfiles such as .secretlintrc.cjs are
not matched by extension globs like **/*.cjs. Do not use broad
allowDefaultProjectFilePatterns as a replacement for a correct tsconfig.json;
each default-project match has parser-service overhead.
Set ESLINT_CONFIG_ROOT only when you need to drive the root directory from the
environment instead of passing rootDirectory to createConfig().
Local plugin dogfooding
Use the matching without* preset, then append the local plugin registration.
For example, eslint-plugin-typefest checkout can use its local plugin build
without also enabling the packaged Typefest rules:
import nick2bad4u from "eslint-config-nick2bad4u";
import localTypefest from "./plugin.mjs";
export default [
...nick2bad4u.configs.withoutTypefest,
{
files: ["src/**/*.{ts,tsx,mts,cts}"],
name: "Local Typefest rules",
plugins: {
typefest: localTypefest,
},
rules: {
...localTypefest.configs.experimental.rules,
},
},
];
Use the same shape for other plugin namespaces, such as withoutCopilot,
withoutEtcMisc, or withoutWriteGoodComments2.
Optional behavior
JSON schema validation is enabled as part of the default config through
eslint-plugin-json-schema-validator-2. The validator caches schema lookups, so
normal lint runs do not repeatedly fetch the same schema URLs.
Progress output
eslint-plugin-file-progress-2 is enabled by default. Control it with
ESLINT_PROGRESS:
| Value | Behavior |
|---|---|
unset or on |
Show progress and file names. |
nofile |
Show progress without file names. |
off, 0, or false |
Disable progress output. |
Development checks
Use the aggregate scripts before opening a pull request or publishing:
npm run lint:all
npm run lint:actions
npm run release:verify
lint:all builds the runtime, runs ESLint, typechecks, runs Vitest, checks
Prettier formatting, validates package metadata and published package shape,
runs Gitleaks, and runs Secretlint. ESLint covers YAML through the shared config;
use lint:yaml or lint:yamllint when you need a targeted YAML-only pass.
lint:actions runs actionlint against GitHub workflows. release:verify uses
the stricter no-cache lint path, repeats strict package checks with publint and
ATTW, and syncs peer ranges and Node version files.
Release notes are generated with git-cliff through the changelog:* scripts.
For contribution and maintenance workflows, see the
contributing guide and
maintainer guide. Historical wording diffs are
captured in diff notes.
Contributors
Nick2bad4u |
Snyk bot |
StepSecurity Bot |
dependabot[bot] |
github-actions[bot] |