WebTech1223411 logo WebTech1223411Web tech, read closely
Dev Tools

How to Set Up Prettier and ESLint So They Stop Fighting

You save a file, Prettier adds a trailing comma, ESLint underlines it in red, you run the ESLint fixer, it removes the comma, and on the next save Prettier puts it straight back.

A code editor showing a JavaScript file with lint warnings cleared after formatting

You save a file, Prettier adds a trailing comma, ESLint underlines it in red, you run the ESLint fixer, it removes the comma, and on the next save Prettier puts it straight back. Most teams hit this loop within a week of setting up Prettier and ESLint together, and many give up by disabling one of them. That is a shame, because the two tools are built to work side by side once each is given a clear job.

I have set this up on about a dozen projects, from a small marketing site to a monorepo with forty packages. The fix is the same every time: Prettier owns formatting, ESLint owns code quality, and nothing overlaps. Here is how to get there and keep it that way.

Why Prettier and ESLint Fight in the First Place

ESLint started life doing two jobs. It caught real bugs, such as unused variables or a missing await, and it enforced style rules, such as quote style, semicolons and indentation. Prettier arrived later and does only the second job, but does it far more thoroughly by reprinting your whole file from scratch.

When both tools have opinions about style, they disagree. A shared config like the popular Airbnb or Standard presets turns on dozens of formatting rules in ESLint. Prettier then rewrites the file in its own style, and ESLint reports every difference as an error. Neither tool is wrong. They simply both think they are in charge of the same thing.

Give Each Tool One Job

The cleanest split looks like this:

ConcernOwned byExamples
Whitespace and line breaksPrettierIndentation, line length, wrapping long calls
Punctuation stylePrettierQuotes, semicolons, trailing commas
Likely bugsESLintUnused variables, unreachable code, missing await
Code patternsESLintNo var, prefer const, React hook rules
Import orderEither, but pick oneSorted or grouped imports

Import sorting is the one grey area. A Prettier plugin or an ESLint rule can both do it. Choose one and make sure the other is not configured to touch imports.

A Setup That Works in Five Steps

  1. Install Prettier as a project dependency, not just as an editor extension. Pin the exact version, because even minor releases occasionally change output, and you want every machine and the CI server to format identically.
  2. Add a small Prettier config file. Set only the options you genuinely care about, usually print width, single or double quotes, and trailing commas. Every option you leave at the default is one fewer thing to argue about.
  3. Add eslint-config-prettier as the last entry in your ESLint config. It switches off every ESLint rule that conflicts with Prettier. It must come last so nothing turns those rules back on after it.
  4. Skip eslint-plugin-prettier unless you have a good reason. It runs Prettier inside ESLint and reports formatting as lint errors, which is slower and fills your editor with red squiggles for things Prettier would have fixed silently.
  5. Run them separately in scripts: one script to check formatting with Prettier, one to lint with ESLint. In CI, run both and fail the build if either fails.

After this, run Prettier across the whole codebase once in a single commit with a clear message. Put that commit's hash in a blame ignore file so git blame skips over it and still shows who really wrote each line.

The Advice I Disagree With

Many tutorials still recommend eslint-plugin-prettier as the standard way to combine the tools. The Prettier team's own documentation has moved away from recommending it, and in my experience the plugin causes more problems than it solves. On a large file it can make linting several times slower, and it mixes two very different kinds of feedback. A formatting difference is not a bug, and showing it in the same red as an unhandled promise trains people to ignore the red.

I also disagree with the common advice to format on every keystroke or on a short auto-save delay. Format on save is enough. Formatting while you type causes the cursor to jump as lines reflow, and it can fight with the editor's own auto-closing of brackets.

Editor Settings That Prevent Surprises

Most conflicts that survive the setup above come from the editor, not the config. Check these in VS Code or your editor of choice:

  • Set Prettier as the default formatter for JavaScript, TypeScript, CSS and JSON, so the built-in formatter does not run instead.
  • Turn off any separate ESLint auto-fix on save for style rules. Let ESLint fix only quality issues, or run its fixer by hand.
  • Make sure the editor uses the project's Prettier, not a globally installed one. A global version that differs by one release can produce different output.
  • Commit an editor config file for line endings and final newlines, so Windows and macOS contributors do not produce noisy diffs.

Catching Problems Before They Reach the Main Branch

A pre-commit hook that runs Prettier and ESLint only on staged files keeps every commit clean without slowing anyone down. Tools like lint-staged handle the "only staged files" part, so a commit touching two files takes a second, not a full project lint.

Keep the CI check as the real gatekeeper, though. Hooks can be skipped, and new contributors sometimes clone without them installed. When something does slip through and breaks a build days later, git bisect can find the commit that broke your build far faster than reading through history by hand.

One more practical point: if your build pipeline minifies code, formatting has no effect on the output at all. What developers see in the browser while debugging depends on source maps, which we cover in why source maps matter.

Frequently Asked Questions

Do I still need ESLint if I use Prettier?

Yes. Prettier never looks at what your code does, only how it is laid out. ESLint catches unused variables, unsafe patterns and framework mistakes that Prettier ignores completely.

Does this setup work with TypeScript?

Yes. Add the TypeScript ESLint parser and its recommended rules, then keep eslint-config-prettier last. Prettier supports TypeScript out of the box.

What about Biome or other all-in-one tools?

Tools that combine formatting and linting avoid the conflict entirely and run much faster. They are a good choice for new projects, but they do not yet cover every ESLint plugin, so check your framework's rules first.

The Short Version to Apply Today

Open your ESLint config, add eslint-config-prettier as the last entry, remove eslint-plugin-prettier if it is there, and set Prettier as the default formatter in your editor. That fixes the save loop on most projects in under ten minutes. For more practical tooling guides, browse our dev tools section.

KO
Kofi Oosterhuis

Kofi spent years keeping APIs and game servers alive through traffic spikes and the occasional bad deploy. He covers back-end design, scaling and networking, with a preference for boring systems that do not page anyone at night.

More posts by Kofi

More in Dev Tools

01doorganico 084goad 3hot8 4465456 after5internprogram ahandfulofblessings ahmadpc ahomcybersecurity allodialresources annodex antiquesandperiodcollectibles aotc asianworldkashmir beedlectrics bloggertemplatefree bluefeatheragency bodyweightsolution campaign08blog carfixadvisor catstreetcollective cbstvsports cnfanspurchasing committeeof500yearsofdignityandresistance covertopsdjs cs-kaiyuangame cuestacomunicaciontotal cxoutlet dancebetgame deskgearhub destinyvillastay detectmagazine di33 diamondsteelbuildings donmo dyanadropship emarsysfinance emimattl escapechan eskitarih evautoplay everythingweddings-orlando farmzone feedviewerapp foxstudiosscratch gamevui123 gleasongrade greetingsday hacklabasu haskell iw-kaiyun jagoanproperti jilidskripsi joltbusinessfinance juegodepokergratis juegospucca kaeru-festival latestmehndidesigns lestanzediottaviano litemagazines localcommunityhero lustrsazan mariashebets menswheels newwebstechs1 nikkit ootheday oxigenvpn plurfitness prefetial probudgetcarpetcleaning psychicmrsmartin pyaten qvantor rejoignezlogis rexzbot riselayouts ruchin rwxqsgd5 sakaltime shibiaowang shop-bot skrtips strcoding tetapatrium topselller uneplanteartificielle vipertechcr wo-kygaming yamaha-mekar yeknava yoybuysheets zenunwa yamaha-mekar jilidskripsi ankertoto ankertoto ankertoto ankertoto