Configure Biome for JavaScript & TypeScript in VS Code
Learn how to configure Biome in VS Code for JavaScript, TypeScript, React, and Next.js projects. Set up biome.json, format on save, linting, import sorting, CI checks, and recommended VS Code extensions.
When working on modern JavaScript, TypeScript, React, or Next.js projects, consistent formatting and fast linting are essential. A clean setup helps teams avoid style debates, reduce code review noise, and catch common issues before they reach production.
Biome is a fast formatter, linter, and code-assist toolchain for web projects. Instead of managing separate ESLint and Prettier configurations, Biome gives you formatting, linting, import organization, and code fixes from one tool.
In this guide, you will learn how to configure Biome in VS Code using the latest Biome setup, including biome.json, workspace settings, recommended extensions, and CI commands.
Why Use Biome?
Biome is a strong choice for modern JavaScript and TypeScript projects because it is fast, simple, and built around a single configuration file.
Key benefits include:
- Fast formatting and linting
- One configuration file
- Built-in lint rules
- Import organization
- VS Code integration
- CI-friendly commands
- Support for JavaScript, TypeScript, JSX, TSX, JSON, and CSS
Biome is especially useful when you want a simpler alternative to managing ESLint and Prettier together.
Install Biome
Biome is best installed as a development dependency in your project.
npm
npm i -D -E @biomejs/biome
pnpm
pnpm add -D -E @biomejs/biome
bun
bun add -D -E @biomejs/biome
yarn
yarn add -D -E @biomejs/biome
The -E flag pins the exact Biome version, which helps keep formatting consistent across your team.
Initialize Biome
After installing Biome, generate a configuration file:
npx @biomejs/biome init
For pnpm:
pnpx @biomejs/biome init
For bun:
bunx --bun @biomejs/biome init
For yarn:
yarn exec biome -- init
This creates a biome.json file in your project.
Biome also supports biome.jsonc if you prefer comments in your configuration.
Configure biome.json
Your biome.json file is the main configuration file for Biome.
Below is a practical setup for JavaScript, TypeScript, React, Next.js, JSON, and CSS projects.
{
"$schema": "https://biomejs.dev/schemas/2.4.13/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "main"
},
"files": {
"ignoreUnknown": true,
"includes": [
"**/*.js",
"**/*.jsx",
"**/*.ts",
"**/*.tsx",
"**/*.json",
"**/*.jsonc",
"**/*.css",
"**/*.scss"
],
"experimentalScannerIgnores": [
"**/node_modules/**",
"**/.next/**",
"**/dist/**",
"**/build/**",
"**/coverage/**",
"**/.turbo/**",
"**/out/**",
"**/.vercel/**",
"**/storybook-static/**",
"**/.env*",
"**/public/**",
"**/*.d.ts"
]
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf",
"attributePosition": "auto"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noDefaultExport": "off",
"noImplicitBoolean": "off",
"noInferrableTypes": "error",
"noNamespace": "error",
"noNegationElse": "warn",
"noNonNullAssertion": "error",
"noParameterAssign": "error",
"noUnusedTemplateLiteral": "error",
"noUselessElse": "warn",
"useBlockStatements": "error",
"useCollapsedElseIf": "error",
"useConst": "error",
"useDefaultParameterLast": "error",
"useEnumInitializers": "error",
"useExportType": "error",
"useFilenamingConvention": {
"level": "error",
"options": {
"strictCase": false,
"requireAscii": true,
"filenameCases": ["kebab-case"]
}
},
"useForOf": "error",
"useFragmentSyntax": "error",
"useImportType": "error",
"useNamingConvention": {
"level": "error",
"options": {
"strictCase": false,
"conventions": [
{
"selector": {
"kind": "function"
},
"formats": ["camelCase", "PascalCase"]
},
{
"selector": {
"kind": "variable"
},
"formats": ["camelCase", "PascalCase", "CONSTANT_CASE"]
},
{
"selector": {
"kind": "typeLike"
},
"formats": ["PascalCase"]
}
]
}
},
"useNodejsImportProtocol": "error",
"useNumberNamespace": "error",
"useSelfClosingElements": "error",
"useShorthandAssign": "error",
"useShorthandFunctionType": "error",
"useSingleVarDeclarator": "error",
"useTemplate": "error",
"useThrowOnlyError": "error"
},
"suspicious": {
"noExplicitAny": "error",
"noDebugger": "error",
"noDuplicateJsxProps": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noShadowRestrictedNames": "error",
"noSparseArray": "error",
"noUnsafeNegation": "error",
"noArrayIndexKey": "warn",
"noAssignInExpressions": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCommentText": "error",
"noCompareNegZero": "error",
"noConsole": "warn",
"noConstEnum": "error",
"noControlCharactersInRegex": "error",
"noDoubleEquals": "error",
"noDuplicateCase": "error",
"noEmptyBlockStatements": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noLabelVar": "error",
"noMisleadingCharacterClass": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noSelfCompare": "error",
"noUnknownAtRules": "off"
},
"correctness": {
"noConstAssign": "error",
"noConstructorReturn": "error",
"noEmptyPattern": "error",
"noInvalidConstructorSuper": "error",
"noInvalidUseBeforeDeclaration": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noSwitchDeclarations": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "error",
"useExhaustiveDependencies": "error",
"useHookAtTopLevel": "error",
"useIsNan": "error",
"useJsxKeyInIterable": "error",
"useValidForDirection": "error",
"useYield": "error"
},
"complexity": {
"noBannedTypes": "error",
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": {
"maxAllowedComplexity": 15
}
},
"noForEach": "warn",
"noStaticOnlyClass": "error",
"noThisInStatic": "error",
"noUselessCatch": "error",
"noUselessConstructor": "error",
"noUselessFragments": "error",
"noUselessLabel": "error",
"noUselessRename": "error",
"noUselessSwitchCase": "error",
"noUselessTernary": "error",
"noUselessTypeConstraint": "error",
"noVoid": "error",
"useFlatMap": "error",
"useLiteralKeys": "error",
"useOptionalChain": "error",
"useSimpleNumberKeys": "error",
"useSimplifiedLogicExpression": "error"
},
"security": {
"noDangerouslySetInnerHtml": "error",
"noDangerouslySetInnerHtmlWithChildren": "error",
"noGlobalEval": "error"
},
"a11y": {
"noAccessKey": "error",
"noAriaHiddenOnFocusable": "error",
"noAriaUnsupportedElements": "error",
"noAutofocus": "error",
"noDistractingElements": "error",
"noHeaderScope": "error",
"noInteractiveElementToNoninteractiveRole": "error",
"noNoninteractiveElementToInteractiveRole": "error",
"noNoninteractiveTabindex": "error",
"noPositiveTabindex": "error",
"noRedundantAlt": "error",
"noRedundantRoles": "error",
"useFocusableInteractive": "error",
"useIframeTitle": "error",
"useKeyWithClickEvents": "error",
"useKeyWithMouseEvents": "error",
"useMediaCaption": "error",
"useSemanticElements": "error",
"useValidAnchor": "error",
"useValidAriaProps": "error",
"useValidAriaValues": "error",
"useValidLang": "error"
},
"performance": {
"noAccumulatingSpread": "warn",
"noDelete": "error"
}
},
"domains": {
"next": "all",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "off",
"options": {
"groups": [
":URL:",
":BLANK_LINE:",
[":BUN:", ":NODE:"],
":BLANK_LINE:",
":PACKAGE_WITH_PROTOCOL:",
":BLANK_LINE:",
[":PACKAGE:", "!@/**", "!#*", "!~*", "!$*", "!%*"],
":BLANK_LINE:",
["@/**", "#*", "~*", "$*", "%*"],
":BLANK_LINE:",
[":PATH:", "!./**", "!../**"],
":BLANK_LINE:",
["../**"],
":BLANK_LINE:",
["./**"]
],
"identifierOrder": "natural"
}
},
"useSortedAttributes": "on"
}
}
},
"javascript": {
"formatter": {
"arrowParentheses": "always",
"bracketSameLine": false,
"bracketSpacing": true,
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"quoteStyle": "double",
"semicolons": "always",
"trailingCommas": "es5"
},
"globals": ["console", "process", "__dirname", "__filename"]
},
"json": {
"formatter": {
"trailingCommas": "none",
"indentStyle": "space",
"indentWidth": 2
}
},
"css": {
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"quoteStyle": "double"
},
"linter": {
"enabled": true
}
},
"overrides": [
{
"includes": ["**/*.test.{js,ts,tsx}", "**/*.spec.{js,ts,tsx}", "**/__tests__/**"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off",
"noConsole": "off"
},
"style": {
"noNonNullAssertion": "off"
}
}
}
},
{
"includes": ["**/next.config.{js,ts}", "**/tailwind.config.{js,ts}", "**/*.config.{js,ts}"],
"linter": {
"rules": {
"style": {
"noDefaultExport": "off"
},
"suspicious": {
"noExplicitAny": "off"
}
}
}
},
{
"includes": ["**/pages/**", "**/app/**/page.{tsx,jsx}", "**/app/**/layout.{tsx,jsx}"],
"linter": {
"rules": {
"style": {
"noDefaultExport": "off"
}
}
}
},
{
"includes": ["**/*.d.ts", "**/lib/env/*.ts"],
"linter": {
"rules": {
"style": {
"noNamespace": "off",
"useNamingConvention": {
"level": "error",
"options": {
"strictCase": false,
"conventions": [
{
"selector": {
"kind": "objectLiteralProperty"
},
"formats": ["CONSTANT_CASE", "camelCase"]
}
]
}
}
},
"suspicious": {
"noExplicitAny": "error"
},
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "error",
"options": {
"maxAllowedComplexity": 12
}
}
}
}
}
}
]
}
This configuration enables formatting, linting, assist actions, React rules, Next.js rules, accessibility checks, performance checks, and project-specific overrides.
Configure VS Code for Biome
Install the official Biome VS Code extension:
{
"recommendations": ["biomejs.biome"]
}
Then add this to .vscode/settings.json:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"biome.enabled": true,
"biome.requireConfiguration": true,
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
This setup makes Biome your default formatter, enables formatting on save, applies safe fixes on save, and organizes imports when explicitly triggered.
Recommended VS Code Extensions
Create or update .vscode/extensions.json:
{
"recommendations": [
"biomejs.biome",
"bradlc.vscode-tailwindcss",
"ms-vscode.vscode-typescript-next",
"yzhang.markdown-all-in-one",
"formulahendry.auto-rename-tag",
"christian-kohler.path-intellisense"
]
}
These extensions pair well with Biome-powered JavaScript, TypeScript, React, and Next.js projects.
Add Useful Scripts
Add Biome scripts to your package.json:
{
"scripts": {
"format": "biome format --write .",
"lint": "biome lint .",
"lint:fix": "biome lint --write .",
"check": "biome check .",
"check:fix": "biome check --write .",
"ci": "biome ci ."
}
}
Use these commands during development:
npm run format
npm run lint
npm run check
For CI pipelines, use:
npm run ci
Format, Lint, and Check with Biome
Biome provides separate commands for formatting, linting, and full project checks.
Format Files
npx @biomejs/biome format --write .
Lint Files
npx @biomejs/biome lint .
Lint and Apply Safe Fixes
npx @biomejs/biome lint --write .
Format, Lint, and Organize Imports
npx @biomejs/biome check --write .
Run Biome in CI
npx @biomejs/biome ci .
The biome ci command is designed for continuous integration and helps enforce consistent code quality across your team.
Use Biome with Git Hooks
To catch issues before code is committed, you can run Biome through a Git hook tool such as Husky or Lefthook.
Example with a pre-commit command:
npx @biomejs/biome check --write .
For larger projects, run Biome only on staged files to keep commits fast.
Best Practices for Biome
Use these practices to get the best results from Biome:
- Keep
biome.jsonas the single source of truth. - Install Biome as a project dependency instead of relying only on a global install.
- Pin the Biome version for consistent formatting across the team.
- Use the official VS Code extension.
- Enable format on save.
- Run
biome ciin your deployment pipeline. - Use overrides for test files, generated files, config files, and framework-specific files.
- Keep ignores focused on generated output such as
dist,build,.next, andcoverage.
When to Use Overrides
Overrides are useful when some files need different linting behavior.
Common examples include:
- Test files that allow
anyorconsole - Next.js page and layout files that require default exports
- Config files that use CommonJS or framework-specific patterns
- Declaration files that use namespaces
- Generated files that should not be linted strictly
Using overrides keeps your main rules strict while allowing practical exceptions where needed.
Troubleshooting Biome in VS Code
If Biome does not format or lint correctly in VS Code, check the following:
Make Sure the Extension Is Installed
Install the official extension:
biomejs.biome
Confirm Your Project Has a Biome Config
Biome should find one of these configuration files:
biome.json
biome.jsonc
.biome.json
.biome.jsonc
Check the VS Code Setting Name
Use the latest setting name:
{
"biome.requireConfiguration": true
}
Avoid older or incorrect setting names such as biome.requireConfig.
Restart the Biome Language Server
Open the VS Code command palette and restart the Biome extension or reload the VS Code window.
Run Biome from the Terminal
If VS Code behaves unexpectedly, confirm Biome works from the CLI:
npx @biomejs/biome check .
If the CLI works but VS Code does not, the issue is likely related to editor settings or workspace configuration.
Conclusion
Biome gives JavaScript and TypeScript teams a fast, modern way to handle formatting, linting, code fixes, import organization, and CI checks from one tool.
With a clean biome.json, the official VS Code extension, format on save, and CI integration, your project can maintain consistent code quality with less configuration overhead.
If you are starting a new React, Next.js, or TypeScript project, Biome is a strong default choice for keeping your codebase clean, fast, and maintainable.