Skip to content

Arend van Beelen jr.

2 posts by Arend van Beelen jr.

Biome v2.0 beta

After hard work from our team, Biome’s long-awaited 2.0 release is nearing completion. It will be packed with many large features, so we would like your help testing it with a public beta!

If you would like to try it out, you can update Biome and migrate your configuration using the following commands:

Terminal window
npm install --save-dev --save-exact @biomejs/biome@beta
npx @biomejs/biome@beta migrate

Also, make sure you use the prereleases of our IDE extensions. The stable versions of our extensions are not yet prepared for Biome 2.0!

Documentation for the upcoming release can be found at https://next.biomejs.dev/.

While the final 2.0 release may still have small changes in its final feature set, here’s what you can expect in the beta:

  • Plugins: You can write custom lint rules using GritQL.
  • Domains: Domains help to group lint rules by technology, framework, or well, domain. Thanks to domains, your default set of recommended lint rules will only include those that are relevant to your project.
  • Multi-file analysis: Lint rules can now apply analysis based on information from other files, enabling rules such as noImportCycles.
  • noFloatingPromises: Still a proof-of-concept, but our first type-aware lint rule is making an appearance.
  • Our Import Organizer has seen a major revamp.
  • Assists: Biome Assist can provide actions without diagnostics, such as sorting object keys.
  • Improved suppressions: Suppress a rule in an entire file using // biome-ignore-all, or suppress a range using // biome-ignore-start and // biome-ignore-end.
  • HTML formatter: Still in preview, this is the first time we ship an HTML formatter.
  • Many, many, fixes, new lint rules, and other improvements.

Biome 2.0 comes with our first iteration of Linter Plugins.

These plugins are still limited in scope: They allow for matching code snippets and reporting diagnostics on them.

Here is an example of a plugin that reports on all usages of Object.assign():

`$fn($args)` where {
$fn <: `Object.assign`,
register_diagnostic(
span = $fn,
message = "Prefer object spread instead of `Object.assign()`"
)
}

It’s a first step, but we have plenty of ideas for making them more powerful, and we’ll eagerly hear from our users on what they would like to see prioritised.

We’ve introduced a new linter feature: Domains.

Domains are a new way to organise lint rules by technology, framework, or well, domain. Right now, we have identified four domains:

  • next: Rules related to Next.js.
  • react: Rules related to React.
  • solid: Rules related to Solid.js.
  • test: Rules related to testing, regardless of framework or library.

You can enable and disable rules that belong to a domain together:

biome.jsonc
{
"linter": {
"domains": {
"test": "all", // all rules that belong to this domain are enabled
"react": "recommended", // only the recommended rules from this domain are enabled
"solid": "none" // rules related to Solid are disabled
}
}
}

But it gets better: Biome will automatically inspect your package.json and determine which domains should be enabled by default. For instance, if you have react defined as one of your dependencies, the default setting for the react domain automatically becomes recommended.

This way, Biome’s total set of recommended rules should be most relevant to your specific project needs.

And finally, domains can add global variables to the javascript.globals setting. This should make Biome even easier to setup.

Before version 2.0, Biome lint rules could only operate on one file at a time. This brought us far, but many of the more interesting rules require information from other files too.

To accomplish this, we have added a file scanner to Biome that scans all the files in your project and indexes them, similar to what an LSP service might do in your IDE. We’re not going to beat around the bush: Scanning projects means that Biome has become slower for many projects. But we do believe the ability to do multi-file analysis is worth it. And without a scanner, multi-file analysis would become even slower, as rules would need to perform ad-hoc file system access individually.

That said, this is a beta, and there are certainly more opportunities to improve our scanner and its performance. If you have a repository where you feel our performance became unacceptably slow, please reach out and file an issue.

For now, we have a few interesting rules that can make use of our multi-file analysis:

  • noImportCycles is able to look at import statements and detect cycles between them.
  • noPrivateImports is a new rule based on the useImportRestrictions nursery rule from Biome 1.x, and inspired by ESLint’s plugin-import-access. It forbids importing symbols with an @private JSDoc tag from other modules, and forbids importing symbols with an @package tag if the importing file is not in the same folder or one of its subfolders.
  • useImportExtensions has been improved because it can now determine the actual extension that needs to be used for an import, instead of guessing based on hueristics.

Finally, we’ve also designed the multi-file analysis with monorepos in mind. While full monorepo support may not make it in time for the 2.0 release, we expect to be able to deliver more on this front soon.

With Biome’s linter we have always strived to provide a battery-included approach to linting. This means we’re not just aiming to replace ESLint, but also its plugins. One of the hardest plugins to replace is typescript-eslint.

Biome has featured some rules from typescript-eslint for a while now, but we could never replace all rules, because they relied on type information for their analysis. And in order to get type information, typescript-eslint relies on tsc itself, which is rather slow and also complicates setup.

This is about to change. With Biome 2.0, we’re introducing a first version of the noFloatingPromises rule, one of the most-requested rules that relies on type information. In fairness, we should not consider it more than a proof-of-concept right now, because there are some notable limitations to its capabilities:

  • It doesn’t understand complex types yet.
  • It cannot do type inference yet.
  • It can currently only analyse types that occur in the same file.

Still, its capabilities are sufficient to catch some of the low-hanging fruit. Consider this small snippet:

example.js
async function returnsPromise() { /* ... */ }
returnsPromise().then(() => {});

It will trigger the following diagnostic:

example.js:3:1 lint/nursery/noFloatingPromises ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ A “floating” Promise was found, meaning it is not properly handled and could lead to ignored errors or unexpected behavior.
1 │ async function returnsPromise() { /* ... */ }
2 │
> 3 │ returnsPromise().then(() => {});
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 │
ℹ This happens when a Promise is not awaited, lacks a .catch or .then rejection handler, or is not explicitly ignored using the void operator.

As you can guess, we intend to expand this rule’s capabilities over time. And with our new multi-file analysis in place, we expect to be able to make serious strides with this. Stay tuned for more announcements on this front!

In Biome 1.x, our Import Organizer had several limitations:

  • Groups of imports or exports would be considered separate chunks, meaning they would be sorted independently. This meant the following didn’t work as expected:

    example.js
    import { lib2 } from "library2";
    import { util } from "./utils.js";
    import { lib1 } from "library1";

    It would correctly sort "library1" to be placed above "./utils.js", but it wouldn’t be able to carry it over the newline to the top. What we got was this:

    organizer_v1.js
    import { lib2 } from "library2";
    import { lib1 } from "library1";
    import { util } from "./utils.js";

    But instead, what we really wanted was this:

    organizer_v2.js
    import { lib1 } from "library1";
    import { lib2 } from "library2";
    import { util } from "./utils.js";
  • Separate imports from the same module wouldn’t be merged. Consider the following example:

    example.js
    import { util1 } from "./utils.js";
    import { util2 } from "./utils.js";

    Nothing would be done to merge these import statements, whereas what we would have wanted was this:

    organizer_v2.js
    import { util1, util2 } from "./utils.js";
  • No custom ordering could be configured. Maybe you didn’t really like the default approach of ordering by “distance” from the source file that you’re importing from. Maybe you wanted to organise like this:

    organizer_v2.js
    import { open } from "node:fs";
    import { internalLib1 } from "@company/library1";
    import { internalLib2 } from "@company/library2";
    import { lib1 } from "library1";

In Biome 2.0, all these limitations are lifted. In fact, if you look at the examples above, all snippets labeled organizer_v2.js can be produced just like that by our new import organizer.

Other improvements include support for organizing export statements, support for “detached” comments for explicitly separating import chunks if necessary, and import attribute sorting.

You can find the documentation on the new import organizer at https://next.biomejs.dev/assist/actions/organize-imports/.

The Import Organizer was always a bit of a special case in Biome. It was neither part of the linter, nor of the formatter. This was because we didn’t want it to show diagnostics the way the linter does, while its organizing features went beyond what we expect from the formatter.

In Biome 2.0, we have generalised such use cases in the form of Biome Assist. The assist is meant to provide actions, which are similar to the fixes in lint rules, but without the diagnostics.

The Import Organizer has become an assist, but we’ve started using this approach for new assists too: useSortedKeys can sort keys in object literals, while useSortedAttributes can sort attributes in JSX.

For more information about assists, see: https://next.biomejs.dev/assist/

In addition to the // biome-ignore comments we already supported, we now support // biome-ignore-all for suppressing a lint rule or the formatter in an entire file.

We also added support for suppression ranges using // biome-ignore-start and // biome-ignore-end. Note that // biome-ignore-end is optional in case you want to let a range run until the end of the file.

For more information about suppressions, see: https://next.biomejs.dev/linter/#suppress-lint-rules

After a few months of hard work, we are happy to announce that the HTML formatter is now ready for users to try out and start reporting bugs! This is a huge step towards Biome fully supporting HTML-ish templating languages used in frameworks like Vue and Svelte.

The HTML formatter only touches actual .html files for now, so no formatting of html in .vue or .svelte files yet. It also won’t format embedded languages like JavaScript or CSS yet. HTML’s options like attributePosition, bracketSameLine, and whitespaceSensitivity have been implemented.

The HTML formatter is still pretty experimental, so it will remain disabled by default for the full 2.0 release. At the time of writing, Biome is able to parse the grand majority of Prettier’s HTML tests, and format 46/124 of them correctly. Despite not matching Prettier yet, we’re pretty confident that it should output documents that are formatted adequately without destroying anything. If you find a case where it doesn’t, please let us know!

You can enable the HTML formatter by adding the following to your config file:

{
"html": {
"formatter": {
"enabled": true
}
}
}

Several new rules have added since v1.9:

  • BREAKING: The configuration fields include and ignore have been replaced with a single includes field.
  • BREAKING: Reworked some recommended rules recommended to be less pedantic and blocking. This is a breaking change if your project relied on those rules to block the CI in case of violations. If you used the migrate command, the behaviour should remain as before.
  • BREAKING: The style rules aren’t recommended anymore. If you used the migrate command, the behaviour should remain as before.
  • BREAKING: Removed deprecated rules:
    • noConsoleLog
    • noInvalidNewBuiltin
    • noNewSymbol
    • useShorthandArrayType
    • useSingleCaseStatement
  • BREAKING: Many deprecated options, including some that still referenced the old Rome name, have been removed.
  • Added a new option javascript.parser.jsxEverywhere to control whether Biome should expect JSX syntax in .js/.mjs/.cjs files.
  • Improved monorepo support: The rule noUndeclaredDependencies now works correctly in monorepos by using the nearest package.json file, instead of only the root one.
  • We have enabled support for .editorconfig files by default.
  • Changed default formatting of package.json to align better with formatting by package managers.

For the full list of changes, please refer to our changelog.

Roadmap 2025 and Biome 2.0

Today we’re happy to share our plans for Biome 2.0 as well as the rest of our roadmap for 2025. But before we dive into what’s coming, let’s do a quick recap of the major developments in 2024.

2024 was a great year for Biome. Let’s see what happened:

  • We released 4 new “minor” Biome versions, from 1.6 through 1.9, with plenty of useful features:
    • New biome search and biome explain commands, while the biome migrate command was significantly expanded to help users coming from ESLint and Prettier.
    • Added support for CSS and GraphQL formatting and linting.
    • Partial support for Astro, Svelte and Vue files.
    • The ability to let configuration files extend from one another, which is especially useful in monorepo and larger organizational setups.
    • Custom reporters for better CI integration and machine-readable output.
    • Support for .editorconfig.
    • We added countless new lint rules and miscellaneous fixes and improvements, with a special shoutout to useSortedClasses that marks the beginning of dedicated Tailwind support.
  • Our team of maintainers has grown from 10 members at the start of 2024 to 18 today.
  • We won the Productivity Booster award of the OS Awards 2024.
  • We gained several new sponsors.
  • We improved our IDE support on multiple fronts:
    • A new Zed extension has been contributed to the project.
    • Our VS Code extension has seen an overhaul that’s currently in Pre-Release.
    • And even though this happened after the new year, we shouldn’t neglect to mention that our IDEA plugin has seen a major update too, which is now available in the nightly channel.

One more thing that we are happy to announce is that as of January 2025, we are also offering Enterprise Support for Biome. Hopefully this will allow some of our contributors to spend more of their time and effort towards Biome!

Right now our team is busy preparing for the Biome 2.0 release. Because our project is still run by volunteer contributors, we do not have an ETA for you. But we can share some of the goodies that will be coming:

  • Plugins. A long-requested feature, we started the development of Biome plugins after an RFC process that started in January 2024. Biome 2.0 will feature the first fruits of this labor: Users will be able to create their own lint rules using GritQL.
  • Domains. Domains are a configuration feature that makes it easy for users to enable or disable all rules related to a specific domain, such as React, Next.js or testing frameworks. It also allows Biome to automatically enable recommended domain-specific rules based on the dependencies listed in your package.json.
  • Monorepo Support. While support for monorepos was already improved with our extends feature in biome.json, many weak spots remained. Biome 2.0 has an improved architecture based on an internal ProjectLayout that should resolve most of these.
  • Suppressions. Biome already allowed suppression of linter diagnostics through the use of // biome-ignore suppression comments. With Biome 2.0 we’re adding support for // biome-ignore-all and // biome-ignore-start/biome-ignore-end comments.
  • Multi-file analysis. Last but not least, we’re adding true Multi-file support to Biome 2.0. This means that our lint rules will be able to query information from other files, which will enable much more powerful lint rules.

Again, we should preface a disclaimer here: We’re a community-driven project, so we cannot promise to deliver any of the features below. But that doesn’t mean we don’t have a wishlist of things we would like to work on in 2025 😉

This year we will focus on:

  • HTML support. No toolchain for the web is complete without it, and we’re already working on it!
  • Embedded languages. CSS or GraphQL snippets inside a template literal in a JavaScript file? JavaScript or CSS inside an HTML file? Biome should be able to handle these as well, and we’ll try to make it happen. This should also lead to better support for Astro, Svelte, and Vue than we have today.
  • Type inference. This was already a wish for 2024, and we’re busy filling in the prerequisites such as multi-file analysis. There’s even an early proof-of-concept for a noFloatingPromises rule. This year we want to ship a real version of noFloatingPromises, and hopefully dabble further into type inference.
  • .d.ts generation. While we’re on the subject of types, we would also like to create our first transformation: generating .d.ts files from TypeScript sources. Initially we would only focus on TypeScript using Isolated Modules.
  • JSDoc support. Can we use JSDoc comments as a source of type information too? If we are able to do type inference, this seems an opportunity we cannot pass on.
  • Markdown support. Some work has already started for it and it would be a nice addition to round out our language support.
  • More plugins. While Biome 2.0 will launch with the ability to create lint rules in GritQL, that’s only the tip of the iceberg. We know our users want more, and we certainly have ideas for more types of plugins. We’ll first collect feedback from the 2.0 release, and then we’ll decide which plugin area we’ll focus on next.

We would like to thank our users and sponsors alike for their amazing support in 2024! Without you, this project would not be what it is today.

Hopefully we can also count on your support for the coming year. If you would like to help out, you can:

  • Become a contributor. Please help us to build those features!
  • Sponsor us. Ask your company to sponsor us: Biome is so fast that it can reduce your company’s CI times, improve developer productivity, and save money. Sponsorships also create exposure for your company.
  • Hire us. Is Biome missing anything that prevents your company from adopting it? You can make it happen by hiring us! Any company that hires a contributor to work on Biome for 3 months or more automatically applies for sponsorship benefits.
  • Improve our documentation. Write guides or recipes, or help to keep our translations up-to-date for non-English speakers.