Meteor Codebase Standardization via Biome
[RFC] Gradual Code Standardization with Biome across Meteor packages
Hi Meteor community!
We’d like to share a plan and invite everyone to participate in a long-overdue modernization effort: gradually introducing Biome across the Meteor core packages.
Background
The Meteor codebase is large, mature, and historically inconsistent in its formatting and linting conventions. Different packages use different indentation styles, quote types, semicolon usage, and have little to no automated style enforcement. This makes contributing harder than it needs to be(especially for newcomers) and slows down code reviews with style-related noise.
Why Biome instead prettier?
Biome promises to be faster than prettier and at same time contain a formatter and linter in the same tool and with 1 config file.
What we’re proposing
A phased, careful rollout of:
- Code formatting using the default values
- Linter (with a gradual rule set) for code quality and modern JavaScript patterns
We are not doing a massive one-shot reformat of the entire codebase. Instead, we’ll proceed package by package, starting with less-trafficked packages to minimize risk and disruption.
Why phased?
- Avoids massive diffs that break
git blameeverywhere at once - Lets us validate the tooling config on lower-risk packages first
- Gives the community time to review and provide feedback at each step
- Reduces the chance of introducing regressions in critical packages
How you can help
- Review the config: we’ll open PRs for each phase with the proposed Biome config
- Adopt for your package: if you maintain a package that lives in this repo, reach out or open a PR following the established config
- Report issues: if formatting changes cause unexpected behavior (it shouldn’t, but let’s be safe), open an issue
Timeline
We’ll proceed in multiple phases over several months. Each phase will have its own tracking issue and PRs. No phase will be merged without community review.
We’ll post updates in this thread as we progress.
Looking forward to working on this with you all. Let’s make contributing to Meteor a smoother experience!
Phase Plan: Meteor Code Standardization
Code formatter
Proposed Biome config (default):
{
"formatter": {
"enabled": true,
"formatWithErrors": false,
"ignore": [],
"attributePosition": "auto",
"indentStyle": "space", //default is tab
"indentWidth": 2,
"lineWidth": 80,
"lineEnding": "lf"
},
"javascript": {
"formatter": {
"arrowParentheses":"always",
"bracketSameLine": false,
"bracketSpacing": true,
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"semicolons": "always",
"trailingCommas": "all"
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
}
}
Linter
Phase 1 - Maybe wont have impact:
noUnusedVariablesuseConstuseTemplate
Phase 2 - We should mensure the impact:
noVarnoDoubleEqualsnoUndeclaredVariablesnoDuplicateImportsuseArrowFunction
Subphases per package
For each package, the work is split into subphases:
| Subphase | Action | Risk |
|---|---|---|
| A | Apply Biome (pure formatting, no logic changes) | Low |
| B | Apply Biome linter with basic rules ( noUnusedVariables, noDoubleEquals, useConst) |
Low-Medium |
| C | Apply Biome linter with modern rules ( noVar, useTemplate, etc.) |
Medium |
Subphase C is optional and can be done in a later iteration, separate from B.
Phase 1 — Non-core packages (lowest risk, lowest traffic)
Location: packages/non-core/
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
geojson-utils |
|||
mongo-decimal |
|||
xmlbuilder |
|||
bundle-visualizer |
|||
facts-base |
|||
facts-ui |
Phase 2 — Simple utility packages
Low-complexity packages with no critical runtime dependencies.
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
base64 |
|||
binary-heap |
|||
diff-sequence |
|||
callback-hook |
|||
ejson |
|||
check |
|||
random |
|||
id-map |
|||
ordered-dict |
|||
rate-limit |
|||
retry |
|||
sha |
|||
url |
Phase 3 — Infrastructure packages (moderate)
Packages used internally by the build system or with limited production usage.
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
boilerplate-generator |
|||
browser-policy-common |
|||
browser-policy-content |
|||
browser-policy-framing |
|||
browser-policy |
|||
caching-compiler |
|||
force-ssl-common |
|||
force-ssl |
|||
audit-argument-checks |
|||
ddp-rate-limiter |
|||
allow-deny |
|||
email |
Phase 4 — Authentication packages
Heavily used but with a well-defined scope. Require extra attention in tests.
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
accounts-base |
|||
accounts-password |
|||
accounts-oauth |
|||
accounts-ui |
|||
accounts-ui-unstyled |
|||
accounts-passwordless |
|||
accounts-2fa |
Phase 5 — Reactivity and data packages
Core of the Meteor experience. High risk — requires extensive testing before each merge.
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
tracker |
|||
reactive-var |
|||
reactive-dict |
|||
minimongo |
|||
mongo |
Phase 6 — DDP and transport packages
Critical for client-server communication. Highest risk.
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
ddp-common |
|||
ddp-client |
|||
ddp-server |
|||
ddp |
Phase 7 — Build and runtime packages (high risk)
| Package | Subphase A | Subphase B | Subphase C |
|---|---|---|---|
ecmascript |
|||
ecmascript-runtime |
|||
babel-compiler |
|||
webapp |
|||
autoupdate |
|||
reload |
|||
dynamic-import |
Phase 8 — tools/ (CLI and Isobuild)
The tools/ directory is Meteor’s build system (Isobuild + CLI). Requires its own phase with special care, as any regression here breaks the entire toolchain.
- Subphase A: Biome on
tools/(excluding generated files) - Subphase B: ESLint basic rules
- Subphase C: ESLint modern rules
Completion criteria per package
A package is considered complete in a subphase when:
- The PR was opened with only the formatting/lint changes for that subphase
- Existing package tests continue to pass (
./meteor test-packages ./packages/<name>) - No logic was changed — style only
- The PR was reviewed and approved by at least one maintainer
- The package config file (if any) was updated to reference the root config
Important notes
- Formatting commits must be isolated — never mix refactor/feature with Biome/lint in the same PR
git blamecan be preserved with.git-blame-ignore-revs— add the SHA of each formatting commit to the.git-blame-ignore-revsfile at the root- Packages with missing or incomplete tests should have tests added before subphase C
- Deprecated or inactive packages can be skipped or archived