Custom plugin publishing is being rolled out gradually. If Admin → Plugin
Settings includes a Custom Plugins tab, use the workflow on this page.
If the tab is not present, follow the previous publishing
instructions. See Switching to
pre-built plugins for rollout details and
help moving existing plugins.
How custom plugin publishing works
A publishing source is a long-lived release channel between one Backstage workspace and one Portal instance. Each publication bundles the compatible frontend and backend features selected from the workspace into a single, coherent source version. Create one publishing source for each repository or workspace, not one for each plugin. A workspace often contains several related plugin frontends, backends, modules, and shared packages. Publishing them together makes the active source version represent code that was developed and tested together. By default, the latest successfully uploaded source version is active. You can pin an older version to roll back or to control when a new release takes effect.Custom plugins must use Backstage’s new frontend
system or new backend
system. Run
yarn fix --publish
in a Backstage workspace to generate and check the package metadata that
Portal uses to discover its features.Prepare a plugin workspace
Portal Studio is the recommended way to develop and test custom plugins. It loads local plugin code in your Portal instance while you work, and the workspace it creates already includes the Portal CLI used for publishing. To create a workspace:yarn start to test the new plugin in Studio Mode. See Get started with Portal Studio for prerequisites, existing workspaces, feature selection, and troubleshooting.
You can publish from an existing Backstage workspace as well. Install @spotify/portal-cli as a development dependency or invoke the latest version with npx. Before publishing, use Studio and the normal checks for that repository to test the exact frontend and backend features you intend to release.
Create a publishing source
You must be a Portal administrator to create a source and its publishing tokens.- Go to Admin → Plugin Settings → Custom Plugins.
- Select Add source.
- Name the source after the workspace or repository it represents, such as
Developer productivity plugins. - Choose whether plugins should start automatically the first time they are published:
- Leave Start new plugins automatically off to review and start each new plugin manually after its first publication.
- Turn it on when releases from the workspace are already trusted and tested. This setting only controls the initial state of newly discovered plugins.
- Select Create publishing source.
Create and store a publishing token
After creating a source, Portal opens its Publish tokens tab.- Enter a descriptive token name. Use separate tokens for separate publishers, for example
GitHub Actions productionandLocal development. - Select Create token.
- Copy the token immediately. Portal shows its value only once.
- Store an automation token in your CI/CD secret store as
PORTAL_PUBLISH_TOKEN. Do not commit it to the repository, print it in build output, or put it directly in a command that might be retained in shell history.

Publish from the workspace
If the workspace was created bystudio init, the Portal CLI is already installed. In an interactive terminal, set the instance and enter the token at a hidden prompt using the example for your shell. Replace https://example.spotifyportal.com with the full URL of your Portal instance.
For Bash or Zsh (macOS, Linux, WSL, or Git Bash):
cmd.exe), open PowerShell for these steps. For other shells, use your secret manager to supply PORTAL_PUBLISH_TOKEN, or switch to one of the shells above.
These prompts keep the token out of the commands saved in shell history and hide it while you enter it. The CLI still receives the token as a plaintext environment variable, so use a trusted machine and do not print the environment or enable shell tracing. For CI/CD, inject the token from your secret store instead of prompting.
Then publish all compatible plugins in the workspace:
unset PORTAL_PUBLISH_TOKEN in Bash/Zsh or Remove-Item Env:PORTAL_PUBLISH_TOKEN in PowerShell, or close the terminal session.
The command discovers publishable plugin packages, builds a release, and uploads it to the source associated with the token. It does not publish the packages to npm.
Select what to publish
With no package selection,repo publish includes every compatible plugin package in the workspace. This is the recommended default when one source represents the whole workspace.
During development or for a deliberately partial release, you can select or exclude features:
--plugin, --exclude-plugin, or --exclude to select multiple values. Package selections accept package names or workspace-relative paths.
Publish from CI/CD
Publishing from the workspace’s normal release pipeline keeps Portal aligned with reviewed source changes and makes releases repeatable. The following GitHub Actions example uses the scripts included in a Studio workspace and publishes after changes reachmain:
.github/workflows/publish-portal-plugins.yaml
PORTAL_PUBLISH_TOKEN repository or environment secret. Adapt the validation commands, branch, runner, and approval rules to your repository. For other CI systems, use the same sequence: install the workspace reproducibly, run its required checks, expose PORTAL_INSTANCE and PORTAL_PUBLISH_TOKEN only to the publish step, then run portal-cli repo publish.
For stronger separation between environments, create a different Portal publishing source and token for each Portal instance. Protect production tokens with your CI system’s environment approvals and branch rules.
Verify and manage a release
After publishing:- Open Admin → Plugin Settings → Custom Plugins and select the source.
- Confirm that a new version is listed and open it to review the included and ignored features.
- If the source does not start new plugins automatically, return to the Installed tab and start the new plugin or module.
- Configure the plugin and exercise its important frontend and backend behavior.

Troubleshooting publishing
- No publishable packages were found: run
yarn fix --publish, check thebackstage.roleandbackstage.pluginIdmetadata in each package, and confirm that the packages use the new frontend or backend system. - The upload is unauthorized: confirm that
PORTAL_PUBLISH_TOKENcontains an active token for this exact source and instance. Create a new token if the old value was lost or revoked. - The wrong packages are included: run with
--dry-run, then use package paths,--plugin,--exclude-plugin, or--excludeto refine the release. - A feature is ignored: check the source version details. Another higher-priority source contains the same package or a plugin package with the same plugin ID.
- The published plugin does not work: reproduce the issue in Studio, review the CLI and browser errors, verify the plugin’s configuration, and confirm that all required frontend, backend, module, and local library packages are part of the workspace.