ESLint and Prettier have been the standard pairing for JavaScript and TypeScript tooling for years. They work, broadly. But they come with a configuration tax that most projects end up paying repeatedly: separate config files, version conflicts between ESLint plugins and Prettier, the eternal argument about whether Prettier’s formatting opinions are the ones you actually want, and a combined startup time that makes pre-commit hooks noticeably slow on larger codebases.
Biome is the “what if there was just one tool” answer to this. It’s a Rust-based formatter and linter that handles both jobs with a single binary, a single configuration file, and startup times measured in milliseconds rather than seconds.
What Biome Actually Does
Biome formats JavaScript, TypeScript, JSX, TSX, JSON, and CSS with Prettier-compatible output for most cases. It lints with a rule set that covers a meaningful chunk of ESLint’s core and the most popular plugins — accessibility rules (jsx-a11y), React hooks rules, TypeScript-aware rules, import ordering. The rule set isn’t as comprehensive as the full ESLint ecosystem, but it covers what most projects actually have enabled.
The key numbers: Biome formats and lints a large TypeScript codebase in under a second where ESLint plus Prettier typically takes five to fifteen seconds. For pre-commit hooks, this is the difference between hooks that run so fast you don’t notice them and hooks that people start skipping with --no-verify.
Installing it is one step:
npm install --save-dev --save-exact @biomejs/biome
Then initialise:
npx @biomejs/biome init
This creates a biome.json with sensible defaults. Format your project:
npx @biomejs/biome format --write .
Lint with automatic fixes:
npx @biomejs/biome lint --write .
Or do both in one pass:
npx @biomejs/biome check --write .
That’s the whole CLI surface. Compare this to maintaining an .eslintrc.js, a .prettierrc, .eslintignore, .prettierignore, and the various plugin configurations they require.
How It Compares to Prettier
Biome’s formatter is intentionally Prettier-compatible in behaviour — it was designed to produce the same output as Prettier for the vast majority of code, which makes migrating an existing project much less painful. You’re not going to get a 10,000-line diff from switching the formatter.
The places where Biome and Prettier diverge are mostly edge cases: unusual JSX patterns, some complex destructuring, specific generic syntax in TypeScript. For most projects, the output is identical. Biome’s documentation maintains a compatibility status page for the cases where they differ.
One genuine difference: Biome is opinionated and not very configurable on formatting. Prettier is also opinionated, but it has more formatting options than Biome currently exposes. If your team has strong preferences about specific formatting behaviours that Prettier satisfies and Biome doesn’t, that’s worth checking before migrating.
How It Compares to ESLint
This is where it gets more nuanced. Biome’s lint rule set is growing but not complete. If you’re using a niche ESLint plugin specific to your framework or environment — GraphQL, testing library, Storybook, security-focused plugins like eslint-plugin-no-unsanitized — Biome probably doesn’t have those rules. The question is whether the rules you’re actually running and acting on are covered.
A practical approach: look at your current ESLint config, list the rules you have enabled, and check the Biome rule compatibility table. For most standard TypeScript React projects, coverage is solid. For projects with heavy plugin dependencies, you may end up running Biome for formatting and keeping ESLint for the plugins it doesn’t yet replace.
Biome does some things ESLint can’t easily do: because the formatter and linter share the same AST, Biome can suggest fixes that require coordination between formatting and semantic analysis. And the rule suggestions are fast enough that you can run them on every keystroke in the editor rather than waiting for a save.
VS Code Integration
The Biome VS Code extension gives you format-on-save and real-time lint feedback in the editor. Set it up by installing the extension and adding this to your workspace settings:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
If you’re migrating from Prettier, set "prettier.enable": false in your workspace settings to prevent the two from fighting over format-on-save.
Is the Migration Worth It?
For new projects: yes, start with Biome. The setup is simpler, the speed is noticeably better, and you’re not accumulating configuration debt from the start. There’s no reason to reach for the Prettier + ESLint combination when starting fresh in 2026.
For existing projects: it depends on how much of ESLint’s extended rule set you’re actually using. If you’re running eslint:recommended plus a few TypeScript and React rules, migration is probably a few hours of work and a CI check to verify nothing changed in unexpected ways. If you have a complex ESLint setup with fifteen plugins and custom rules, migration is a bigger undertaking.
The migration path is: run biome migrate eslint and biome migrate prettier (both commands exist and work reasonably well), review the rules that didn’t map across, decide whether to drop them or keep ESLint in parallel for those specific checks. For most teams, the result is a meaningfully simpler toolchain and noticeably faster development feedback.
There’s something satisfying about tools that do less than you expect until you actually need them, and then do exactly what you need. Biome is that kind of tool.