NashTech Blog

Biome.js: Configs for JS/TS, React & Angular (Plus Ignoring the Noise)

Table of Contents
Biome.js: Configs for JS/TS, React & Angular (Plus Ignoring the Noise) make it different

Hi folks,
Welcome again! I hope you are doing well. I am thrilled to see you here. If you caught my first blog on Biome.js and actually tried it out, you felt that instant speed boost when switching from ESLint + Prettier. But here’s the real talk: the intro magic only gets you so far. Custom configs? That’s where Biome goes from “nice tool” to “can’t live without it.”

So today, we will discuss about the configuration you need when you use Biome.js.

Configuring Biome for Vanilla JS/TS Projects: The Basic Foundation

Let’s start simple:
No frameworks needed, just a Node.js CLI tool or vanilla Vite app.
The biome.json file lives in root directory and controls everything.
Think of it as your project’s DNA.

Below is the config for a TypeScript CLI tool:

{
"$schema": "https://biomejs.dev/schemas/1.9.6/schema.json",
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"ignore": ["dist/**"]
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUndeclaredVariables": "error",
"noUnusedVariables": "warn"
},
"style": {
"useFlatMap": "error",
"noUselessCatch": "warn",
"noDefaultExport": "warn"
},
"suspicious": {
"noExplicitAny": "warn"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded",
"trailingComma": "es5"
},
"parser": {
"unsafeParameterDecoratorsEnabled": true
}
},
"organizeImports": {
"enabled": true
}
}

Let’s break down why each setting matters:

  • $schema: VS Code/WebStorm autocomplete + prevents schema drift as Biome evolves.
  • lineWidth: 100 is the suitable balance readability with modern wide screens (80 for React purists).
  • useFlatMap: My favorite—catches .map(item => item).flat() and rewrites as .flatMap(item => item)
  • noUselessCatch: Flags try { ... } catch(e) {} blocks you forgot to handle
  • quoteStyle: "single": Personal preference, but consistent across teams.
  • organizeImports: Alphabetizes + groups your imports.

For vanilla JS projects, remove the javascript.parser section. Test with:
npx @biomejs/biome@latest check src/

Migrating Existing React & Angular Projects

Swapping tools in production code feels like defusing a bomb. I just survived two migrations and learned the hard way.

React Migration (Next.js/Vite/Create React App)

Step-by-step from my React 19 + Apollo project:

Install without removing old tools (safety first):
npm i -D @biomejs/biome

Port ESLint rules (most map 1:1):
npx @biomejs/biome migrate eslint

Rewrite package.json scripts:

{
"scripts": {
"lint": "biome lint --apply .",
"format": "biome format --write .",
"check": "biome check . --reporter=github",
"lint:staged": "biome lint --apply --files-ignore=\"dist/**\""
}
}

React/Next.js specific biome.json:

{
"linter": {
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "warn",
"noArrayIndexKey": "error"
},
"style": {
"useHookAtTopLevel": "error",
"useValidForDirection": "error"
}
}
},
"overrides": [
{
"include": ["src/**/*.tsx"],
"options": {
"parser": { "unsafeParameterDecoratorsEnabled": true }
}
}
]
}

Angular 18 Migration (CLI + Standalone + Signals)

Angular’s stricter by nature, so expect more fixes:

{
"files": {
"ignore": [
"dist/**",
"node_modules/**",
"**/*.angular-cli.json",
"src/environments/*"
]
},
"overrides": [
{
"include": ["src/app/**/*.ts"],
"linter": {
"rules": {
"correctness": {
"noUndeclaredVariables": "off"
},
"style": {
"noDefaultExport": "off"
}
}
}
},
{
"include": ["src/**/*.html"],
"formatter": {
"enabled": false
}
}
]
}

Angular-specific wins:
1) Catches signal misuse before runtime errors
2) Standalone component imports get auto-sorted
3) Nx workspaces need files.maxSize: 1000000 for large files

