> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# ADR-009: Biome as Primary Formatter and Linter

> Status: Accepted Date: 2026-04-12 Participants: Platform Architecture Team

**Status:** Accepted\
**Date:** 2026-04-12\
**Participants:** Platform Architecture Team

***

## Context

The project needed a code formatter and linter for TypeScript/React code. The traditional stack was Prettier (formatter) + ESLint (linter). Biome emerged as a unified alternative offering both formatting and linting in a single fast tool written in Rust.

## Options Considered

### Option A: Prettier + ESLint (traditional)

* **How it works:** Prettier formats code; ESLint checks for errors and code quality. Often combined via `eslint-prettier-plugin` to avoid conflicts.
* **Pros:** Industry standard; wide plugin ecosystem; well-understood; broad IDE support.
* **Cons:** Two tools to configure and maintain; frequent conflicts between Prettier and ESLint rules requiring `eslint-config-prettier`; slow on large codebases; complex config overlap.
* **Why not chosen:** Configuration complexity and performance on a 7,354-file codebase warranted a better solution.

### Option B: Biome ✓

* **How it works:** Single Rust-based tool for formatting, linting, and import organization. Replaces Prettier for formatting and most ESLint rules. ESLint retained only for custom project rules not available in Biome.
* **Pros:** 10–100x faster than Prettier+ESLint; single configuration file (`biome.json`); no plugin conflicts; built-in import organizer (`noUnusedImports`); modern defaults (single quotes, trailing commas, 120 char line width).
* **Cons:** Biome's rule coverage doesn't 100% match ESLint's plugin ecosystem; some custom rules still require ESLint; newer tool with smaller community than ESLint.
* **Why chosen:** Performance advantage is significant on a large codebase with 5,600+ pre-commit checks. Single tool reduces configuration overhead. ESLint remains for custom rules Biome doesn't cover.

## Decision

Biome 2.3 is the primary formatter and import organizer. ESLint 9 provides supplementary custom rules. The `biome.json` config enforces: 2-space indent, 120-char line width, single quotes, trailing commas (all), semicolons (always), `noUnusedImports`, `noUnusedVariables`, `useConst`, `useExportType`, `useImportType`, `useSelfClosingElements`, and `noConsole: warn` in `src/`. Lint-staged runs Biome on every commit via Husky.

## Consequences

### Positive

* Dramatically faster pre-commit checks
* Single tool reduces config sprawl
* Import organization automated on commit
* Consistent code style across 12 cores

### Negative

* Developers unfamiliar with Biome need onboarding
* Some ESLint plugins have no Biome equivalent (requiring ESLint to remain)
* Biome updates may change formatting rules (minor disruption)

### Mitigations

* `npm run format` and `npm run format:imports` commands documented in CLAUDE.md and AGENTS.md
* `npm run lint:fix` for ESLint auto-fixes
* `biome.json` committed and versioned; changes reviewed in PR

## Related Documents

* [CLAUDE.md §Formatting & Linting](../../../CLAUDE.md) — Biome config details
* [package.json](../../../package.json) — `format`, `format:imports`, `lint`, `check:biome` scripts
