BiomeJS Architecture Overview: A Deep Dive into the Rust-Based Tooling Platform

BiomeJS is a monorepo built in Rust that decouples JavaScript/TypeScript tooling into discrete crates for parsing, type inference, linting, and formatting, exposing them through a CLI and WASM-based JavaScript API.

The biomejs/biome repository implements a full-stack development toolchain where every concern lives in its own isolated crate. This modular BiomeJS architecture enables standalone use of the parser, formatter, or analyzer while maintaining a unified pipeline orchestrated by the command-line interface.

Core Architectural Layers

The codebase organizes functionality into distinct layers, each responsible for a specific phase of the development workflow.

Syntax and Parsing Layer

The foundation of the architecture rests on two core crates. biome_js_syntax generates Concrete Syntax Tree (CST) definitions from the language grammar, located in crates/biome_js_syntax/src/lib.rs. This crate defines the node types that represent every valid syntactic construct in JavaScript and TypeScript.

Building on these definitions, biome_js_parser transforms raw source text into a CST. The entry point resides in crates/biome_js_parser/src/parser.rs, where the parser consumes input strings and produces a structured tree that preserves all formatting details, including comments and whitespace.

Analysis and Type Inference Layer

The analytical capabilities reside in biome_js_analyze, found in crates/biome_js_analyze/src/lib.rs. This crate walks the CST to perform semantic analysis, but it does not work in isolation. It collaborates with biome_resolver (crates/biome_resolver/src/lib.rs) to construct a module graph, resolving import and export statements, path aliases, and cross-module dependencies.

Type inference occurs during this phase, where the analyzer attaches type information to symbols and collects diagnostics. Individual lint rules live in crates/biome_js_analyze/src/rules/, each implementing logic to detect anti-patterns and emit automatic fixes.

Formatting Layer

The biome_js_formatter crate handles pretty-printing without reparsing the source. Located in crates/biome_js_formatter/src/format.rs, this layer traverses the existing CST and applies style rules according to user configuration. Because it operates on the CST rather than the raw text, the formatter preserves the original parsing artifacts and ensures consistent output.

CLI and API Layer

The biome_cli crate serves as the orchestration engine, exposing the biome binary. Its entry point in crates/biome_cli/src/main.rs coordinates the entire pipeline: parse → analyze → format.

For programmatic access, the @biomejs/js-api npm package exposes the Rust engine to Node.js via WebAssembly. The TypeScript definitions in packages/@biomejs/js-api/src/index.ts provide type-safe access to the formatter, linter, and resolver. Underlying this are the WASM bindings in @biomejs/wasm-nodejs and @biomejs/wasm-web, implemented in packages/@biomejs/wasm-nodejs/src/lib.rs, which compile the core Rust crates into portable WebAssembly modules.

The BiomeJS Pipeline: From Source to Output

Understanding the BiomeJS architecture requires tracing how source code flows through the system:

  1. Parsingbiome_js_parser consumes raw JavaScript/TypeScript and produces a CST via parser.rs.
  2. Resolution – The resolver builds a module graph, mapping import links and resolving path aliases.
  3. Type Inference – The analyzer walks the CST and module graph to infer types and collect symbols.
  4. Linting – Individual rules in src/rules/ read the inferred model to emit diagnostics and auto-fixes.
  5. Formattingbiome_js_formatter walks the CST again to generate formatted output through format.rs.
  6. Execution – The CLI binary or WASM-based JS API ties these steps together, exposing commands like biome format and biome lint.

This separation of concerns allows developers to import only the functionality they need. For example, an HTML parser exists in biome_html_parser, demonstrating how the architecture supports multiple languages through shared grammar generators like biome_ungrammar.

Working with the BiomeJS Architecture

CLI Usage

Invoke the toolchain directly from the command line to process files:


# Format all JavaScript files under src/

biome format src/**/*.js

# Lint a single file and output JSON diagnostics

biome lint --diagnostic-format=json path/to/file.ts

JavaScript API Integration

Import the WASM-powered API to use Biome inside Node.js applications:

import { format } from "@biomejs/js-api";

const source = `function  foo ( ) {return 42;}`;
const result = await format(source, { lang: "js" });

console.log(result.code); // → formatted code

Embedding in Build Tools

Integrate the formatter into custom build pipelines:

import { format } from "@biomejs/js-api";

export async function transform({ code, path }) {
  const { code: formatted } = await format(code, { filePath: path });
  return { code: formatted };
}

Key Source Files and Module Organization

The following files illustrate the clean separation of concerns that defines the BiomeJS architecture:

Summary

  • BiomeJS architecture is a Rust-based monorepo splitting functionality into isolated crates for parsing, analysis, and formatting.
  • Each layer communicates through Concrete Syntax Trees (CST), enabling lossless transformation and preservation of formatting details.
  • The parser (biome_js_parser), analyzer (biome_js_analyze), and formatter (biome_js_formatter) can operate independently or as a unified pipeline.
  • The CLI (biome_cli) and JavaScript API (@biomejs/js-api) expose the same Rust core via native binaries and WebAssembly.
  • Source files in crates/ and packages/ demonstrate strict separation of concerns, making the codebase extensible and embeddable.

Frequently Asked Questions

What is the BiomeJS architecture based on?

The BiomeJS architecture is built entirely in Rust as a monorepo of discrete crates. Each crate handles a specific responsibility—syntax definitions, parsing, type inference, formatting, or CLI orchestration—allowing the components to be reused independently or composed into a complete toolchain.

How does BiomeJS parse JavaScript and TypeScript?

Parsing occurs in the biome_js_parser crate, specifically within src/parser.rs. The parser consumes raw source text and generates a Concrete Syntax Tree (CST) using node types defined in biome_js_syntax. Unlike Abstract Syntax Trees (AST), the CST preserves all formatting details including whitespace and comments.

What crate handles linting in BiomeJS?

Linting logic resides in the biome_js_analyze crate, with individual rules implemented in src/rules/. This crate performs semantic analysis on the CST and module graph, emitting diagnostics and automatic fixes based on the inferred type model and symbol resolution.

How can I use BiomeJS programmatically in Node.js?

Node.js applications access Biome through the @biomejs/js-api package, which wraps the Rust engine compiled to WebAssembly. The bindings in packages/@biomejs/wasm-nodejs/src/lib.rs expose formatter and linter functions that can be imported directly into JavaScript or TypeScript projects.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →