Move plugins from the previous Portal installation methods to pre-built or custom plugins.
Portal’s previous plugin installer installed plugins from npm packages and ran a build whenever you installed, updated, or uninstalled a plugin. It handled both public packages and your organization’s private packages, which you published to the Portal package registry.Portal is replacing that installer with two approaches:
Pre-built plugins are supported public plugins that Spotify builds and prepares in advance. You choose and install their prepared releases from Plugin Settings.
Custom plugins are plugins your organization develops, modifies, or maintains. You build and publish them from a Backstage workspace directly to a publishing source in your Portal instance using the Portal CLI.
These approaches are being rolled out to Portal instances throughout September 2026. Both let Portal load plugins that have already been built, removing the installation-time build step.Existing plugins installed with the previous installer need to move to one of these approaches. This guide explains what changes and how to activate and test replacements before removing the previous installations.
What changes
You still use Plugin Settings to explore, install, update, and uninstall public plugins. Installation adds an Analyze step where you review the resolved package versions and related frontend, backend, and module packages before confirming.For plugins your organization develops or maintains, publishing also changes. Instead of publishing individual npm packages to the Portal registry, you build and upload a workspace release with the Portal CLI. A publishing source groups the workspace’s plugins into one release, and source-scoped tokens let you publish from local development or CI/CD. Use Studio to test the workspace before publishing.Pre-built installation supports stable versions and latest. To use experimental or prerelease code, publish it as a custom plugin. See Plugin Versioning for the version and revision update behavior.Plugin-specific configuration and testing remain necessary with both types of plugin.
Availability
During the September 2026 rollout, availability may differ between instances. The Custom Plugins tab under Admin → Plugin Settings indicates that the new approaches are available in your instance. Until then, use the Using the previous installer instructions at the bottom of the installation, updating, uninstalling, and versioning pages.Existing packages need to be moved even after your instance has the new experience. The steps below let you activate and test replacements before removing the previous copies.
Before you migrate
Before starting, consider how you will verify that your plugins still work as expected after migration. If you have many plugins, consider migrating in stages so you can verify each group before moving on to the next.The Installed tab displays migration notices after Portal has compared legacy package names with the pre-built plugin catalog:
Move packages to pre-built installs lists public packages with a prepared release that Portal can install directly.
Move custom plugin packages lists packages that are not in the pre-built catalog and need to be published from your own workspace.
Packages shown as Not ready yet are known, but do not currently have a release that Portal can install.
Migrate related frontend, backend, and module packages together whenever possible.
Migrate to pre-built plugins
Go to Admin → Plugin Settings.
In the Move packages to pre-built installs notice, select Review pre-built migration.
Review the packages Portal resolved. Select the plugins and modules you want to move.
Select Switch to pre-built.
Wait for the operation to finish, then verify each replacement. Plugins that were running remain running after a successful switch; stopped plugins and modules remain stopped.
Portal installs the prepared replacement first and leaves the legacy copy installed. The replacement takes precedence at runtime, which lets you test it before cleanup. Do not remove the legacy copy yet.If a package appears under Not ready yet, read the reason shown in the dialog. Check the plugin release for a metadata, compatibility, dependency, or build problem and look for a newer version. If the reason is unclear, contact Customer Support with the package name, Portal instance, and message. For experimental code, follow the custom publishing guidance.
Migrate to custom plugins
Packages in the Move custom plugin packages notice are not available as pre-built plugins. They are typically private or organization-specific packages that were previously published to a package registry and installed from there.
In the notice, select Review custom migration and record every package listed.
Find the source repository and Backstage workspace that produce those packages. Stop publishing new releases through the previous Portal package registry flow.
Make sure the packages use the new frontend or backend system and have valid Backstage package metadata. Use Portal Studio to update and test them if needed.
Create a publishing source for each workspace under Admin → Plugin Settings → Custom Plugins. Use one source for the whole workspace rather than one source per package.
Create a source-scoped publishing token and add portal-cli repo publish to the workspace’s CI/CD release flow. See Publish and install custom plugins for the complete setup and an example pipeline.
Publish a source version containing all of the packages listed for that workspace. Preserve the package names and plugin IDs so Portal can match the replacements to their legacy copies.
Confirm that the new source version is active. Start any replacement that should be running, then verify its behavior and configuration.
Repeat these steps for each workspace represented by the migration list. If the original source code or ownership of a package is unknown, resolve that before migration; the previous installed artifact is not a maintainable substitute for a source workspace.
Verify the replacements
Before cleanup, check that the migrated plugins still work as expected for the features your teams use.If a pre-built replacement does not work as expected and shows Legacy copy installed, you can revert by uninstalling the plugin. This removes the pre-built version and restores the previously installed copy. This option is only available before you remove that copy during cleanup. If you need help, collect the package version and visible error details before contacting Support.If a custom release fails, pin its source to the previous known-good version while you fix and republish the workspace.If an individual custom plugin does not work as expected, consider republishing the workspace without it using --exclude-plugin or --exclude. This lets you keep the other custom plugins active and continue validating them while you fix the affected plugin, without removing the entire publishing source. See Select what to publish for examples. Make sure the new source version is active, and leave the affected plugin’s previous installation in place until its replacement is working.
Remove previous installations
After Portal detects a migrated package alongside its previous installation, the Clean up legacy plugin copies notice appears on Plugin Settings.
Confirm again that every selected replacement works correctly.
Select Review cleanup.
Review the selected legacy copies. Clear any plugin that you are not ready to remove.
Select Uninstall legacy copies.
Monitor the cleanup build until it completes, then run a final check of the replacement plugins.
Cleanup cannot restore the old installation automatically. Only remove a
legacy copy after its replacement has been tested. Do not continue publishing
migrated custom plugins with the previous registry-based method.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Spotify for Backstage","colors":{"primary":"#34baa2","light":"#9af0e1","dark":"#91eeda"},"logo":{"light":"https://mintcdn.com/spotify-89f50c35/24doFeqc-xIrJKxF/static/logo/light.svg?fit=max\u0026auto=format\u0026n=24doFeqc-xIrJKxF\u0026q=85\u0026s=e7c3376851f302fc6d1308df15deb771","dark":"https://mintcdn.com/spotify-89f50c35/24doFeqc-xIrJKxF/static/logo/dark.svg?fit=max\u0026auto=format\u0026n=24doFeqc-xIrJKxF\u0026q=85\u0026s=a4e4bd6c0b855fc5959169face3701e1","href":"/"},"favicon":"https://mintcdn.com/spotify-89f50c35/6C5KyJhdlFRgXnE0/static/favicon.ico?fit=max\u0026auto=format\u0026n=6C5KyJhdlFRgXnE0\u0026q=85\u0026s=78c7096e52c0a4493c1d4b76355d22d9","api":{"playground":{"display":"simple"}},"appearance":{"default":"dark"},"navbar":{"links":[{"href":"https://backstage.spotify.com/contact-us/try-portal/","label":"Try Spotify Portal"}],"primary":{"type":"button","label":"Log in","href":"https://backstage.spotify.com/login/"}},"footer":{"socials":{"linkedin":"https://www.linkedin.com/showcase/spotify-r\u0026d","x":"https://twitter.com/spotifyeng","youtube":"https://www.youtube.com/@SpotifyRnD","instagram":"https://www.instagram.com/lifeatspotify","facebook":"https://www.facebook.com/spotify"},"links":[{"header":"Learn More","items":[{"label":"Go to backstage.spotify.com","href":"https://backstage.spotify.com"},{"label":"Explore the demo","href":"https://demo.backstage.io/catalog"},{"label":"Partner interest form","href":"https://backstage.spotify.com/interested-in-partnering"}]},{"header":"News \u0026 Updates","items":[{"label":"Read our blog","href":"https://backstage.spotify.com/blog"},{"label":"Subscribe to newsletter","href":"https://spoti.fi/backstagenewsletter"},{"label":"Portal system status","href":"https://status.spotifyportal.com"}]},{"header":"Community","items":[{"label":"Join the community","href":"https://github.com/backstage/community"},{"label":"Get Backstage Certified","href":"https://www.cncf.io/training/certification/cba"}]},{"header":"Legal","items":[{"label":"Security","href":"https://backstage.spotify.com/security"},{"label":"Privacy Policy","href":"https://backstage.spotify.com/spotify-for-backstage-terms/privacy-policy"},{"label":"Cookies","href":"https://www.spotify.com/legal/cookies-policy"},{"label":"Terms of Service","href":"https://backstage.spotify.com/terms-of-service"},{"label":"Trademark Usage","href":"https://www.linuxfoundation.org/legal/trademark-usage"}]}]},"seo":{"metatags":{"canonical":"https://backstage.spotify.com/docs"}},"fonts":{"heading":{"family":"Circular Sp","source":"https://mintlify-assets.b-cdn.net/fonts/CircularSpTitle-Bold.woff2","format":"woff2"},"body":{"family":"Circular Sp","source":"https://mintlify-assets.b-cdn.net/fonts/CircularSp-Book.woff2","format":"woff2"}},"styling":{"codeblocks":{"theme":{"light":"github-light","dark":"dracula"}},"latex":false},"integrations":{"gtm":{"tagId":"GTM-58S6R55"},"telemetry":{"enabled":false}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"navigation":{"global":{"anchors":[{"anchor":"Contact us","icon":"headset","href":"https://backstage.spotify.com/contact-us/talk-to-us/"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"spotify-89f50c35","hasAudioNarration":false,"actualSubdomain":"spotify-89f50c35","customDomains":["backstage.spotify.com"],"gitSource":{"type":"github","owner":"backstage-external","repo":"spotify-for-backstage-docs","deployBranch":"main","contentDirectory":"public","isPrivate":true,"mountPath":"","label":""},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"ENABLED"},"CONTEXTUAL_FEEDBACK":{"status":"ENABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6af70fd85dcd64e14d2edac9","clientVersion":"0.0.4128","searchFilterCounts":[{"language":"default","tag":"Portal","count":140},{"language":"default","tag":"Plugins","count":111},{"language":"default","tag":"Soundcheck","count":88},{"language":"default","tag":"Portal Features \u0026 Plugins","count":88},{"language":"default","tag":"API Reference","count":45},{"language":"default","tag":"Integrations","count":35},{"language":"default","tag":"Guides","count":34},{"language":"default","tag":"Core Concepts","count":31},{"language":"default","tag":"Checks","count":19},{"language":"default","tag":"Fact Collectors","count":16}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true,"deflection":{"enabled":true,"email":"backstage-support@spotify.com","showHelpButton":true}},"basePath":"/docs","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"styles.css","content":"body{--font-jetbrains-mono:\n 'JetBrains Mono', SF Mono, SFMono-Regular, Menlo, Monaco, Cascadia Mono,\n Segoe UI Mono, Roboto Mono, Oxygen Mono, Ubuntu Monospace, Source Code Pro,\n Fira Mono, Droid Sans Mono, Consolas, Courier New, monospace}#topbar-cta-button svg path{stroke:#000000}#topbar-cta-button span{color:#000000}#content:has(.video-overlay){isolation:auto}.landing-page-card{transition:all 0.3s cubic-bezier(0.4, 0, 0.2, 1);backdrop-filter:blur(12px);border-width:2px;background-color:rgb(255 255 255)}.landing-page-card:is(.dark *){background-color:rgb(255 255 255 / 0.1)}.landing-page-card:hover{transform:translateY(-0.25rem)}.landing-page-card [data-component-part=\"card-icon\"],.landing-page-card [data-component-part=\"card-icon\"]>img{width:48px;height:48px}.landing-page-card h2{font-size:1.5rem;margin-bottom:1rem;font-weight:600}"}],"page":{"pagePath":"portal/managing-plugins/migration","slug":"/portal/managing-plugins/migration","pageMetadata":{"title":"Switching to pre-built plugins","description":"Move plugins from the previous Portal installation methods to pre-built or custom plugins.","href":"/portal/managing-plugins/migration"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Heading,Warning}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`Portal’s previous plugin installer installed plugins from npm packages and ran a build whenever you installed, updated, or uninstalled a plugin. It handled both public packages and your organization’s private packages, which you published to the Portal package registry.`}),`\n`,_jsx(_components.p,{children:`Portal is replacing that installer with two approaches:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Pre-built plugins`}),` are supported public plugins that Spotify builds and prepares in advance. You choose and install their prepared releases from `,_jsx(_components.strong,{children:`Plugin Settings`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Custom plugins`}),` are plugins your organization develops, modifies, or maintains. You build and publish them from a Backstage workspace directly to a publishing source in your Portal instance using the Portal CLI.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`These approaches are being rolled out to Portal instances throughout `,_jsx(_components.strong,{children:`September 2026`}),`. Both let Portal load plugins that have already been built, removing the installation-time build step.`]}),`\n`,_jsx(_components.p,{children:`Existing plugins installed with the previous installer need to move to one of these approaches. This guide explains what changes and how to activate and test replacements before removing the previous installations.`}),`\n`,_jsx(Heading,{level:`2`,id:`what-changes`,children:`What changes`}),`\n`,_jsxs(_components.p,{children:[`You still use `,_jsx(_components.strong,{children:`Plugin Settings`}),` to explore, install, update, and uninstall public plugins. Installation adds an `,_jsx(_components.strong,{children:`Analyze`}),` step where you review the resolved package versions and related frontend, backend, and module packages before confirming.`]}),`\n`,_jsx(_components.p,{children:`For plugins your organization develops or maintains, publishing also changes. Instead of publishing individual npm packages to the Portal registry, you build and upload a workspace release with the Portal CLI. A publishing source groups the workspace’s plugins into one release, and source-scoped tokens let you publish from local development or CI/CD. Use Studio to test the workspace before publishing.`}),`\n`,_jsxs(_components.p,{children:[`Pre-built installation supports stable versions and `,_jsx(_components.code,{children:`latest`}),`. To use experimental or prerelease code, publish it as a custom plugin. See `,_jsx(_components.a,{href:`/portal/managing-plugins/plugin-versioning`,children:`Plugin Versioning`}),` for the version and revision update behavior.`]}),`\n`,_jsx(_components.p,{children:`Plugin-specific configuration and testing remain necessary with both types of plugin.`}),`\n`,_jsx(Heading,{level:`2`,id:`availability`,children:`Availability`}),`\n`,_jsxs(_components.p,{children:[`During the September 2026 rollout, availability may differ between instances. The `,_jsx(_components.strong,{children:`Custom Plugins`}),` tab under `,_jsx(_components.strong,{children:`Admin → Plugin Settings`}),` indicates that the new approaches are available in your instance. Until then, use the `,_jsx(_components.strong,{children:`Using the previous installer`}),` instructions at the bottom of the installation, updating, uninstalling, and versioning pages.`]}),`\n`,_jsx(_components.p,{children:`Existing packages need to be moved even after your instance has the new experience. The steps below let you activate and test replacements before removing the previous copies.`}),`\n`,_jsx(Heading,{level:`2`,id:`before-you-migrate`,children:`Before you migrate`}),`\n`,_jsx(_components.p,{children:`Before starting, consider how you will verify that your plugins still work as expected after migration. If you have many plugins, consider migrating in stages so you can verify each group before moving on to the next.`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.strong,{children:`Installed`}),` tab displays migration notices after Portal has compared legacy package names with the pre-built plugin catalog:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Move packages to pre-built installs`}),` lists public packages with a prepared release that Portal can install directly.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Move custom plugin packages`}),` lists packages that are not in the pre-built catalog and need to be published from your own workspace.`]}),`\n`,_jsxs(_components.li,{children:[`Packages shown as `,_jsx(_components.strong,{children:`Not ready yet`}),` are known, but do not currently have a release that Portal can install.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Migrate related frontend, backend, and module packages together whenever possible.`}),`\n`,_jsx(Heading,{level:`2`,id:`migrate-to-pre-built-plugins`,children:`Migrate to pre-built plugins`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Go to `,_jsx(_components.strong,{children:`Admin → Plugin Settings`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.strong,{children:`Move packages to pre-built installs`}),` notice, select `,_jsx(_components.strong,{children:`Review pre-built migration`}),`.`]}),`\n`,_jsx(_components.li,{children:`Review the packages Portal resolved. Select the plugins and modules you want to move.`}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Switch to pre-built`}),`.`]}),`\n`,_jsx(_components.li,{children:`Wait for the operation to finish, then verify each replacement. Plugins that were running remain running after a successful switch; stopped plugins and modules remain stopped.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Portal installs the prepared replacement first and leaves the legacy copy installed. The replacement takes precedence at runtime, which lets you test it before cleanup. Do not remove the legacy copy yet.`}),`\n`,_jsxs(_components.p,{children:[`If a package appears under `,_jsx(_components.strong,{children:`Not ready yet`}),`, read the reason shown in the dialog. Check the plugin release for a metadata, compatibility, dependency, or build problem and look for a newer version. If the reason is unclear, `,_jsx(_components.a,{href:`https://backstage.spotify.com/account/support/`,children:`contact Customer Support`}),` with the package name, Portal instance, and message. For experimental code, follow the `,_jsx(_components.a,{href:`/portal/managing-plugins/plugin-versioning#experimental-versions`,children:`custom publishing guidance`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`migrate-to-custom-plugins`,children:`Migrate to custom plugins`}),`\n`,_jsxs(_components.p,{children:[`Packages in the `,_jsx(_components.strong,{children:`Move custom plugin packages`}),` notice are not available as pre-built plugins. They are typically private or organization-specific packages that were previously published to a package registry and installed from there.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the notice, select `,_jsx(_components.strong,{children:`Review custom migration`}),` and record every package listed.`]}),`\n`,_jsx(_components.li,{children:`Find the source repository and Backstage workspace that produce those packages. Stop publishing new releases through the previous Portal package registry flow.`}),`\n`,_jsxs(_components.li,{children:[`Make sure the packages use the new frontend or backend system and have valid Backstage package metadata. Use `,_jsx(_components.a,{href:`/portal/portal-plugins/get-started#migrate-an-existing-plugin-to-portal`,children:`Portal Studio`}),` to update and test them if needed.`]}),`\n`,_jsxs(_components.li,{children:[`Create a publishing source for each workspace under `,_jsx(_components.strong,{children:`Admin → Plugin Settings → Custom Plugins`}),`. Use one source for the whole workspace rather than one source per package.`]}),`\n`,_jsxs(_components.li,{children:[`Create a source-scoped publishing token and add `,_jsx(_components.code,{children:`portal-cli repo publish`}),` to the workspace’s CI/CD release flow. See `,_jsx(_components.a,{href:`/portal/portal-plugins/publishing-custom-plugins`,children:`Publish and install custom plugins`}),` for the complete setup and an example pipeline.`]}),`\n`,_jsx(_components.li,{children:`Publish a source version containing all of the packages listed for that workspace. Preserve the package names and plugin IDs so Portal can match the replacements to their legacy copies.`}),`\n`,_jsx(_components.li,{children:`Confirm that the new source version is active. Start any replacement that should be running, then verify its behavior and configuration.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Repeat these steps for each workspace represented by the migration list. If the original source code or ownership of a package is unknown, resolve that before migration; the previous installed artifact is not a maintainable substitute for a source workspace.`}),`\n`,_jsx(Heading,{level:`2`,id:`verify-the-replacements`,children:`Verify the replacements`}),`\n`,_jsx(_components.p,{children:`Before cleanup, check that the migrated plugins still work as expected for the features your teams use.`}),`\n`,_jsxs(_components.p,{children:[`If a pre-built replacement does not work as expected and shows `,_jsx(_components.strong,{children:`Legacy copy installed`}),`, you can revert by `,_jsx(_components.a,{href:`/portal/managing-plugins/uninstalling-plugins`,children:`uninstalling the plugin`}),`. This removes the pre-built version and restores the previously installed copy. This option is only available before you remove that copy during cleanup. If you need help, collect the package version and visible error details before contacting Support.`]}),`\n`,_jsx(_components.p,{children:`If a custom release fails, pin its source to the previous known-good version while you fix and republish the workspace.`}),`\n`,_jsxs(_components.p,{children:[`If an individual custom plugin does not work as expected, consider republishing the workspace without it using `,_jsx(_components.code,{children:`--exclude-plugin`}),` or `,_jsx(_components.code,{children:`--exclude`}),`. This lets you keep the other custom plugins active and continue validating them while you fix the affected plugin, without removing the entire publishing source. See `,_jsx(_components.a,{href:`/portal/portal-plugins/publishing-custom-plugins#select-what-to-publish`,children:`Select what to publish`}),` for examples. Make sure the new source version is active, and leave the affected plugin’s previous installation in place until its replacement is working.`]}),`\n`,_jsx(Heading,{level:`2`,id:`remove-previous-installations`,children:`Remove previous installations`}),`\n`,_jsxs(_components.p,{children:[`After Portal detects a migrated package alongside its previous installation, the `,_jsx(_components.strong,{children:`Clean up legacy plugin copies`}),` notice appears on `,_jsx(_components.strong,{children:`Plugin Settings`}),`.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Confirm again that every selected replacement works correctly.`}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Review cleanup`}),`.`]}),`\n`,_jsx(_components.li,{children:`Review the selected legacy copies. Clear any plugin that you are not ready to remove.`}),`\n`,_jsxs(_components.li,{children:[`Select `,_jsx(_components.strong,{children:`Uninstall legacy copies`}),`.`]}),`\n`,_jsx(_components.li,{children:`Monitor the cleanup build until it completes, then run a final check of the replacement plugins.`}),`\n`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Cleanup cannot restore the old installation automatically. Only remove a\nlegacy copy after its replacement has been tested. Do not continue publishing\nmigrated custom plugins with the previous registry-based method.`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":{"theme":{"light":"github-light","dark":"dracula"}},"config":{},"pageMetadata":{"title":"Switching to pre-built plugins","description":"Move plugins from the previous Portal installation methods to pre-built or custom plugins.","href":"/portal/managing-plugins/migration"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"What changes","slug":"what-changes","depth":2,"children":[]},{"title":"Availability","slug":"availability","depth":2,"children":[]},{"title":"Before you migrate","slug":"before-you-migrate","depth":2,"children":[]},{"title":"Migrate to pre-built plugins","slug":"migrate-to-pre-built-plugins","depth":2,"children":[]},{"title":"Migrate to custom plugins","slug":"migrate-to-custom-plugins","depth":2,"children":[]},{"title":"Verify the replacements","slug":"verify-the-replacements","depth":2,"children":[]},{"title":"Remove previous installations","slug":"remove-previous-installations","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"spotify-89f50c35","siteName":"Spotify for Backstage","title":"Switching to pre-built plugins - Spotify for Backstage","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-14T13:33:02.268Z","originalFileLocation":"portal/managing-plugins/migration.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Spotify for Backstage\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Switching to pre-built plugins - Spotify for Backstage\">\u003cmeta data-mint-head property=\"og:description\" content=\"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Spotify for Backstage\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://backstage.spotify.com/docs/portal/managing-plugins/migration\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://spotify-89f50c35.mintlify.site/docs/_mintlify/api/og/v2?division=Managing+Plugins\u0026amp;title=Switching+to+pre-built+plugins\u0026amp;description=Move+plugins+from+the+previous+Portal+installation+methods+to+pre-built+or+custom+plugins.\u0026amp;theme=a6f41037062b0a3b3eab7f14\u0026amp;signature=80dd4d28fca9d4f5186cc93eb90650876840b6bdd186445d3d9f7f3120debff4\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Switching to pre-built plugins - Spotify for Backstage\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://spotify-89f50c35.mintlify.site/docs/_mintlify/api/og/v2?division=Managing+Plugins\u0026amp;title=Switching+to+pre-built+plugins\u0026amp;description=Move+plugins+from+the+previous+Portal+installation+methods+to+pre-built+or+custom+plugins.\u0026amp;theme=a6f41037062b0a3b3eab7f14\u0026amp;signature=80dd4d28fca9d4f5186cc93eb90650876840b6bdd186445d3d9f7f3120debff4\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/spotify-89f50c35/R_8z5ScClO7v3nRq/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Spotify for Backstage\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#34baa2\">\u003clink data-mint-head rel=\"canonical\" href=\"https://backstage.spotify.com/docs/portal/managing-plugins/migration\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/portal/managing-plugins/migration.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://backstage.spotify.com/#organization\",\"name\":\"Spotify for Backstage\",\"url\":\"https://backstage.spotify.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/spotify-89f50c35/24doFeqc-xIrJKxF/static/logo/light.svg?fit=max\u0026auto=format\u0026n=24doFeqc-xIrJKxF\u0026q=85\u0026s=e7c3376851f302fc6d1308df15deb771\"}},{\"@type\":\"WebSite\",\"@id\":\"https://backstage.spotify.com/docs#website\",\"name\":\"Spotify for Backstage\",\"url\":\"https://backstage.spotify.com/docs\",\"publisher\":{\"@id\":\"https://backstage.spotify.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration#webpage\",\"url\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration\",\"name\":\"Switching to pre-built plugins\",\"description\":\"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\",\"dateModified\":\"2026-09-14T13:33:02.268Z\",\"isPartOf\":{\"@id\":\"https://backstage.spotify.com/docs#website\"},\"breadcrumb\":{\"@id\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Managing Plugins\",\"item\":\"https://backstage.spotify.com/docs/portal/managing-plugins\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Switching to pre-built plugins\",\"item\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration#article\",\"headline\":\"Switching to pre-built plugins\",\"name\":\"Switching to pre-built plugins\",\"description\":\"Move plugins from the previous Portal installation methods to pre-built or custom plugins.\",\"url\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration\",\"mainEntityOfPage\":{\"@id\":\"https://backstage.spotify.com/docs/portal/managing-plugins/migration#webpage\"},\"dateModified\":\"2026-09-14T13:33:02.268Z\",\"publisher\":{\"@id\":\"https://backstage.spotify.com/#organization\"},\"isPartOf\":{\"@id\":\"https://backstage.spotify.com/docs#website\"}}]}\u003c/script>","agentPointerHref":"/docs/portal/managing-plugins/migration.md","siteName":"Spotify for Backstage","nav":{"global":{"anchors":[{"anchor":"Contact us","icon":"headset","href":"https://backstage.spotify.com/contact-us/talk-to-us/"}]},"tabs":[{"tab":"Portal","pages":[{"title":"Spotify Portal for Backstage","sidebarTitle":"Spotify Portal for Backstage","href":"/portal"},{"group":"Getting Started","root":{"title":"Getting Started Guide","sidebarTitle":"Getting started with Portal for Backstage","href":"/portal/getting-started"},"pages":[{"title":"AWS Marketplace","sidebarTitle":"Buy Portal on AWS Marketplace","href":"/portal/aws-marketplace"}]},{"group":"Portal Features \u0026 Plugins","root":{"title":"Portal Features \u0026 Plugins","sidebarTitle":"Overview","href":"/portal/core-features-and-plugins/index"},"pages":[{"group":"Catalog","root":{"title":"Software Catalog Overview","sidebarTitle":"Overview","href":"/portal/core-features-and-plugins/catalog/index"},"pages":[{"title":"Creating the Catalog Graph","href":"/portal/core-features-and-plugins/catalog/creating-the-catalog-graph"},{"title":"Descriptor Format of Catalog Entities","href":"/portal/core-features-and-plugins/catalog/descriptor-format"},{"title":"Life of an Entity","href":"/portal/core-features-and-plugins/catalog/life-of-an-entity"},{"title":"Entity References","href":"/portal/core-features-and-plugins/catalog/references"},{"title":"System Model","href":"/portal/core-features-and-plugins/catalog/system-model"},{"title":"Well-known Relations between Catalog Entities","sidebarTitle":"Well-known Relations","href":"/portal/core-features-and-plugins/catalog/well-known-relations"},{"title":"Well-known Status fields of Catalog Entities","sidebarTitle":"Well-known Statuses","href":"/portal/core-features-and-plugins/catalog/well-known-statuses"},{"title":"Creating a Single Entity","sidebarTitle":"Creating a Single Entity","href":"/portal/core-features-and-plugins/catalog/single-entity-create"},{"title":"Auto Ingestion","sidebarTitle":"Auto Ingestion","href":"/portal/core-features-and-plugins/catalog/auto-ingestion"},{"title":"Monorepos","href":"/portal/core-features-and-plugins/catalog/monorepos"},{"title":"Updating Components","sidebarTitle":"Updating Components","href":"/portal/core-features-and-plugins/catalog/bulk-editing"},{"group":"Bulk catalog ingestion","root":{"title":"Bulk catalog ingestion","sidebarTitle":"Overview","href":"/portal/core-features-and-plugins/catalog-builder/index"},"pages":[{"title":"Understanding Management Modes","sidebarTitle":"Understanding Management Modes","href":"/portal/core-features-and-plugins/catalog-builder/management-modes"},{"title":"Portal Mode Walkthrough","sidebarTitle":"Portal Mode Walkthrough","href":"/portal/core-features-and-plugins/catalog-builder/portal-mode-walkthrough"},{"title":"YAML Mode Walkthrough","sidebarTitle":"YAML Mode Walkthrough","href":"/portal/core-features-and-plugins/catalog-builder/yaml-mode-walkthrough"},{"title":"Troubleshooting Bulk Catalog Ingestion","sidebarTitle":"Troubleshooting","href":"/portal/core-features-and-plugins/catalog-builder/troubleshooting"},{"title":"Frequently Asked Questions","sidebarTitle":"FAQ","href":"/portal/core-features-and-plugins/catalog-builder/faq"}]}]},{"group":"Scaffolder","root":{"sidebarTitle":"Scaffolder","title":"Scaffolder (Portal)","href":"/portal/core-features-and-plugins/scaffolder/index"},"pages":[{"sidebarTitle":"Getting Started","title":"Getting Started with Scaffolder","href":"/portal/core-features-and-plugins/scaffolder/getting-started"},{"title":"How-to Guides","href":"/portal/core-features-and-plugins/scaffolder/how-to-guides"},{"sidebarTitle":"Reference","title":"Scaffolder Reference","href":"/portal/core-features-and-plugins/scaffolder/reference"}]},{"title":"TechDocs","sidebarTitle":"TechDocs","href":"/portal/core-features-and-plugins/techdocs"},{"title":"Soundcheck","sidebarTitle":"Soundcheck","href":"/portal/core-features-and-plugins/soundcheck"},{"group":"Fleetshift","root":{"title":"Fleetshift: Getting Started","sidebarTitle":"Fleetshift","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/getting-started"},"pages":[{"title":"Enable AI Shifts","sidebarTitle":"Enable AI Shifts","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/enable-ai-shifts"},{"title":"Create and Run a Shift","sidebarTitle":"Create and Run","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/create-and-run"},{"title":"Fleetshift Guides","sidebarTitle":"Guides","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/guides"},{"title":"Fleetshift: Writing and Publishing npm Package Shifts","sidebarTitle":"npm Package Shifts","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/npm-package-shifts"},{"title":"Fleetshift: OpenRewrite Shifts","sidebarTitle":"OpenRewrite Shifts","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/openrewrite-shifts"},{"title":"Fleetshift MCP Actions","sidebarTitle":"MCP Actions","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/mcp-actions"},{"title":"Fleetshift Troubleshooting","sidebarTitle":"Troubleshooting","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/troubleshooting"},{"title":"Fleetshift FAQ","sidebarTitle":"FAQ","hidden":false,"href":"/portal/core-features-and-plugins/fleetshift/faq"}]},{"group":"AI Gateway","root":{"title":"AI Gateway","sidebarTitle":"Overview","href":"/portal/core-features-and-plugins/ai-gateway/index"},"pages":[{"group":"Integrations","root":{"title":"Integrations","sidebarTitle":"Overview","href":"/portal/core-features-and-plugins/ai-gateway/integrations/index"},"pages":[{"title":"Anthropic","href":"/portal/core-features-and-plugins/ai-gateway/integrations/anthropic"},{"title":"OpenAI","href":"/portal/core-features-and-plugins/ai-gateway/integrations/openai"},{"title":"Azure OpenAI","href":"/portal/core-features-and-plugins/ai-gateway/integrations/azure"},{"title":"Cohere","href":"/portal/core-features-and-plugins/ai-gateway/integrations/cohere"},{"title":"Google Generative AI","href":"/portal/core-features-and-plugins/ai-gateway/integrations/google"},{"title":"Ollama","href":"/portal/core-features-and-plugins/ai-gateway/integrations/ollama"},{"title":"Amazon Bedrock","href":"/portal/core-features-and-plugins/ai-gateway/integrations/aws-bedrock"}]}]},{"title":"DevEx Metrics","href":"/portal/core-features-and-plugins/devex-metrics"},{"title":"Search","sidebarTitle":"Search","href":"/portal/core-features-and-plugins/search"},{"title":"Home","sidebarTitle":"Home","href":"/portal/core-features-and-plugins/home"},{"title":"Insights","sidebarTitle":"Insights","href":"/portal/core-features-and-plugins/insights"},{"title":"Skill Exchange","href":"/portal/core-features-and-plugins/skillexchange"},{"title":"Role-Based Access Control (RBAC)","sidebarTitle":"RBAC","href":"/portal/core-features-and-plugins/rbac"},{"group":"AiKA","pages":[{"title":"Getting Started with AiKA","sidebarTitle":"Getting Started","href":"/portal/core-features-and-plugins/aika/getting-started"},{"title":"Searching for Information","href":"/portal/core-features-and-plugins/aika/searching-for-information"},{"title":"Semantic Plugin","href":"/portal/core-features-and-plugins/aika/semantic-plugin"},{"title":"Tracing for AiKA","sidebarTitle":"Tracing for AiKA","href":"/portal/core-features-and-plugins/aika/tracing"},{"title":"AiKA Data Flow \u0026 Security","sidebarTitle":"Data Flow \u0026 Security","href":"/portal/core-features-and-plugins/aika/data-flow"},{"title":"Agent Configuration","sidebarTitle":"Agent Configuration","href":"/portal/core-features-and-plugins/aika/agent-configuration"},{"title":"AiKA Side Panel","sidebarTitle":"AiKA Side Panel","href":"/portal/core-features-and-plugins/aika/side-panel"},{"title":"Modes","sidebarTitle":"Modes","href":"/portal/core-features-and-plugins/aika/modes"}]},{"group":"AI Explorer","root":{"title":"AI Explorer","href":"/portal/core-features-and-plugins/ai-explorer/index"},"pages":[{"title":"Configuration","href":"/portal/core-features-and-plugins/ai-explorer/configuration"},{"title":"Local Resource Management From AI Explorer","href":"/portal/core-features-and-plugins/ai-explorer/installation"},{"title":"Rules","href":"/portal/core-features-and-plugins/ai-explorer/rules"},{"title":"Skills","href":"/portal/core-features-and-plugins/ai-explorer/skills"},{"title":"Marketplaces \u0026 Plugins","href":"/portal/core-features-and-plugins/ai-explorer/marketplaces"},{"title":"Ownership","href":"/portal/core-features-and-plugins/ai-explorer/ownership"},{"title":"Soundcheck Integration","href":"/portal/core-features-and-plugins/ai-explorer/soundcheck"}]},{"title":"Confidence Flags","href":"/portal/core-features-and-plugins/confidence-flags"},{"title":"Entity Overlays","sidebarTitle":"Entity Overlays","href":"/portal/core-features-and-plugins/entity-overlays"},{"group":"Data Experience","root":{"title":"Overview","href":"/portal/core-features-and-plugins/data-experience/overview"},"pages":[{"title":"Data Experience Quick Start","sidebarTitle":"Quick Start","href":"/portal/core-features-and-plugins/data-experience/quickstart"},{"title":"Key Concepts","href":"/portal/core-features-and-plugins/data-experience/key-concepts"},{"title":"Configuration","href":"/portal/core-features-and-plugins/data-experience/configuration"},{"title":"TechDocs","href":"/portal/core-features-and-plugins/data-experience/techdocs"},{"title":"Dataset Access Requests","href":"/portal/core-features-and-plugins/data-experience/data-access"},{"title":"Portal database tables","href":"/portal/core-features-and-plugins/data-experience/integration-portal-databases"},{"title":"Integration: Redshift","href":"/portal/core-features-and-plugins/data-experience/integration-redshift"},{"title":"Integration: Snowflake","href":"/portal/core-features-and-plugins/data-experience/integration-snowflake"},{"title":"Integration: BigQuery","href":"/portal/core-features-and-plugins/data-experience/integration-bigquery"},{"title":"Integration: Databricks","href":"/portal/core-features-and-plugins/data-experience/integration-databricks"},{"title":"Integration: dbt","href":"/portal/core-features-and-plugins/data-experience/integration-dbt"},{"title":"Data Lineage","href":"/portal/core-features-and-plugins/data-experience/data-lineage"}]},{"group":"MCP","root":{"title":"MCP in Portal","href":"/portal/core-features-and-plugins/mcp/overview"},"pages":[{"title":"Connecting AI Agents","href":"/portal/core-features-and-plugins/mcp/connecting-agents"},{"title":"Available MCP Tools","sidebarTitle":"Available Tools","href":"/portal/core-features-and-plugins/mcp/available-tools"},{"sidebarTitle":"Registering Tools","title":"Registering MCP Tools","href":"/portal/core-features-and-plugins/mcp/registering-tools"},{"title":"Third-Party MCP Servers","href":"/portal/core-features-and-plugins/mcp/third-party-servers"}]},{"group":"Portal CLI","root":{"title":"Get started with Portal CLI","sidebarTitle":"Get started","href":"/portal/core-features-and-plugins/cli/getting-started"},"pages":[]},{"group":"Audit Logs","root":{"title":"Getting Started","href":"/portal/core-features-and-plugins/audit-logs/getting-started"},"pages":[{"title":"Guides","href":"/portal/core-features-and-plugins/audit-logs/guides"},{"title":"Reference","href":"/portal/core-features-and-plugins/audit-logs/reference"}]},{"group":"Recommended Plugins","pages":[{"title":"PagerDuty","sidebarTitle":"PagerDuty","href":"/portal/core-features-and-plugins/recommended-plugins/pagerduty"},{"title":"Buildkite","sidebarTitle":"Buildkite","href":"/portal/core-features-and-plugins/recommended-plugins/buildkite"},{"title":"GitHub Actions","sidebarTitle":"GitHub Actions","href":"/portal/core-features-and-plugins/recommended-plugins/github-actions"},{"title":"GitHub Deployments","sidebarTitle":"GitHub Deployments","href":"/portal/core-features-and-plugins/recommended-plugins/github-deployments"},{"title":"GitHub Issues","sidebarTitle":"GitHub Issues","href":"/portal/core-features-and-plugins/recommended-plugins/github-issues"},{"title":"GitHub Pull Request Board","sidebarTitle":"GitHub Pull Request Board","href":"/portal/core-features-and-plugins/recommended-plugins/github-pull-request-board"},{"title":"Azure DevOps","sidebarTitle":"Azure DevOps","href":"/portal/core-features-and-plugins/recommended-plugins/azure-devops"},{"title":"New Relic","sidebarTitle":"New Relic","href":"/portal/core-features-and-plugins/recommended-plugins/new-relic"},{"title":"SonarQube","sidebarTitle":"SonarQube","href":"/portal/core-features-and-plugins/recommended-plugins/sonarqube"},{"title":"Jira Dashboard","sidebarTitle":"Jira Dashboard","href":"/portal/core-features-and-plugins/recommended-plugins/jira-dashboard"}]},{"title":"Portal Connect","href":"/portal/core-features-and-plugins/portal-connect"}]},{"group":"Developing Portal plugins","root":{"title":"Developing Portal plugins","sidebarTitle":"Overview","href":"/portal/portal-plugins/index"},"pages":[{"title":"Get started","sidebarTitle":"Get started","href":"/portal/portal-plugins/get-started"},{"title":"Build a plugin","sidebarTitle":"Build a plugin","href":"/portal/portal-plugins/build-plugin"},{"title":"Publish and install custom plugins","sidebarTitle":"Publish custom plugins","href":"/portal/portal-plugins/publishing-custom-plugins"},{"title":"Registry plugin publishing","sidebarTitle":"Registry publishing (previous method)","href":"/portal/portal-plugins/publishing-plugins"},{"title":"Generate package metadata","sidebarTitle":"Generate package metadata","href":"/portal/portal-plugins/generate-metadata"}]},{"group":"Managing Plugins","root":{"title":"Managing Plugins","sidebarTitle":"Overview","href":"/portal/managing-plugins/index"},"pages":[{"title":"Installing a Plugin","href":"/portal/managing-plugins/installing-plugins"},{"title":"Updating a Plugin","href":"/portal/managing-plugins/updating-plugins"},{"title":"Uninstalling a Plugin","href":"/portal/managing-plugins/uninstalling-plugins"},{"title":"Build Progress","href":"/portal/managing-plugins/build-progress"},{"title":"Plugin Versioning","description":"Choose stable pre-built plugin versions, understand version and revision updates, and publish experimental versions as custom plugins.","href":"/portal/managing-plugins/plugin-versioning"},{"title":"Switching to pre-built plugins","href":"/portal/managing-plugins/migration"}]},{"group":"Guides","root":{"title":"Guides","description":"Step-by-step guides for configuring authentication, integrations, admin settings, and feature flags in Spotify Portal for Backstage.","href":"/portal/guides/index"},"pages":[{"group":"Authentication","root":{"title":"Authentication","sidebarTitle":"Overview","href":"/portal/guides/auth/index"},"pages":[{"group":"Entra ID","root":{"title":"Entra ID","sidebarTitle":"Overview","href":"/portal/guides/auth/entraId/index"},"pages":[{"title":"Create an Azure App Registration","href":"/portal/guides/auth/entraId/create-azure-app-registration"},{"title":"Ingest users and groups","href":"/portal/guides/auth/entraId/setup-catalog-provider"},{"title":"Setup auth provider","href":"/portal/guides/auth/entraId/setup-auth"},{"title":"Retain admin access","href":"/portal/guides/auth/entraId/retain-admin-access"}]},{"group":"Okta","root":{"title":"Okta","sidebarTitle":"Overview","href":"/portal/guides/auth/okta/index"},"pages":[{"title":"Ingest users and groups","href":"/portal/guides/auth/okta/setup-catalog-provider"},{"title":"Setup auth provider","href":"/portal/guides/auth/okta/setup-auth"}]},{"group":"GitHub","root":{"title":"GitHub","sidebarTitle":"Overview","href":"/portal/guides/auth/github/index"},"pages":[{"title":"GitHub Identity Setup Guide","sidebarTitle":"GitHub Setup Guide","href":"/portal/guides/auth/github/setup-auth"}]},{"group":"GitLab","root":{"title":"GitLab","sidebarTitle":"Overview","href":"/portal/guides/auth/gitlab/index"},"pages":[{"title":"Ingest users and groups","href":"/portal/guides/auth/gitlab/setup-catalog-provider"},{"title":"Setup auth provider","href":"/portal/guides/auth/gitlab/setup-auth"}]}]},{"group":"Integrations","root":{"title":"Integrations","sidebarTitle":"Overview","href":"/portal/guides/integrations/index"},"pages":[{"group":"Azure DevOps","root":{"title":"Azure DevOps","sidebarTitle":"Overview","href":"/portal/guides/integrations/azure-devops/index"},"pages":[{"title":"Setup the Azure integration in App Settings","href":"/portal/guides/integrations/azure-devops/azure-app-settings-integrations"},{"title":"Setup Azure DevOps Discovery","href":"/portal/guides/integrations/azure-devops/azure-devops-discovery"},{"title":"Install the Azure DevOps Annotator Processor","href":"/portal/guides/integrations/azure-devops/azure-devops-annotator-processor"},{"title":"Install the Azure DevOps plugin","href":"/portal/guides/integrations/azure-devops/azure-devops-plugin"},{"title":"Install the Azure DevOps scaffolder actions","href":"/portal/guides/integrations/azure-devops/azure-devops-scaffolder-actions"},{"title":"Install the Azure DevOps Wiki Collator","href":"/portal/guides/integrations/azure-devops/azure-devops-wiki-collator"}]},{"group":"GitLab","root":{"title":"GitLab","sidebarTitle":"Overview","href":"/portal/guides/integrations/gitlab/index"},"pages":[{"title":"Setup the GitLab integration in App Settings","href":"/portal/guides/integrations/gitlab/gitlab-app-settings-integrations"},{"title":"Setup GitLab Discovery","href":"/portal/guides/integrations/gitlab/gitlab-discovery"}]},{"title":"AWS Credentials","href":"/portal/guides/integrations/aws-credentials"},{"title":"Migrating to a GitHub App Integration","sidebarTitle":"Migrating to a GitHub App","href":"/portal/guides/integrations/migrating-to-a-github-app-integration"},{"title":"Ingesting Entities into your Catalog from GitHub","sidebarTitle":"Ingesting Entities into your Catalog from GitHub","href":"/portal/guides/integrations/ingesting-entities-into-your-catalog-from-github"},{"title":"Storing Entity Metadata outside of your SCM System","sidebarTitle":"Storing Entity Metadata outside of your SCM System","href":"/portal/guides/integrations/storing-entity-metadata-outside-of-your-scm-system"}]},{"title":"Enabling recovery mode","sidebarTitle":"Enabling recovery mode","href":"/portal/guides/enable-recovery-mode"},{"group":"Confidence Flags","root":{"title":"Introduction to Flags","sidebarTitle":"Overview","href":"/portal/guides/confidence-flags/index"},"pages":[{"title":"Confidence Flag SDKs","sidebarTitle":"Flag SDKs","href":"/portal/guides/confidence-flags/sdks"},{"title":"Configure a Flag","sidebarTitle":"Quickstart","href":"/portal/guides/confidence-flags/quickstart"},{"title":"Rules","sidebarTitle":"Rules","href":"/portal/guides/confidence-flags/rules"},{"title":"Flags","sidebarTitle":"Reference","href":"/portal/guides/confidence-flags/reference"},{"title":"Resolve Tester","sidebarTitle":"Resolve tester","href":"/portal/guides/confidence-flags/resolve-tester"},{"title":"Audience","href":"/portal/guides/confidence-flags/audience"}]},{"title":"Event-Driven Catalog Component Updates","sidebarTitle":"Event-Driven Catalog Component Updates","href":"/portal/guides/events-based-github"},{"group":"Admin","pages":[{"title":"Getting Started with Admin","sidebarTitle":"Getting Started","href":"/portal/guides/Admin/getting_started"},{"title":null,"href":"/portal/guides/Admin/create-api-key"}]},{"group":"Portal Connect","root":{"title":"Portal Connect","href":"/portal/guides/portal-connect/index"},"pages":[{"title":"Installation and Setup","href":"/portal/guides/portal-connect/installation"},{"title":"Managing Portal Connect","href":"/portal/guides/portal-connect/managing"},{"title":"Security Model","href":"/portal/guides/portal-connect/security"}]}]},{"title":"Portal Security Overview","sidebarTitle":"Security","href":"/portal/security"},{"group":"Troubleshooting","root":{"title":"Troubleshooting","sidebarTitle":"Overview","href":"/portal/troubleshooting/index"},"pages":[{"title":"GitHub Integration Troubleshooting","href":"/portal/troubleshooting/github-integration"},{"title":"Troubleshooting Rate Limiting Issues","sidebarTitle":"Rate Limiting Issues","href":"/portal/troubleshooting/rate-limiting"}]},{"title":"Spotify Portal for Backstage Changelog","sidebarTitle":"Changelog","href":"/portal/changelog"},{"title":"Videos","mode":"wide","href":"/portal/videos"}]},{"tab":"Plugins","pages":[{"title":"Plugins","href":"/plugins"}]},{"tab":"Xirp","pages":[{"title":"Xirp","href":"/xirp"}]}]},"basePath":"","title":"Switching to pre-built plugins - Spotify for Backstage","buildId":"dpl_4UDxC3erAcBDHX8QT9FjyxxnLZSQ","deploymentId":"dpl_4UDxC3erAcBDHX8QT9FjyxxnLZSQ","dynamics":[],"chunks":[]}