Skip to main content

Package Metadata

The package.json file is a JSON file that contains metadata about a JavaScript package. It is a Node.js standard that is expanded upon in the NPM ecosystem, and is required for all packages published to NPM or a similar package registry.

Known Metadata Fields

This section documents the known package.json metadata fields that play a significant role in the Backstage ecosystem.

All fields defined by NPM are inherited by the Backstage ecosystem. The list below only includes those standard fields for which additional information is available.

name

The name of the package, as defined by NPM. In addition, the following naming scheme is strongly encouraged for packages published in the Backstage ecosystem:

First pick a package name prefix that is unique to your organization or collection of packages, but also places it within the Backstage ecosystem, for example: @example/backstage, @example-backstage/, or example-backstage. This prefix should be used by all packages that you publish, regardless of whether they're part of a plugin or not.

Any package that is not part of a plugin should use the prefix along with a descriptive name, for example: @example/backstage-components or @example/backstage-foo-client.

For plugin packages you should also pick a plugin ID and add plugin-<pluginId> to the prefix, along with a suffix based on the package role:

  • <prefix>-plugin-<pluginId>: The main frontend code of the plugin.
  • <prefix>-plugin-<pluginId>-module-<name>: Optional modules related to the frontend plugin package.
  • <prefix>-plugin-<pluginId>-backend: The main backend code of the plugin.
  • <prefix>-plugin-<pluginId>-backend-module-<name>: Optional modules related to the backend plugin package.
  • <prefix>-plugin-<pluginId>-react: Shared widgets, hooks and similar that both the plugin itself and third-party frontend plugins or modules can depend on.
  • <prefix>-plugin-<pluginId>-node: Utilities for backends that both the plugin backend itself and third-party backend plugins or modules can depend on.
  • <prefix>-plugin-<pluginId>-common: An isomorphic package with platform agnostic models, clients, and utilities that all packages above or any third-party plugin or module can depend on.

For example, a frontend package for the poetry plugin might be called @example/backstage-plugin-poetry, and a backend package for the same plugin might be called @example/backstage-plugin-poetry-backend.

If you are creating a module for an existing package that is not part of your project, you should use the same prefix along with the plugin ID of the package that the module is for. For example, if you are creating a poetry provider module for @backstage/plugin-catalog-backend, you might call it @example/backstage-plugin-catalog-backend-module-poetry-provider.

repository

The location of the source code for the package, as defined by NPM.

This field can be generated by the backstage-cli repo fix --publish command. The only requirement is that the package.json in your workspace root has the repository field documented.

main

The main entry point of the package, as defined by NPM. In a standard Backstage setup this should point to the entry point for local development, typically src/index.ts. This field along with other entry point fields such as module and types are rewritten when packaging the package for distribution. You can read more about this process in the publishing section, and it is also used for backend production builds.

exports

The exports of the package, as defined by Node.js. This field is used to define the entry points of the package. As with other entry point fields, the exports should point to entry points for local development. They will the be rewritten when packaging the package for distribution. You can read more about this in the sub-path exports section.

typeVersions

This field is used to specify versioned type entry points for the package, as defined by TypeScript, and is used as the equivalent of the exports field. TypeScript does support type declarations in the exports field, but that requires that the moduleResolution option in tsconfig.json is set to node16 or bundler, which the Backstage ecosystem currently does not support.

This field can be generated by the backstage-cli repo fix command. First fill out the exports field to point to source fields, which will then be used to generate typeVersions.

sideEffects

This field declares whether it is safe to remove unused code through tree shaking when bundling this package into a frontend build, and is defined for example by WebPack.

This field can be generated by the backstage-cli repo fix command. It will set to false by default for all frontend packages, since Backstage frontend packages should generally never have any side effects. If your package does have side effects, you can set explicitly set this field to true.

scripts

The package scripts as defined by NPM. The Backstage CLI provides a set of standard scripts, which you can read more about in the build system section. The full list of scripts is as follows:

"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"clean": "backstage-cli package clean",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
}

configSchema

The Backstage configuration schema for the package, as described in the defining configuration section.

backstage

This field is a collection of Backstage specific metadata fields. It is required for all Backstage packages, and any package that defines this field is considered to be part of the Backstage ecosystem. All sub-fields of this collection are defined below.

backstage.role

This field defines the role of the package in the Backstage ecosystem. It can affect both the build process and runtime behavior, and signals the intended usage of the package to consumers. You can read more about this field in the package roles section.