Migration checklist (what saved me):
1. git commit -m "pre-biome" (rollback ready)
2. biome check src/ --reporter=json > biome-issues.json (baseline)
3. biome lint --apply src/ (fix safe issues)
4. biome format --write src/ (format everything)
5. Team review PR with only Biome changes

New React & Angular Projects: Start Clean

New React (Vite + TypeScript):

npm create vite@latest my-react-app — –template react-ts
cd my-react-app
npm i -D @biomejs/biome
npx @biomejs/biome@latest init

Enhanced biome.json:
{
"files": {
"ignore": ["dist/", "node_modules/", "*.config.*"],
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.json"]
},
"formatter": { "enabled": true },
"linter": {
"rules": {
"recommended": true,
"style": {
"useFlatMap": "error",
"noDefaultExport": "warn",
"noUselessCatch": "error"
},
"suspicious": {
"noExplicitAny": "error"
}
}
},
"organizeImports": { "enabled": true }
}

New Angular 18 (Standalone + Signals):

ng new my-angular-app --strict --standalone --routing=false
cd my-angular-app
npm i -D @biomejs/biome
npx @biomejs/biome@latest init
Angular starter config:
{
"javascript": {
"parse": {
"unsafeParameterDecoratorsEnabled": true,
"allowSuperOutsideMethod": true
}
},
"overrides": [
{
"include": ["src/app/**/*.component.ts"],
"linter": {
"rules": {
"style": { "noDefaultExport": "off" }
}
}
}
]
}

Ignoring Linting & Formatting: Graceful Opt-Outs

Biome’s opinionated, but flexible. Here’s every way to say “not here, not now.”

1. Inline Comments (Most Common)

// biome-ignore lint/style/useFlatMap: third-party API limitation
// biome-ignore lint/suspicious/noExplicitAny: legacy prop type
const items = dangerousApi().map(x => x).flat();
// biome-ignore format: preserve exact indentation for markdown parser
const markdown = `
## Heading
* Bullet stays indented
`;

2. Rule Overrides in biome.json

{
"linter": {
"rules": {
"style": {
"useFlatMap": "off", // Legacy codebase
"noDefaultExport": "off" // Angular barrel files
},
"suspicious": {
"noExplicitAny": "warn" // Migration phase
}
}
}
}

3. File/Path Ignores

{
"files": {
"ignore": [
"dist/", "build/",
"node_modules/.cache/", "legacy/",
".min.js", ".generated.*"
],
"maxSize": 1000000 // 1MB limit for huge files
}
}

4. Dedicated .biomeignore

# Auto-generated
dist/
coverage/
# Vendor + build tools
node_modules/.cache/
**/*.config.js
# Legacy migration folder
legacy/

The Payoff: Real Numbers

ProjectOld SetupBiomeImprovements
Angular Monorepo (50k LOC)ESLint + Prettier: 2m 15s12s11x faster
React Vite (10k LOC)ESLint + Prettier: 28s3s9x faster
Node CLI (5k LOC)ESLint only: 12s1s12x faster

Conclusion

Biome configs aren’t set-it-and-forget-it—they evolve with your project.
That Angular monorepo now runs linting in parallel across 15 apps.
React side project? Zero lint debt since day one.

Your Aim: Pick one project today. Run npx @biomejs/biome@latest init, commit the config, time your biome check .. Share your before/after numbers below!

Hey, let’s stay in touch!

If you liked this blog, please share it with your friends and colleagues. Connect with FE competency on LinkedIn to read more about such topics.

Picture of Paras Jain

Paras Jain

Frontend Developer with more than four years of Frontend experience at Nashtech in helping the company to develop and maintain a better code base for reusability. I have experience in technologies such as Angular, CSS, and Javascript, and I also worked on web and mobile automation using Selenium and Appium. I am always eager to tackle more complex problems and continue to find ways to maximize user efficiency.

Leave a Comment

Suggested Article

Discover more from NashTech Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading