Files
pnpm/pnpm11/docs/catalogs.md
Zoltan KochanandClaude Opus 5.5 6f95957063 docs: lint prose with Vale (#17238)
* docs: lint prose with Vale

Add Vale with an in-repo style, .vale/styles/pnpm, that turns the
writing rules in AGENTS.md and the Google developer documentation style
guide into lint rules. The stock Vale packages (Google, Microsoft,
RedHat, write-good) were too noisy to block on, for example 1,300
passive-voice hits in the v12 docs alone, so the rules are written for
this repo, following the GitLab model. Each one links the guideline it
enforces.

Levels:
- error, fails CI: dashes, plain-word substitutions, condescending
  words, "please", "note that", hedges, puffery, optional plurals,
  exclamation marks, ellipses, curly quotes, generic link text, product
  spellings, sentence-case headings, repeated words, double spaces,
  implementation history in comments; in changesets, bold or italic
  emphasis, internal names and release-line names.
- warning: future tense, sentences over 30 words, "instead of" and
  "so that" tails in changesets.
- suggestion: passive voice.

.vale.ini scopes the rules. Docs get every rule. Contributor Markdown
and code comments keep dashes and headings as warnings until their
roughly 8,100 em dashes are rewritten. Released changesets stay in
.changeset/ and are not rewritten, so lint-prose.mjs lints only the
changesets added since PROSE_BASE (the PR base in CI).

The prose workflow installs a pinned, checksum-verified Vale release and
runs `pnpm lint:prose`. The rest of this change rewrites the existing
docs, READMEs, contributor Markdown, and code comments to pass the
error-level rules. Only prose and comment text changed. Renamed
headings keep their anchors.

Spelling stays with cspell, which checks identifiers that Vale does not
see.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: keep prose lint from flattening meaning

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:48:09 +02:00

5.9 KiB

id, title
id title
catalogs Catalogs

"Catalogs" are a workspace feature for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in package.json files.

The catalog protocol (catalog:)

Once a catalog is defined in pnpm-workspace.yaml,

packages:
  - packages/*

# Define a catalog of version ranges.
catalog:
  react: ^18.3.1
  redux: ^5.0.1

The catalog: protocol can be used instead of the version range itself.

{
  "name": "@example/app",
  "dependencies": {
    "react": "catalog:",
    "redux": "catalog:"
  }
}

This is equivalent to writing a version range (e.g. ^18.3.1) directly.

{
  "name": "@example/app",
  "dependencies": {
    "react": "^18.3.1",
    "redux": "^5.0.1"
  }
}

You may use the catalog: protocol in the next fields:

  • package.json:
    • dependencies
    • devDependencies
    • peerDependencies
    • optionalDependencies
  • pnpm-workspace.yaml
    • overrides

The catalog: protocol allows an optional name after the colon (ex: catalog:name) to specify which catalog should be used. When a name is omitted, the default catalog is used.

Depending on the scenario, the catalog: protocol offers a few advantages compared to writing version ranges directly that are detailed next.

Advantages

In a workspace (i.e. monorepo or multi-package repo) it's common for the same dependency to be used by many packages. Catalogs reduce duplication when authoring package.json files and provide a few benefits in doing so:

  • Maintain unique versions: It's usually desirable to have only one version of a dependency in a workspace. Catalogs make this easier to maintain. Duplicated dependencies can conflict at runtime and cause bugs. Duplicates also increase size when using a bundler.
  • Easier upgrades: When upgrading a dependency, only the catalog entry in pnpm-workspace.yaml needs to be edited rather than all package.json files using that dependency. This saves time. Only one line needs to be changed instead of many.
  • Fewer merge conflicts: Since package.json files do not need to be edited when upgrading a dependency, git merge conflicts no longer happen in these files.

Defining catalogs

Catalogs are defined in the pnpm-workspace.yaml file. There are two ways to define catalogs.

  1. Using the (singular) catalog field to create a catalog named default.
  2. Using the (plural) catalogs field to create arbitrarily named catalogs.

:::tip

If you have an existing workspace that you want to migrate to using catalogs, you can use the following codemod:

pnpx codemod pnpm/catalog

:::

Default catalog

The top-level catalog field allows users to define a catalog named default.

catalog:
  react: ^18.2.0
  react-dom: ^18.2.0

These version ranges can be referenced through catalog:default. For the default catalog only, a special catalog: shorthand can also be used. Think of catalog: as a shorthand that expands to catalog:default.

Named catalogs

Multiple catalogs with arbitrarily chosen names can be configured under the catalogs key.

catalogs:
  # Can be referenced through "catalog:react17"
  react17:
    react: ^17.0.2
    react-dom: ^17.0.2

  # Can be referenced through "catalog:react18"
  react18:
    react: ^18.2.0
    react-dom: ^18.2.0

A default catalog can be defined alongside multiple named catalogs. This might be useful in a large multi-package repo that's migrating to a newer version of a dependency piecemeal.

catalog:
  react: ^16.14.0
  react-dom: ^16.14.0

catalogs:
  # Can be referenced through "catalog:react17"
  react17:
    react: ^17.0.2
    react-dom: ^17.0.2

  # Can be referenced through "catalog:react18"
  react18:
    react: ^18.2.0
    react-dom: ^18.2.0

Workspace dependencies in a catalog

Added in: v11.26.0

A catalog entry may hold a workspace: range, so the version a workspace dependency is linked by is written once too:

catalog:
  '@example/utils': workspace:^
{
  "name": "@example/app",
  "dependencies": {
    "@example/utils": "catalog:"
  }
}

pnpm expands the catalog: reference to workspace:^ and then links the workspace project, exactly as if the package.json had declared workspace:^ itself. On publish both protocols are replaced, so the example above ships as "^1.4.0" when @example/utils is at 1.4.0.

Publishing

The catalog: protocol is removed when running pnpm publish or pnpm pack. This is similar to the workspace: protocol, which is also replaced on publish.

For example,

{
  "name": "@example/components",
  "dependencies": {
    "react": "catalog:react18"
  }
}

Will become the following on publish.

{
  "name": "@example/components",
  "dependencies": {
    "react": "^18.3.1"
  }
}

The catalog: protocol replacement process allows the @example/components package to be used by other workspaces or package managers.

Settings

import CatalogMode from './settings/_catalogMode.mdx'

import CatalogPrune from './settings/_catalogPrune.mdx'