backstage.pluginId

For any package that is part of a plugin, this field should be set to the plugin ID. This is the same ID as you would pass to the createPlugin, createBackendPlugin, or createBackendModule functions in the implementation of the package. It is also the same ID as the one described in the name section.

This field can be generated by the backstage-cli repo fix --publish command. The plugin ID will be inferred from the package name and role. If the package name is not actually part of a plugin but still has plugin-* in its name, you can set this field to be explicitly null.

The presence of this field is checked by the backstage-cli package prepack command, which is used to prepare a package for publishing. You can read more about this requirement in the section on metadata for published packages.

backstage.pluginPackages

For any package that is part of a plugin, this field should be set to a list of all packages that are directly part of the same plugin. This includes frontend and backend plugin packages as well as related libraries, but not modules.

This field can be generated by the backstage-cli repo fix --publish command. It will list all packages with the same plugin ID in the workspace.

The presence of this field is checked by the backstage-cli package prepack command, which is used to prepare a package for publishing. You can read more about this requirement in the section on metadata for published packages.

Example usage of the backstage.pluginPackages field
{
"name": "@backstage/plugin-catalog",
"backstage": {
"role": "frontend-plugin",
"pluginId": "catalog",
"pluginPackages": [
"@backstage/plugin-catalog",
"@backstage/plugin-catalog-backend",
"@backstage/plugin-catalog-common",
"@backstage/plugin-catalog-node",
"@backstage/plugin-catalog-react"
]
}
...
}

backstage.pluginPackage

For any module package of a plugin, this field should be set to the name of the plugin package that this is a module for.

This field can be generated by the backstage-cli repo fix --publish command. It checks for packages with a matching plugin ID in the same workspace, but also knows the package names of the core feature plugin IDs such as catalog, auth, scaffolder, etc. If the package name can not be inferred, it has to be provided manually.

The presence of this field is checked by the backstage-cli package prepack command, which is used to prepare a package for publishing. You can read more about this requirement in the section on metadata for published packages.

Example usage of the backstage.pluginPackage field
{
"name": "@backstage/plugin-catalog-backend-module-github",
"backstage": {
"role": "backend-plugin-module",
"pluginId": "catalog",
"pluginPackage": "@backstage/plugin-catalog-backend"
}
...
}

backstage.moved

This field indicates that a package has been renamed and moved to a new location. This field is recognized by the Backstage CLI, where the version bump command will automatically switch to using the new package instead. The value of this field should be the new package name.

Example usage of the backstage.moved field
{
"name": "@backstage/plugin-azure-devops",
"backstage": {
"moved": "@backstage-community/plugin-azure-devops"
}
...
}

backstage.inline

If set to true this field indicates that monorepo package is private and should be inlined into dependent packages rather than being treated as a dependency. This effectively means that all imported code from the inlined package will be copied into the consuming package, once for each package.

This flag affects various parts of the Backstage tooling, for example the way the Backstage CLI builds work, the way that @backstage/eslint-plugin lints dependencies on the package, and how it's treated by @backstage/repo-tools.

The backstage.inline field is primarily intended to aid in the implementation of the Backstage core framework in the main Backstage repository, but it can be used in other projects as well.

Setting this flag also requires the top-level private field to be set as well, since inline packages should not be published.

Example usage of the backstage.moved field
{
"name": "@internal/utils",
"backstage": {
"inline": true
}
...
}

Metadata for Published Packages

When publishing a package with the help of the Backstage CLI, there are a number of metadata checks that are performed to ensure that the package is correctly set up for the Backstage ecosystem. These checks are performed by the backstage-cli package prepack command, which is used to prepare a package for publishing. These checks can all also be verified separately using the backstage-cli repo fix --publish command, and in many cases the required metadata can be generated automatically. It is therefore important to make running the fix command part of your workflow in any project that is publishing Backstage packages.

To set this up, we recommend that you add the following script to the root package.json of your workspace:

{
"scripts": {
"fix": "backstage-cli repo fix --publish"
}
}

This allows anyone working in the repo to run yarn fix to check and update all packages in the workspace.

In addition, you should also add a check to your CI pipeline that ensures that there are no pending fixes. This is done by calling the command with the --check flag, which in GitHub actions would look something like this:

- name: check for missing repo fixes
run: yarn fix --check

Finally, if you are using Husky or any other pre-commit hook, you can also set up a hook to run the fix command before committing:

{
"lint-staged": {
"package.json": [
"yarn fix"
]
}
}