Biome 03 🧹 The biome.json File — Configuration structure & schema
The biome.json file is the single configuration surface for the entire toolchain. It replaces the eslint.config.js, the .prettierrc, and the eslint-config-prettier bridge with one JSON file that governs the formatter, the linter, and the assist actions. The file is optional—Biome uses a default configuration if none is found—but a project that wants a consistent experience across the CLI, the editor, and the CI creates one at the project root, next to the package.json . The configuration is organized around the three tools that Biome provides, and each tool has its own enabled flag, its own options, and its own per-language overrides.
The schema is the second half of the file. The $schema key points to the published JSON Schema, and the editor uses it to provide the autocomplete and the validation. The schema is versioned, and the URL includes the version number, so a project on Biome 2.x points to the 2.x schema and a project on Biome 1.x points to the 1.x schema. The schema is the mechanism that makes the configuration file discoverable, and the versioned URL is the mechanism that keeps the editor’s validation aligned with the installed binary.
Key point: The biome.json file has three tool sections—formatter, linter, and assist—and each is enabled by default. The files.includes array controls which files the tools process, and the negative patterns with the ! prefix exclude the files. The paths and the globs are resolved relative to the configuration file, not the working directory, since Biome v2. The $schema key points to the versioned JSON Schema for the editor validation.
Why the configuration is organized around the tools
The tool-first structure. Biome is not a single-purpose formatter. It is a toolchain, and the configuration mirrors the toolchain. The formatter section controls the formatting, the linter section controls the lint rules, and the assist section controls the code actions like the import organization . Each section has an enabled flag, and the flag is the mechanism that disables a tool without removing the configuration. A project that wants the formatting but not the linting sets linter.enabled: false and keeps the rest of the configuration.
The per-language override. The tool sections hold the options that apply to every language, and the <language>.<tool> sections hold the language-specific options. The formatter.indentStyle applies to all the files, and the javascript.formatter.quoteStyle applies only to the JavaScript files . The override is the mechanism that lets the project use the tabs for the general formatting and the single quotes for the JavaScript, without duplicating the configuration for every language.
The file selection. The files.includes array is the mechanism that controls which files the tools process. The glob patterns are the positive matches, and the ! prefix is the negative match. The files.includes applies to all three tools, and the <tool>.includes is the per-tool refinement . The file selection is the mechanism that excludes the generated files, the build output, and the vendor directories from the formatting and the linting.
The trade-off. The single file is the simplicity, and the per-language sections are the complexity. A project that uses one language has a short configuration, and a project that uses the JavaScript, the TypeScript, the JSON, and the CSS has a longer one. The structure is the trade-off against the separate configuration files that the ESLint and the Prettier setup required, and the single file is the reason the configuration is discoverable.
a. The tool sections and the per-language overrides
The formatter section holds the options that apply to every language. The indentStyle is "tab" or "space", the indentWidth is the number of the spaces, and the lineWidth is the maximum line length . The formatter.enabled flag is the mechanism that disables the formatting for the whole project.
// biome.json — the formatter section
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
}
}
The javascript.formatter section overrides the general options for the JavaScript and the TypeScript files. The quoteStyle is the "single" or the "double", and the jsxQuoteStyle is the equivalent for the JSX attributes . The override is the mechanism that lets the project use the single quotes for the JavaScript and the double quotes for the JSON.
// biome.json — the per-language override
{
"formatter": {
"indentStyle": "space",
"lineWidth": 80
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"lineWidth": 100
}
},
"json": {
"formatter": {
"enabled": false
}
}
}
The json.formatter.enabled: false disables the formatting for the JSON files, which is the mechanism for the projects that want the JSON to stay in the compact form or the generated form. The override is the per-language tool control, and it is the reason the configuration can be specific without being verbose.
The linter section holds the rule configuration. The rules.recommended flag enables the recommended rules, and the rules.<group>.<rule> is the specific rule override. The correctness.noUnusedVariables is the Biome name for the ESLint no-unused-vars, and the suspicious.noDoubleEquals is the Biome name for the eqeqeq . The rule groups are the correctness, the suspicious, the style, the complexity, the performance, the security, the a11y, and the nursery.
// biome.json — the linter section
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error"
},
"suspicious": {
"noDoubleEquals": "error"
}
}
}
}
The assist section holds the code actions. The assist.actions.source.organizeImports is the import sorting, and the assist.actions.source.fixAll is the safe fix application . The assist is the third tool, and it is the mechanism that replaces the eslint-plugin-import and the prettier-plugin-sort-imports.
b. The file selection and the schema
The files.includes array is the file selection mechanism. The glob patterns are the positive matches, and the ! prefix is the negative match. The paths are resolved relative to the configuration file, not the working directory, since Biome v2 . The files.includes applies to all three tools, and the <tool>.includes is the per-tool refinement.
// biome.json — the file selection
{
"files": {
"includes": [
"src/**/*.js",
"src/**/*.ts",
"!**/*.min.js",
"!**/dist/**"
]
}
}
The negative patterns must be listed after the positive ones, and they must start with the ** pattern if they are meant to exclude the nested directories . The files.includes is the mechanism that replaces the .eslintignore and the .prettierignore, and the vcs.useIgnoreFile is the mechanism that makes Biome respect the .gitignore.
The $schema key points to the versioned JSON Schema. The URL is https://biomejs.dev/schemas/2.5.9/schema.json for the 2.5.9 version, and the schema is the mechanism that provides the editor autocomplete and the validation . The extends key is the mechanism that inherits a shared configuration, and the merged configuration is the result of the base and the overrides.
// biome.json — the schema and the extends
{
"$schema": "https://biomejs.dev/schemas/2.5.9/schema.json",
"extends": ["@company/biome-config"],
"files": {
"includes": ["src/**/*.ts", "!**/dist"]
}
}
The extends array is the shared configuration mechanism, and the shared package is the published biome.json fragment. The overrides array is the mechanism that applies the different options to the different files, such as the .svelte files or the test files .
Complete Example Session
// ============================================
// PART 1: THE MINIMAL CONFIGURATION
// ============================================
// biome.json
{
"$schema": "https://biomejs.dev/schemas/2.5.9/schema.json"
}
// The minimal configuration.
// The defaults apply.
// The formatter, the linter, and the assist are enabled.
// ============================================
// PART 2: THE FORMATTER SECTION
// ============================================
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
}
}
// The indentStyle is "space" for the Prettier-like output.
// The lineWidth is the maximum line length.
// ============================================
// PART 3: THE PER-LANGUAGE OVERRIDE
// ============================================
{
"formatter": { "indentStyle": "space" },
"javascript": {
"formatter": {
"quoteStyle": "single",
"lineWidth": 100
}
}
}
// The JavaScript uses the single quotes and the 100-column width.
// The general formatter uses the space indentation.
// ============================================
// PART 4: THE LINTER SECTION
// ============================================
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error"
}
}
}
}
// The recommended rules are enabled.
// The noUnusedVariables is the error.
// ============================================
// PART 5: THE FILE SELECTION
// ============================================
{
"files": {
"includes": ["src/**/*.ts", "!**/*.test.ts"]
}
}
// The src/**/*.ts files are included.
// The *.test.ts files are excluded.
// ============================================
// PART 6: THE VCS INTEGRATION
// ============================================
{
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}
}
// The .gitignore is respected.
// The ignored files are not processed.
// ============================================
// PART 7: THE EXTENDS
// ============================================
{
"extends": ["@company/biome-config"]
}
// The shared configuration is inherited.
// The local keys override the base.
// ============================================
// PART 8: THE OVERRIDES
// ============================================
{
"overrides": [
{
"includes": ["**/*.svelte"],
"formatter": { "enabled": false }
}
]
}
// The Svelte files are excluded from the formatting.
// ============================================
// PART 9: THE FULL CONFIGURATION
// ============================================
{
"$schema": "https://biomejs.dev/schemas/2.5.9/schema.json",
"formatter": {
"indentStyle": "space",
"lineWidth": 80
},
"linter": {
"rules": { "recommended": true }
},
"files": {
"includes": ["src/**/*.ts", "!**/dist"]
}
}
// The full configuration.
// The schema, the formatter, the linter, and the files.
// ============================================
// PART 10: THE CHECKLIST
// ============================================
// [ ] The $schema points to the versioned schema.
// [ ] The formatter.indentStyle is set.
// [ ] The linter.rules.recommended is enabled.
// [ ] The files.includes has the positive and negative patterns.
// [ ] The vcs.useIgnoreFile is enabled for the .gitignore.
// [ ] The extends is set for the shared config.
The ten parts covered the minimal configuration, the formatter section, the per-language override, the linter section, the file selection, the VCS integration, the extends, the overrides, the full configuration, and the checklist. The through-line is that the file is organized around the three tools, and the schema is the editor validation.
Quick Reference
The tool sections
| Section | Purpose | Default |
|---|---|---|
formatter | The code formatting | Enabled |
linter | The lint rules | Enabled |
assist | The code actions | Enabled |
The formatter options
| Option | Values | Prettier equivalent |
|---|---|---|
indentStyle | "tab", "space" | useTabs |
indentWidth | Number | tabWidth |
lineWidth | Number | printWidth |
The file selection
| Pattern | Meaning |
|---|---|
src/**/*.ts | Include the TypeScript files in src |
!**/*.test.ts | Exclude the test files |
!**/dist/** | Exclude the dist directory |
The schema versions
| Biome version | Schema URL |
|---|---|
| 2.5.9 | https://biomejs.dev/schemas/2.5.9/schema.json |
| 1.8.2 | https://biomejs.dev/schemas/1.8.2/schema.json |
Best Practices
✅ Do This:
// Use the versioned schema
{ "$schema": "https://biomejs.dev/schemas/2.5.9/schema.json" } // ✅
// Use the negative patterns for the exclusions
{ "files": { "includes": ["src/**", "!**/dist"] } } // ✅
// Use the per-language overrides
{ "javascript": { "formatter": { "quoteStyle": "single" } } } // ✅
❌ Don’t Do This:
// Use the unversioned schema
{ "$schema": "https://biomejs.dev/schemas/schema.json" } // ❌
// Put the negative pattern before the positive one
{ "files": { "includes": ["!**/dist", "src/**"] } } // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The paths are not matching | The globs are relative to the working directory in v1 | Upgrade to v2, the globs are relative to the config |
| The excluded files are still processed | The negative pattern is in the wrong position | Put the negative patterns after the positive ones |
| The editor does not validate | The $schema is missing or the version is wrong | Add the versioned schema URL |
| The per-language override is ignored | The option is in the wrong section | Put it in <language>.<tool> |
Real-World Examples
1. The minimal config
{ "$schema": "https://biomejs.dev/schemas/2.5.9/schema.json" }
2. The formatter section
{ "formatter": { "indentStyle": "space", "lineWidth": 80 } }
3. The linter section
{ "linter": { "rules": { "recommended": true } } }
4. The file selection
{ "files": { "includes": ["src/**/*.ts", "!**/dist"] } }
5. The VCS integration
{ "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true } }
6. The per-language override
{ "javascript": { "formatter": { "quoteStyle": "single" } } }
7. The extends
{ "extends": ["@company/biome-config"] }
8. The overrides
{ "overrides": [{ "includes": ["**/*.svelte"], "formatter": { "enabled": false } }] }
9. The rule name
{ "linter": { "rules": { "suspicious": { "noDoubleEquals": "error" } } } }
10. The full config
{ "$schema": "https://biomejs.dev/schemas/2.5.9/schema.json", "formatter": { "indentStyle": "space" } }
Visual
The Tool Structure
┌──────────────────────────────────────────────────────────────┐
│ THE biome.json STRUCTURE │
│ │
│ biome.json │
│ ┌─────────────────────┐ │
│ │ $schema │ The editor validation │
│ ├─────────────────────┤ │
│ │ formatter │ The formatting options │
│ │ linter │ The lint rules │
│ │ assist │ The code actions │
│ ├─────────────────────┤ │
│ │ javascript │ The per-language overrides │
│ │ json │ │
│ │ css │ │
│ ├─────────────────────┤ │
│ │ files.includes │ The file selection │
│ │ vcs │ The .gitignore integration │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
The File Selection
┌──────────────────────────────────────────────────────────────┐
│ files.includes │
│ │
│ "src/**/*.ts" ← the positive match │
│ "!**/*.test.ts" ← the negative match │
│ "!**/dist/**" ← the negative match │
│ │
│ The negative patterns must come after the positive ones. │
│ The paths are relative to the config file in v2. │
└──────────────────────────────────────────────────────────────┘
The Schema
┌──────────────────────────────────────────────────────────────┐
│ $schema │
│ │
│ "https://biomejs.dev/schemas/2.5.9/schema.json" │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ The editor uses the │ Autocomplete + validation │
│ │ schema │ │
│ └─────────────────────┘ │
│ │
│ The version in the URL matches the installed Biome. │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Config file | biome.json or biome.jsonc |
| Tool sections | formatter, linter, assist |
| File selection | files.includes with the ! negative patterns |
| Path resolution | Relative to the config file (v2) |
| Schema | $schema with the versioned URL |
| Shared config | extends array |
| Per-language override | <language>.<tool> sections |
Key takeaways:
- The
biome.jsonfile is organized around the three tools. Theformatter, thelinter, and theassisteach have their own section, their ownenabledflag, and their own options. The per-language sections override the general options for the specific languages . - The
files.includesarray controls which files the tools process. The positive patterns include the files, and the negative patterns with the!prefix exclude them. The negative patterns must come after the positive ones, and the paths are relative to the configuration file in v2 . - The
$schemakey points to the versioned JSON Schema. The URL includes the version number, and the editor uses it for the autocomplete and the validation. The version in the URL should match the installed Biome version . - The
extendskey inherits a shared configuration. The shared package is the publishedbiome.jsonfragment, and the local keys override the base. Theoverridesarray applies the different options to the different files, such as the Svelte files or the test files . - The
vcssection enables the.gitignoreintegration. TheuseIgnoreFileflag makes Biome respect the.gitignore, which is the mechanism that keeps the ignored files out of the formatting and the linting .
Remember: The biome.json file is the single configuration surface for the formatter, the linter, and the assist. The tool sections hold the options, the per-language sections override them, and the files.includes array selects the files. The $schema is the editor validation, the extends is the shared configuration, and the vcs is the .gitignore integration. The file is small, and the structure is the mechanism.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!