Meteor Codebase Standardization via Biome

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 blame everywhere 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:

  • noUnusedVariables
  • useConst
  • useTemplate

Phase 2 - We should mensure the impact:

  • noVar
  • noDoubleEquals
  • noUndeclaredVariables
  • noDuplicateImports
  • useArrowFunction

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:

  1. The PR was opened with only the formatting/lint changes for that subphase
  2. Existing package tests continue to pass (./meteor test-packages ./packages/<name>)
  3. No logic was changed — style only
  4. The PR was reviewed and approved by at least one maintainer
  5. 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 blame can be preserved with .git-blame-ignore-revs — add the SHA of each formatting commit to the .git-blame-ignore-revs file 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
1 Like