Biome: One Tool to Lint and Format Your JavaScript
A small shop's checkout script starts as twenty lines in one file, then three developers edit it. One prefers single quotes, another double quotes. One writes two-space indents, another tabs, and a third leaves a half-finished discount variable behind after a refactor. Nothing is broken: the script runs and the totals are right. But every pull request now carries an argument about style, and real problems, like that unused variable, hide in the noise. Two tools usually police this: a linter for mistakes and a formatter for style, each with its own config. Biome folds both jobs into one binary, and this post puts that claim to the test on a real file.
What I would check before using it
My judgement is that Biome is worth trying once more than one person touches the JavaScript, because that is when style arguments start costing review time. First, I would check whether one tool can cover the rules you rely on. Biome ships with a linter and a formatter in one package, so there is one install and one config, and the two never fight each other the way tools sometimes do. That is the pitch, and it holds up as long as Biome's rules cover what your team needs.
The second check is speed. Biome is written in Rust and checks a project in milliseconds, which matters where a slow linter gets skipped entirely. The third check is the defaults. Biome is opinionated: double quotes, tabs, semicolons, and a trailing comma style of its own. You can change most of these in biome.json, but every override is a decision the team has to agree on, which is the argument you were trying to avoid.
The fourth check is the ecosystem. Biome's plugin system is newer and smaller than ESLint's, so a rule from a niche ESLint plugin has no Biome equivalent, and teams with custom linting will feel that gap. The fifth check is migration. Moving an existing project means translating the old ESLint and Prettier settings, and Biome ships a migrate command to help, but a big config still takes an afternoon of checking diffs.
The verdict: use Biome for a new JavaScript or TypeScript project, or a team tired of keeping two tools in sync. That flips if the project depends on ESLint plugins Biome cannot replace, or the team has a house style Biome fights against. Then the single tool saves less than the migration costs.
A messy checkout script, cleaned end to end
The example is the shop script from the opening. It prices a small order of mugs, a tote, and a lamp, written the way real code gets written in a hurry: mixed quotes, uneven indentation, a missing space around an equals sign, and a discount variable started and never used. Here is the file before Biome touched it:
const prices = {"mug": 18.00, 'tote': 24.50, "lamp": 42.00};
function total(items) {
let sum=0;
const unusedDiscount = 0.1;
for (const item of items) {
sum += prices[item] * 1;
}
return sum;
}
const order = ["mug", 'tote', "mug"];
console.log("Order total: $" + total(order));
console.log('Items: ' + order.length);
Running npx biome check cart.js gave diagnostics that read like a code review. It flagged the unused variable first:
cart.js:5:11 lint/correctness/noUnusedVariables FIXABLE ! This variable unusedDiscount is unused.
Then it flagged both lines that build strings with +, suggesting template literals instead:
cart.js:13:13 lint/style/useTemplate FIXABLE i Template literals are preferred over string concatenation.
It also showed the formatting diff: double quotes everywhere, tabs for indentation, spaces around =, and quoted keys dropped from the prices object. The summary was "Found 1 error. Found 1 warning. Found 2 infos.", and the command exited with code 1. The formatting diff alone counts as an error, so biome check fails even when nothing is broken, which is what makes it useful as a build gate.
Before fixing anything, I ran the script: node cart.js printed "Order total: $60.5" and "Items: 3". Two mugs at 18 plus one tote at 24.50 is 60.50, so the maths was right and the mess was only style and dead code. Then I ran npx biome check --write cart.js, and this is where the tidy story breaks. The output said "Skipped 3 suggested fixes" and "Fixed 1 file.", and the fixed file had formatting, double quotes, and tabs:
const prices = { mug: 18.0, tote: 24.5, lamp: 42.0 };
function total(items) {
let sum = 0;
const unusedDiscount = 0.1;
for (const item of items) {
sum += prices[item] * 1;
}
return sum;
}
const order = ["mug", "tote", "mug"];
console.log("Order total: $" + total(order));
console.log("Items: " + order.length);
The formatting is fixed, but the unused variable is still there, and so is the string concatenation. Those three fixes are marked unsafe, because removing a variable or rewriting a string could change behaviour, so Biome leaves them for a human. Running it again gave the same output, "Order total: $60.5" and "Items: 3", which is the proof the safe fix changed nothing. A re-check confirmed the state: "Checked 1 file in 5ms. No fixes applied. Found 1 warning. Found 2 infos."
Now the part the tidy tutorials skip: something goes wrong. Wanting single quotes, I added a biome.json with "quoteStyle": "single" under the formatter section, and Biome refused it:
biome.json:6:5 deserialize × Found an unknown key `quoteStyle`.
In Biome 2, that key lives under javascript.formatter, not the top level formatter, so the fix was to move it there. With the corrected config, biome format --write rewrote "hello" to 'hello' at once, which confirmed the setting was finally being read. The lesson is small but practical: a config key in the wrong section is not ignored, it is an error, and the error names the key and lists the ones allowed.
Common mistakes and how to fix them
1. Expecting check --write to fix everything. Safe fixes are applied, but unsafe ones are skipped, and the output says so: "Skipped 3 suggested fixes." The fix is biome check --write --unsafe when you accept the risk, or to fix the flagged lines by hand, which is safer.
2. Putting quoteStyle in the wrong part of biome.json. The error is Found an unknown key 'quoteStyle'. The fix is to put it under "javascript": { "formatter": { "quoteStyle": "single" } }, because quote style is language-specific in Biome 2, not a top level formatter option.
3. Running biome format without --write and expecting the file to change. The command prints the diff, exits with code 1, and leaves the file as it was. The fix is biome format --write to change files in place, or biome check in a build step so a badly formatted file fails it.
4. Trying to format a file with a syntax error. A file containing const x = ; fails with "Expected an expression, or an assignment but instead found ';'." and then "Code formatting aborted due to parsing errors." Fix the syntax first, then run the formatter.
Where this leaves you
Biome does what it promises on a real file: one command found the dead variable, the style drift, and the string concatenation, then fixed the formatting safely and left the risky changes for a human. The config mistake cost a few minutes, but Biome's error pointed straight at the wrong key. For a new project, or a team that wants one tool instead of two, it is an easy yes. The next step is to run biome check on one file in your own project and read what it finds. If the diagnostics feel like a useful review rather than noise, adopt it for the whole project, and delete the second config file.
Comments
Post a Comment