Skip to content

Existing & legacy projects

Adopting a strict config in a greenfield project is easy. The hard case is the four-year-old codebase where npm run lint suddenly reports two thousand violations. If the only option is "fix everything before CI goes green," adoption never happens.

It doesn't have to be all-or-nothing.

The strategy: baseline, then ratchet

ESLint has a built-in mechanism for exactly this — bulk suppressions (ESLint ≥ 9.24). You record every existing violation as a baseline. From then on:

  • Existing violations are silenced, so CI is green immediately.
  • New violations (new code, or newly-introduced errors in files you touch) fail normally.
  • As you fix old violations, the baseline only ever shrinks. It's a one-way ratchet toward clean.
  install config ──▶ baseline existing issues ──▶ CI green today

                                ├─ new code held to the full standard
                                └─ old issues fixed gradually, at your pace

Step by step

  1. Install and configure the way any project would:

    bash
    npx eslint-config-mocg init
  2. Create the baseline. This writes eslint-suppressions.json capturing every current violation:

    bash
    npx eslint --suppress-all
  3. Commit eslint-suppressions.json. It is part of the repo. CI is now green: only new violations fail.

  4. Burn it down over time. After fixing some violations, prune the entries that no longer apply:

    bash
    npx eslint --prune-suppressions

    The file shrinks. When it's empty, you're fully on the standard — delete it.

Suppress one rule at a time

To adopt incrementally rule-by-rule instead of all at once, baseline a single rule:

bash
npx eslint --suppress-rule unicorn/prevent-abbreviations

Fixing in bulk with an agent

Because the baseline keeps CI green, the cleanup is no longer time-critical — which makes it a great fit for an automated pass. A practical loop:

  1. Pick a file or a rule from the suppressions file.
  2. Run npx eslint --fix to clear the autofixable violations.
  3. Have an agent (or a developer) resolve the rest, with the project's tests as the safety net — if the suds tests pass after the refactor, the change is sound.
  4. npx eslint --prune-suppressions and commit.

Repeat until eslint-suppressions.json is empty. Nothing about this is big-bang; each step is independently shippable.

Migrating from eslint-config-next

If a Next.js project already uses eslint-config-next, replace it — don't layer the two. eslint-config-next re-bundles its own eslint-plugin-react, eslint-plugin-react-hooks, and typescript-eslint, which would duplicate-register against this config's own copies and conflict with its tuning. The Next stack here uses @next/eslint-plugin-next directly and brings the React layer itself.

  1. Remove the old config and dependency:

    bash
    npm rm eslint-config-next
  2. Install and initialize (the wizard detects next and offers the Next stack):

    bash
    npx eslint-config-mocg init
  3. Your eslint.config.mjs becomes a single zero-config call — Next is auto-detected:

    js
    import { mocg } from 'eslint-config-mocg';
    
    export default mocg();

The Next stack already covers what eslint-config-next gave you (the @next/eslint-plugin-next Core Web Vitals rules, React, and hooks) plus this config's full strict baseline. Build artifacts (.next/, out/, next-env.d.ts) are ignored for you.

What about per-rule relaxation?

If a particular rule genuinely doesn't fit a project, relax it locally and visibly in that project's eslint.config.mjs — append a config block after mocg():

js
import { mocg } from 'eslint-config-mocg';

const config = await mocg();

export default [
  ...config,
  {
    name: 'local/overrides',
    rules: {
      // Deliberately relaxed for this repo — explain why.
      'unicorn/prevent-abbreviations': 'off',
    },
  },
];

Prefer suppressions for temporary debt and local overrides for permanent, intentional deviations. Keep both rare — the value of a shared config is that everyone runs the same rules.

Internal tooling — Master of Code Global