@cfxlabsinc/b2b-services
    Preparing search index...

    Module @cfxlabsinc/nx-biome

    @cfxlabsinc/nx-biome

    Workspace-internal Nx plugin that gives every project its own cached lint and format targets.

    Adapted from Integrate Biome in 20 Minutes — see Deviations for where and why this differs.

    The plugin's createNodesV2 watches for **/project.json and contributes two targets to every project except the workspace root.

    Configuration Command
    (default) biome check <projectRoot> && eslint <projectRoot>
    fix biome check --fix <projectRoot> && eslint --fix …
    ci biome ci <projectRoot> && eslint <projectRoot>
    nx run <pkg>:lint -c fix     # one project
    nx affected -t lint -c ci # what CI runs
    nx run-many -t lint -c fix # everything

    biome check --fix already formats, so this is the narrower, faster option when you only want to reformat and don't want lint diagnostics.

    Configuration Command
    (default) biome format --write <projectRoot>
    check / ci biome format <projectRoot> (no write)
    nx run-many -t format          # format everything
    nx affected -t format # only what changed
    nx run <pkg>:format:check # dry run

    Its cache is tighter than lint's: formatting is purely local, so inputs omits ^default and an unrelated upstream edit doesn't invalidate it.

    This covers only what Biome formats — JS/TS/JSX/TSX, JSON/JSONC, CSS, GraphQL. .sql, .md and .yml/.yaml still belong to Prettier via nx format write --all; see rules/formatting.md.

    This replaced a single root lint target running bun biome check && bun eslint over the whole repo — one task, no cache, no inputs, so every invocation re-checked all 4531 files. Per-project targets are cacheable and nx affected-aware, so a one-package change lints one package.

    The workspace root is skipped explicitly (projectRoot === "."). It is its own Nx project, and giving it a lint target would restore exactly the whole-repo task these replace.

    There are no per-project Biome configs today. The command scopes Biome to a directory while the root biome.jsonc still supplies the rules, so a project opts into nothing and inherits everything.

    If a project ever does grow its own biome.json/biome.jsonc, Biome v2 discovers and merges it automatically when it declares "extends": "//" (which implies "root": false) — so the command never needs --config-path. The plugin's only job there is to add that file to inputs, or a project-local rule change would not invalidate the cache. See Biome: big projects.

    • Globs **/project.json, not **/biome.json. The article globs Biome configs so projects can adopt Biome one at a time. This workspace already lints everything from one root config, so the opt-in file would only ever match the root — which the plugin then skips, inferring nothing at all.
    • Runs eslint too. The target it replaced ran both. eslint.config.mjs globally ignores every .ts/.tsx file, so all that remains is @nx/dependency-checks over **/*/package.json — the rule that generates each package's dependencies. Dropping it would stop manifest drift being caught. --no-error-on-unmatched-pattern covers projects with nothing for eslint to match.
    • Keeps ^default in inputs. Biome never reads a dependency's sources, so for Biome alone this would be pure cache invalidation with no correctness value. It is here for the eslint half: @nx/dependency-checks walks the whole dependency closure (includeTransitiveDependencies: true) to derive a project's manifest, so an upstream import change has to invalidate this project's cache.

    Registered in workspace nx.json under plugins, excluding the vendored Pulumi provider SDKs (which biome.jsonc also ignores, and which the @nx/js/typescript plugin excludes the same way):

    {
    "plugin": "@cfxlabsinc/nx-biome",
    "options": {},
    "exclude": ["packages/pulumi/sdks/*/**"]
    }

    Resolves through the workspace dependency in the root package.json:

    "@cfxlabsinc/nx-biome": "workspace:*"
    
    NxBiomePluginOptions
    createNodesV2