Summary
10up-toolkit currently relies on three separate tools for code quality: ESLint (JavaScript linting), Prettier (formatting), and Stylelint (CSS linting). This requires managing multiple configurations, dependencies, and plugin ecosystems.
Modern alternatives like Biome offer a unified, significantly faster experience. This issue explores what it would take to migrate 10up-toolkit's linting and formatting infrastructure to Biome or similar modern tooling.
Current State
What 10up-toolkit Uses Today
@10up/eslint-config → ESLint + eslint-config-airbnb + plugins
@10up/stylelint-config → Stylelint + various plugins
Prettier → Integrated via eslint-plugin-prettier
Dependencies involved:
eslint + ~15-20 plugins (React, JSX-a11y, import, WordPress, Jest, etc.)
prettier + eslint-plugin-prettier + eslint-config-prettier
stylelint + ~5-10 plugins (SCSS, order, etc.)
Total: 100+ transitive dependencies, complex version management
Pain Points
- Slow: ESLint with TypeScript type-checking can take 10-15+ seconds on large projects
- Complex configuration: Three separate config files, often conflicting
- Dependency hell: Plugin version conflicts, peer dependency warnings
- CI overhead: Linting often the slowest step in CI pipelines
- Maintenance burden: Keeping plugins updated across all three tools
Biome: The Leading Alternative
Biome is an all-in-one toolchain written in Rust that combines linting, formatting, and more into a single binary.
Key Features (as of Biome v2.0, June 2025)
| Feature |
Details |
| Speed |
10-25x faster than ESLint + Prettier |
| Unified |
Linter + Formatter + Import sorter in one tool |
| Languages |
JavaScript, TypeScript, JSX, JSON, CSS, GraphQL |
| Rules |
425+ rules from ESLint, typescript-eslint, and other sources |
| Prettier compat |
97% formatting compatibility with Prettier |
| Type-aware |
v2.0 introduced type-aware linting WITHOUT requiring TypeScript compiler |
| Zero deps |
Single binary, no node_modules bloat |
| Domains |
Auto-configures rules based on package.json dependencies (React, Next.js, etc.) |
Biome v2.0 Highlights
Biome v2—codename: Biotype—the first JavaScript and TypeScript linter
that provides type-aware linting rules that doesn't rely on the
TypeScript compiler!
- Type inference detects ~85% of floating promise cases at a fraction of the performance cost
- Linter plugins (limited scope, but growing)
- Domains auto-enable React/Next.js rules based on dependencies
- Biome Assist for import organizing, key sorting, attribute sorting
Performance Comparison
| Tool |
Time (example project) |
| ESLint + Prettier |
10-15 seconds |
| Biome |
< 1 second |
| Oxlint |
< 0.5 seconds |
Alternative: Oxlint
Oxlint is another Rust-based linter from the Oxc project.
Oxlint v1.0 (August 2025)
| Feature |
Details |
| Speed |
50-100x faster than ESLint (even faster than Biome) |
| Rules |
520+ ESLint rules supported |
| Zero config |
Works out of the box |
| Limitations |
Linting only (no formatting), no type-aware rules yet |
When to Choose Which
| Use Case |
Recommendation |
| All-in-one replacement |
Biome |
| Maximum speed, keep Prettier |
Oxlint + Prettier |
| Need type-aware rules |
Biome v2 |
| Heavy plugin ecosystem needs |
Stay with ESLint (for now) |
Migration Analysis
What Can Be Migrated
| Current Tool |
Biome Replacement |
Coverage |
| ESLint core rules |
✅ Biome linter |
~90% |
| eslint-plugin-react |
✅ Built-in JSX rules |
~90% |
| eslint-plugin-jsx-a11y |
✅ Built-in a11y rules |
~80% |
| eslint-plugin-import |
✅ Import organizer |
~85% |
| typescript-eslint |
✅ Type-aware rules (v2) |
~85% |
| Prettier (JS/TS/JSON) |
✅ Biome formatter |
97% |
| Prettier (CSS) |
✅ Biome formatter |
97% |
| Stylelint |
⚠️ Partial CSS linting |
~60% |
What Cannot Be Migrated (Yet)
| Tool/Plugin |
Status |
@wordpress/eslint-plugin |
❌ No direct equivalent - WordPress-specific rules |
eslint-plugin-jest |
⚠️ Partial - some rules available |
| SCSS linting |
❌ Biome doesn't support SCSS syntax |
| HTML/Markdown |
❌ Not yet supported |
| Vue/Svelte/Astro |
⚠️ Partial support |
| Custom ESLint plugins |
❌ Plugin system is limited |
WordPress-Specific Considerations
The @wordpress/eslint-plugin provides several WordPress-specific rules:
// Rules we'd lose or need alternatives for:
'@wordpress/no-unsafe-wp-apis'
'@wordpress/dependency-group'
'@wordpress/no-unused-vars-before-return'
'@wordpress/i18n-*' rules
// etc.
Options:
- Run Biome + ESLint (just for WordPress rules) in parallel
- Contribute WordPress rules to Biome as plugins
- Accept some rule loss initially
WordPress Globals
Biome needs manual configuration for WordPress globals:
{
"javascript": {
"globals": ["wp", "jQuery", "Backbone", "JSON", "_"]
}
}
The biome migrate eslint command won't automatically pick these up from @wordpress/eslint-plugin.
Proposed Migration Path
Phase 1: Formatter Migration (Low Risk)
Replace Prettier with Biome formatter only:
// 10up-toolkit.config.js
module.exports = {
formatter: 'biome', // Instead of 'prettier'
};
Benefits:
- Immediate speed improvement for formatting
- No rule changes, just formatting
- Easy rollback if issues
Changes needed:
- Add
@biomejs/biome as dependency
- Update
lint-style and format commands
- Provide
biome.json with Prettier-compatible settings
Phase 2: JavaScript/TypeScript Linting
Replace ESLint for JS/TS with Biome linter:
module.exports = {
linter: {
js: 'biome', // Instead of 'eslint'
css: 'stylelint' // Keep Stylelint for now
}
};
Migration steps:
- Run
biome migrate eslint --write to convert config
- Add WordPress globals manually
- Identify and document any lost rules
- Provide
@10up/biome-config preset
Phase 3: CSS Linting
Evaluate Biome CSS linting vs keeping Stylelint:
| Consideration |
Biome |
Stylelint |
| Speed |
✅ Much faster |
❌ Slower |
| SCSS support |
❌ None |
✅ Full |
| Rule coverage |
⚠️ Basic |
✅ Comprehensive |
| Property order |
✅ Via assist |
✅ Via plugin |
Recommendation: Keep Stylelint for SCSS projects, use Biome for CSS-only projects.
Phase 4: Full Migration
For projects that can fully migrate:
{
"linter": "biome",
"formatter": "biome"
}
Single biome.json replaces:
.eslintrc.js
.prettierrc
.stylelintrc.js
Configuration Design
New 10up-toolkit Config Options
// 10up-toolkit.config.js
module.exports = {
// Linting/formatting tool selection
codeQuality: {
// 'legacy' = ESLint + Prettier + Stylelint (current default)
// 'biome' = Biome for JS/TS/CSS, Stylelint for SCSS
// 'biome-full' = Biome only (no SCSS support)
preset: 'biome',
// Or granular control:
linter: {
js: 'biome', // 'eslint' | 'biome' | 'oxlint'
css: 'stylelint', // 'stylelint' | 'biome'
},
formatter: 'biome', // 'prettier' | 'biome'
}
};
Biome Preset for 10up
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"extends": ["@10up/biome-config"],
"javascript": {
"globals": ["wp", "jQuery", "ajaxurl", "wpApiSettings"]
},
"linter": {
"rules": {
"recommended": true,
"domains": {
"react": "all"
}
}
},
"formatter": {
"indentStyle": "tab",
"indentWidth": 4,
"lineWidth": 100
}
}
CLI Changes
Current Commands
10up-toolkit lint-js [files]
10up-toolkit lint-style [files]
10up-toolkit format [files]
Proposed Commands
# Smart routing based on config
10up-toolkit lint [files] # Runs appropriate linter(s)
10up-toolkit format [files] # Runs appropriate formatter
# Or explicit tool selection
10up-toolkit lint --tool=biome [files]
10up-toolkit lint --tool=eslint [files]
# Check mode (CI-friendly)
10up-toolkit check [files] # Lint + format check, no writes
Package Changes
New Packages
@10up/biome-config # Biome configuration preset
Modified Packages
10up-toolkit # Add Biome support, keep ESLint as fallback
@10up/eslint-config # Maintain for legacy/WordPress-specific needs
@10up/stylelint-config # Maintain for SCSS projects
Deprecated (Eventually)
@10up/eslint-config # Once Biome covers all use cases
Risks and Mitigations
| Risk |
Mitigation |
| WordPress rule coverage gaps |
Run Biome + minimal ESLint config for WP rules |
| SCSS not supported |
Keep Stylelint for SCSS, or use CSS-only |
| Team unfamiliarity |
Documentation, gradual rollout |
| Different formatting output |
Run both tools in CI initially, compare |
| Plugin ecosystem |
Biome plugins are maturing; wait or contribute |
Timeline Consideration
| Milestone |
Estimated Timeframe |
| Biome formatter only |
Ready now |
| JS/TS linting (non-WordPress) |
Ready now |
| WordPress-aware config |
Needs config work |
| Full SCSS support |
Waiting on Biome |
| Complete ESLint replacement |
2026+ |
Questions to Consider
- Should we default new projects to Biome while keeping ESLint for existing projects?
- How do we handle the WordPress-specific ESLint rules gap?
- Should we support running Biome + ESLint in parallel for WordPress rules?
- What's our SCSS story - require CSS, or maintain Stylelint?
- Should we contribute WordPress-specific rules to Biome's plugin system?
References
Summary
10up-toolkit currently relies on three separate tools for code quality: ESLint (JavaScript linting), Prettier (formatting), and Stylelint (CSS linting). This requires managing multiple configurations, dependencies, and plugin ecosystems.
Modern alternatives like Biome offer a unified, significantly faster experience. This issue explores what it would take to migrate 10up-toolkit's linting and formatting infrastructure to Biome or similar modern tooling.
Current State
What 10up-toolkit Uses Today
Dependencies involved:
eslint+ ~15-20 plugins (React, JSX-a11y, import, WordPress, Jest, etc.)prettier+ eslint-plugin-prettier + eslint-config-prettierstylelint+ ~5-10 plugins (SCSS, order, etc.)Total: 100+ transitive dependencies, complex version management
Pain Points
Biome: The Leading Alternative
Biome is an all-in-one toolchain written in Rust that combines linting, formatting, and more into a single binary.
Key Features (as of Biome v2.0, June 2025)
Biome v2.0 Highlights
Performance Comparison
Alternative: Oxlint
Oxlint is another Rust-based linter from the Oxc project.
Oxlint v1.0 (August 2025)
When to Choose Which
Migration Analysis
What Can Be Migrated
What Cannot Be Migrated (Yet)
@wordpress/eslint-plugineslint-plugin-jestWordPress-Specific Considerations
The
@wordpress/eslint-pluginprovides several WordPress-specific rules:Options:
WordPress Globals
Biome needs manual configuration for WordPress globals:
{ "javascript": { "globals": ["wp", "jQuery", "Backbone", "JSON", "_"] } }The
biome migrate eslintcommand won't automatically pick these up from@wordpress/eslint-plugin.Proposed Migration Path
Phase 1: Formatter Migration (Low Risk)
Replace Prettier with Biome formatter only:
Benefits:
Changes needed:
@biomejs/biomeas dependencylint-styleandformatcommandsbiome.jsonwith Prettier-compatible settingsPhase 2: JavaScript/TypeScript Linting
Replace ESLint for JS/TS with Biome linter:
Migration steps:
biome migrate eslint --writeto convert config@10up/biome-configpresetPhase 3: CSS Linting
Evaluate Biome CSS linting vs keeping Stylelint:
Recommendation: Keep Stylelint for SCSS projects, use Biome for CSS-only projects.
Phase 4: Full Migration
For projects that can fully migrate:
{ "linter": "biome", "formatter": "biome" }Single
biome.jsonreplaces:.eslintrc.js.prettierrc.stylelintrc.jsConfiguration Design
New 10up-toolkit Config Options
Biome Preset for 10up
{ "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json", "extends": ["@10up/biome-config"], "javascript": { "globals": ["wp", "jQuery", "ajaxurl", "wpApiSettings"] }, "linter": { "rules": { "recommended": true, "domains": { "react": "all" } } }, "formatter": { "indentStyle": "tab", "indentWidth": 4, "lineWidth": 100 } }CLI Changes
Current Commands
Proposed Commands
Package Changes
New Packages
Modified Packages
Deprecated (Eventually)
Risks and Mitigations
Timeline Consideration
Questions to Consider
References