Most TypeScript projects still carry ESLint, Prettier, and a pile of plugins that overlap and occasionally fight each other. Biome replaces both with a single Rust binary. Same code gets linted and formatted; the wall-clock cost drops from seconds to milliseconds. My monorepo's pre-commit went from 18 seconds to under one.
This is a migration walkthrough from a real project that had the usual ESLint + Prettier + a dozen plugins setup, plus notes on the rough edges I hit.
What Biome Actually Is
Biome is a single tool that does:
- Formatting — Prettier-compatible output for JavaScript, TypeScript, JSX, JSON, CSS
- Linting — ~300 rules covering correctness, style, accessibility, and common TypeScript pitfalls
- Import sorting — without the
eslint-plugin-importconfig gymnastics
It is written in Rust, it is parallelized, and it parses each file once for lint and format. Benchmarks against eslint . --fix && prettier --write . show 20–30x speedups on medium codebases.
Install and Init
Terminal
pnpm add -D --save-exact @biomejs/biome
pnpm biome init
The init creates biome.json. For most projects, the default is a reasonable starting point.
biome.json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"files": { "ignoreUnknown": true },
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noNonNullAssertion": "off"
},
"correctness": {
"noUnusedVariables": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all",
"semicolons": "always"
}
}
}
Removing ESLint + Prettier
Mechanically, the cleanup is short. Delete the config files and uninstall the packages. The list usually looks something like:
Terminal
rm .eslintrc.* .prettierrc.* .prettierignore .eslintignore
pnpm remove \
eslint \
prettier \
eslint-config-prettier \
eslint-plugin-import \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-plugin-jsx-a11y \
@typescript-eslint/parser \
@typescript-eslint/eslint-plugin
Update your package.json scripts:
package.json
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write ."
}
}
The Rough Edges
A few things to know before you commit:
1. Not every ESLint rule has a Biome equivalent yet
The rule catalog is large but not 1:1. Rules from niche plugins (some framework-specific ones, some security plugins) may not exist in Biome. Before migrating, run biome migrate eslint — it parses your ESLint config and tells you which rules have direct equivalents and which do not.
2. Type-aware linting is limited
ESLint with @typescript-eslint can run rules that require TypeScript's type checker. Biome's type-aware rules are growing but are not yet a complete replacement. If you depend on rules like no-floating-promises that need type info, you may want to keep a minimal @typescript-eslint config alongside Biome for just those rules.
3. Plugin ecosystem is smaller
ESLint has a decade of community plugins. Biome is catching up, but if you rely on an obscure plugin, check first.
Pro Tip: Biome's
biome checkcommand runs lint + format in one pass — it is 2x faster than running them separately because the parse only happens once. Make it your default CI command and your local "fix-everything" script.
Pre-commit Integration
Lefthook or Husky both work. Here is the Lefthook config I use:
lefthook.yml
pre-commit:
parallel: true
commands:
biome:
glob: '*.{js,ts,jsx,tsx,json,css}'
run: pnpm biome check --write --no-errors-on-unmatched {staged_files}
stage_fixed: true
stage_fixed means fixes are automatically re-staged, so the commit that lands includes the formatting changes.
Editor Setup
The VS Code extension is biomejs.biome. Once installed, set it as the default formatter and enable format-on-save:
.vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
When to Wait
- Heavy reliance on type-aware rules — stay on ESLint for those, or run both tools (Biome for everything, ESLint for the type-checker rules only)
- Framework plugins you cannot replace — check the Biome rule catalog first
- Monorepo with shared ESLint config across many apps — migration is straightforward but not trivial; plan a couple of days
For everyone else, I'd suggest giving Biome a serious look. Faster CI, simpler config, one less tool to keep updated.
