diff --git a/.changeset/README.md b/.changeset/README.md index 6c68425e59..423552ee75 100644 --- a/.changeset/README.md +++ b/.changeset/README.md @@ -26,7 +26,7 @@ Optional description with code examples. Migration instructions (breaking changes only). -**Affected components:** button, card +**Affected components:** Button, Card ``` **Required:** @@ -40,7 +40,7 @@ Migration instructions (breaking changes only). ```markdown Fixed button hover state -**Affected components:** button +**Affected components:** Button ``` ````markdown @@ -56,7 +56,7 @@ Update imports: ``` ```` -**Affected components:** table +**Affected components:** Table ``` diff --git a/.changeset/add-actions-registry-examples.md b/.changeset/add-actions-registry-examples.md new file mode 100644 index 0000000000..5174bcc68d --- /dev/null +++ b/.changeset/add-actions-registry-examples.md @@ -0,0 +1,7 @@ +--- +'@backstage/backend-plugin-api': minor +'@backstage/backend-defaults': patch +'@backstage/backend-test-utils': patch +--- + +Added support for typed `examples` on actions registered via the actions registry. Action authors can now provide examples with compile-time-checked `input` and `output` values that match their schema definitions. diff --git a/.changeset/add-masked-and-hidden-option.md b/.changeset/add-masked-and-hidden-option.md deleted file mode 100644 index ad5c810a8e..0000000000 --- a/.changeset/add-masked-and-hidden-option.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-gitlab': patch ---- - -Added `maskedAndHidden` option to `gitlab:projectVariable:create` and `publish:gitlab` action to support creating GitLab project variables that are both masked and hidden. Updated gitbeaker to version 43.8.0 for proper type support. diff --git a/.changeset/add-query-catalog-entities-action.md b/.changeset/add-query-catalog-entities-action.md deleted file mode 100644 index 78fb30d584..0000000000 --- a/.changeset/add-query-catalog-entities-action.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Added `query-catalog-entities` action to the catalog backend actions registry. Supports predicate-based filtering with `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. diff --git a/.changeset/add-who-am-i-action.md b/.changeset/add-who-am-i-action.md deleted file mode 100644 index 5c1008a7e1..0000000000 --- a/.changeset/add-who-am-i-action.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Added `who-am-i` action to the auth backend actions registry. Returns the catalog entity and user info for the currently authenticated user. diff --git a/.changeset/add-withApis-core-compat-api.md b/.changeset/add-withApis-core-compat-api.md deleted file mode 100644 index 135dcf87c7..0000000000 --- a/.changeset/add-withApis-core-compat-api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-compat-api': patch ---- - -Added `withApis`, which is a Higher-Order Component for providing APIs as props to a component via `useApiHolder`. diff --git a/.changeset/angry-clouds-tell.md b/.changeset/angry-clouds-tell.md new file mode 100644 index 0000000000..a01306d84a --- /dev/null +++ b/.changeset/angry-clouds-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-module-new': patch +--- + +Rename the legacy `frontend-plugin` to `frontend-plugin-legacy` diff --git a/.changeset/app-defaults-clarify-failures.md b/.changeset/app-defaults-clarify-failures.md new file mode 100644 index 0000000000..c6321a3a3a --- /dev/null +++ b/.changeset/app-defaults-clarify-failures.md @@ -0,0 +1,5 @@ +--- +'@backstage/app-defaults': patch +--- + +Added `FetchMiddlewares.clarifyFailures()` to the default fetch API middleware stack. diff --git a/.changeset/app-routes-redirect-config.md b/.changeset/app-routes-redirect-config.md new file mode 100644 index 0000000000..ce43e3c159 --- /dev/null +++ b/.changeset/app-routes-redirect-config.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-app': patch +--- + +Added support for configuring URL redirects on the `app/routes` extension. Redirects can be configured through `app-config` as an array of `{from, to}` path pairs, which will cause navigation to the `from` path to be redirected to the `to` path. + +For example: + +```yaml +app: + extensions: + - app/routes: + config: + redirects: + - from: /old-path + to: /new-path +``` diff --git a/.changeset/auditor-zod-v4-refactor.md b/.changeset/auditor-zod-v4-refactor.md new file mode 100644 index 0000000000..c1ac7ce0aa --- /dev/null +++ b/.changeset/auditor-zod-v4-refactor.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Refactored auditor severity log level mappings to use `zod/v4` with schema-driven defaults and type inference. diff --git a/.changeset/azure-scm-events-layer.md b/.changeset/azure-scm-events-layer.md new file mode 100644 index 0000000000..22ca304f96 --- /dev/null +++ b/.changeset/azure-scm-events-layer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-azure': patch +--- + +Add Azure DevOps SCM event translation layer for instant catalog reprocessing. diff --git a/.changeset/blue-moons-crash.md b/.changeset/blue-moons-crash.md deleted file mode 100644 index bb5ae15c2e..0000000000 --- a/.changeset/blue-moons-crash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Made Accordion a `bg` provider so nested components like Button auto-increment their background level. Updated `useDefinition` to resolve `bg` `propDef` defaults for provider components. diff --git a/.changeset/bright-items-see.md b/.changeset/bright-items-see.md deleted file mode 100644 index ea3ba17cdf..0000000000 --- a/.changeset/bright-items-see.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Fixed `generate-catalog-info` command failing with "too many arguments" when invoked by lint-staged via the pre-commit hook. diff --git a/.changeset/bright-moons-open.md b/.changeset/bright-moons-open.md deleted file mode 100644 index 2668dfb2e6..0000000000 --- a/.changeset/bright-moons-open.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-react': patch -'@backstage/plugin-search': patch ---- - -Fixes the search component not registering the first search on navigate to the search page. diff --git a/.changeset/brown-rings-sort.md b/.changeset/brown-rings-sort.md deleted file mode 100644 index 045f2fbd3b..0000000000 --- a/.changeset/brown-rings-sort.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Added interactive support to the `Card` component. Pass `onPress` to make the entire card surface pressable, or `href` to make it navigate to a URL. A transparent overlay handles the interaction while nested buttons and links remain independently clickable. diff --git a/.changeset/brown-towns-find.md b/.changeset/brown-towns-find.md deleted file mode 100644 index c3244d9427..0000000000 --- a/.changeset/brown-towns-find.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Fixed invisible text in parameter input fields when using dark mode in OpenAPI definition pages diff --git a/.changeset/bui-analytics.md b/.changeset/bui-analytics.md deleted file mode 100644 index 65ba31b1cf..0000000000 --- a/.changeset/bui-analytics.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Added analytics capabilities to the component library. Components with navigation behavior (Link, ButtonLink, Tab, MenuItem, Tag, Row) now fire analytics events on click when a `BUIProvider` is present. - -New exports: `BUIProvider`, `useAnalytics`, `getNodeText`, and associated types (`AnalyticsTracker`, `UseAnalyticsFn`, `BUIProviderProps`, `AnalyticsEventAttributes`). - -Components with analytics support now accept a `noTrack` prop to suppress event firing. - -**Affected components:** Link, ButtonLink, Tab, MenuItem, Tag, Row diff --git a/.changeset/bump-bfj-v9.md b/.changeset/bump-bfj-v9.md deleted file mode 100644 index 63309e4657..0000000000 --- a/.changeset/bump-bfj-v9.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Updated dependency `bfj` to `^9.0.2`. diff --git a/.changeset/bump-glob-rollup-security.md b/.changeset/bump-glob-rollup-security.md new file mode 100644 index 0000000000..1738169fd1 --- /dev/null +++ b/.changeset/bump-glob-rollup-security.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-catalog-backend': patch +'@backstage/cli-module-auth': patch +'@backstage/cli-module-build': patch +'@backstage/cli-module-test-jest': patch +'@backstage/cli': patch +'@backstage/ui': patch +'@backstage/repo-tools': patch +--- + +Bumped `glob` dependency from v7/v8/v11 to v13 to address security vulnerabilities in older versions. Bumped `rollup` from v4.27 to v4.59+ to fix a high severity path traversal vulnerability (GHSA-mw96-cpmx-2vgc). diff --git a/.changeset/bumpy-colts-teach.md b/.changeset/bumpy-colts-teach.md deleted file mode 100644 index e3457127ce..0000000000 --- a/.changeset/bumpy-colts-teach.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed neutral-1 hover & pressed state in light mode. diff --git a/.changeset/bumpy-keys-pay.md b/.changeset/bumpy-keys-pay.md deleted file mode 100644 index fdd698fd7b..0000000000 --- a/.changeset/bumpy-keys-pay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-gitlab': patch ---- - -Added new `gitlab:group:access` scaffolder action to add or remove users and groups as members of GitLab groups. The action supports specifying members via `userIds` and/or `groupIds` array parameters, configurable access levels (Guest, Reporter, Developer, Maintainer, Owner), and defaults to the 'add' action when not specified. diff --git a/.changeset/by-refs-predicate-backend.md b/.changeset/by-refs-predicate-backend.md deleted file mode 100644 index a2a0346122..0000000000 --- a/.changeset/by-refs-predicate-backend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Added support for predicate-based filtering on the `/entities/by-refs` endpoint via the `query` field in the request body. Supports `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. diff --git a/.changeset/by-refs-predicate-client.md b/.changeset/by-refs-predicate-client.md deleted file mode 100644 index 5ed136fbe1..0000000000 --- a/.changeset/by-refs-predicate-client.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-client': minor ---- - -Added support for the `query` field in `getEntitiesByRefs` requests, enabling predicate-based filtering with `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. diff --git a/.changeset/calm-vans-play.md b/.changeset/calm-vans-play.md deleted file mode 100644 index 0b7571da7b..0000000000 --- a/.changeset/calm-vans-play.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Migrated all components from `useStyles` to `useDefinition` hook. Exported `OwnProps` types for each component, enabling better type composition for consumers. - -**Affected components:** Avatar, Checkbox, Container, Dialog, FieldError, FieldLabel, Flex, FullPage, Grid, HeaderPage, Link, Menu, PasswordField, PluginHeader, Popover, RadioGroup, SearchField, Select, Skeleton, Switch, Table, TablePagination, Tabs, TagGroup, Text, TextField, ToggleButton, ToggleButtonGroup, Tooltip, VisuallyHidden diff --git a/.changeset/card-hybrid-click.md b/.changeset/card-hybrid-click.md deleted file mode 100644 index 48343c72a7..0000000000 --- a/.changeset/card-hybrid-click.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Fixed interactive cards so that CardBody can scroll when the card has a constrained height. Previously, the overlay element blocked scroll events. - -**Affected components:** Card diff --git a/.changeset/catalog-entity-page-no-header.md b/.changeset/catalog-entity-page-no-header.md new file mode 100644 index 0000000000..51cda8f087 --- /dev/null +++ b/.changeset/catalog-entity-page-no-header.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Disabled the default page layout header for the catalog entity page in the new frontend system. The entity page already renders its own header through the `EntityHeader` extension, so the page layout header was redundant. diff --git a/.changeset/catalog-exists-query-optimization.md b/.changeset/catalog-exists-query-optimization.md new file mode 100644 index 0000000000..e0eb2cbb31 --- /dev/null +++ b/.changeset/catalog-exists-query-optimization.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Improved catalog entity filter query performance by switching from `IN (subquery)` to `EXISTS (correlated subquery)` patterns. This enables PostgreSQL semi-join optimizations and fixes `NOT IN` NULL-semantics pitfalls by using `NOT EXISTS` instead. diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md new file mode 100644 index 0000000000..fac437c641 --- /dev/null +++ b/.changeset/catalog-graph-nfs-page.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/catalog-import-nfs-page.md b/.changeset/catalog-import-nfs-page.md new file mode 100644 index 0000000000..2944565205 --- /dev/null +++ b/.changeset/catalog-import-nfs-page.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/catalog-search-table-sync.md b/.changeset/catalog-search-table-sync.md new file mode 100644 index 0000000000..3a3bcea96a --- /dev/null +++ b/.changeset/catalog-search-table-sync.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Reduced search table write churn during stitching by syncing only changed rows instead of doing a full delete and re-insert. On Postgres this uses a single writable CTE, on MySQL a temporary table merge with deadlock retry, and on SQLite the previous bulk replace. diff --git a/.changeset/chatty-cups-create.md b/.changeset/chatty-cups-create.md new file mode 100644 index 0000000000..0fa05b14f3 --- /dev/null +++ b/.changeset/chatty-cups-create.md @@ -0,0 +1,24 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING**: The `Header` component's `tabs` prop now uses `HeaderNavTabItem[]` instead of `HeaderTab[]`. Tabs render as a `
- + Components
{components.map(item => { @@ -92,6 +92,29 @@ export const Navigation = ({ onLinkClick }: NavigationProps) => { ); })} +
+ Hooks +
+ {hooks.map(item => { + const isActive = pathname === `/hooks/${item.slug}`; + return ( + +
{item.title}
+
+ {item.status === 'alpha' && 'Alpha'} + {item.status === 'beta' && 'Beta'} + {item.status === 'inProgress' && 'In Progress'} + {item.status === 'stable' && 'Stable'} + {item.status === 'deprecated' && 'Deprecated'} +
+ + ); + })} ); }; diff --git a/docs-ui/src/utils/changelog.ts b/docs-ui/src/utils/changelog.ts index a99c0e8335..21ffa93651 100644 --- a/docs-ui/src/utils/changelog.ts +++ b/docs-ui/src/utils/changelog.ts @@ -1,4 +1,6 @@ export * from './types'; +import { changelog_0_13_0 } from './changelogs/v0.13.0'; +import { changelog_0_12_0 } from './changelogs/v0.12.0'; import { changelog_0_11_0 } from './changelogs/v0.11.0'; import { changelog_0_10_0 } from './changelogs/v0.10.0'; import { changelog_0_9_1 } from './changelogs/v0.9.1'; @@ -18,6 +20,8 @@ import { changelog_0_2_0 } from './changelogs/v0.2.0'; import { changelog_0_1_0 } from './changelogs/v0.1.0'; export const changelog = [ + ...changelog_0_13_0, + ...changelog_0_12_0, ...changelog_0_11_0, ...changelog_0_10_0, ...changelog_0_9_1, diff --git a/docs-ui/src/utils/changelogs/v0.12.0.ts b/docs-ui/src/utils/changelogs/v0.12.0.ts new file mode 100644 index 0000000000..f83920c36f --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.12.0.ts @@ -0,0 +1,526 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_12_0: ChangelogProps[] = [ + { + components: ['alert'], + version: '0.12.0', + prs: ['32711'], + description: `**BREAKING**: Alert no longer accepts a \`surface\` prop + + The Alert component's background is now driven entirely by its \`status\` prop. The \`surface\` prop has been removed. + + \`\`\`diff + - + + + \`\`\``, + breaking: true, + commitSha: '46a9adc', + }, + { + components: [], + version: '0.12.0', + prs: ['32723'], + description: `**BREAKING**: Removed gray scale tokens and renamed background surface tokens to neutral tokens + + The \`--bui-gray-1\` through \`--bui-gray-8\` tokens have been removed. The \`--bui-bg-surface-*\` and \`--bui-bg-neutral-on-surface-*\` tokens have been replaced by a unified \`--bui-bg-neutral-*\` scale.`, + migration: `Replace surface tokens directly: + +\`\`\`diff +- background: var(--bui-bg-surface-0); ++ background: var(--bui-bg-neutral-0); +\`\`\` + +Replace on-surface tokens shifted by +1: + +\`\`\`diff +- background: var(--bui-bg-neutral-on-surface-0); ++ background: var(--bui-bg-neutral-1); +\`\`\` + +Replace gray tokens 1-4 with neutral equivalents (\`--bui-gray-5\` through \`--bui-gray-8\` have no direct replacement): + +\`\`\`diff +- background: var(--bui-gray-1); ++ background: var(--bui-bg-neutral-1); +\`\`\``, + breaking: true, + commitSha: 'b63c25b', + }, + { + components: [ + 'box', + 'button', + 'button-icon', + 'button-link', + 'toggle-button', + 'card', + 'flex', + 'grid', + ], + version: '0.12.0', + prs: ['32711'], + description: `**BREAKING**: Replaced \`Surface\` / \`onSurface\` system with new provider/consumer background system + + The old \`Surface\` type (\`'0'\`–\`'3'\`, \`'auto'\`) and its associated props (\`surface\`, \`onSurface\`) have been replaced by a provider/consumer \`bg\` architecture. + + **Types:** + + - \`ContainerBg\` — \`'neutral-1'\` | \`'neutral-2'\` | \`'neutral-3'\` | \`'danger'\` | \`'warning'\` | \`'success'\` + - \`ProviderBg\` — \`ContainerBg | 'neutral-auto'\` + + Consumer components (e.g. Button) inherit the parent's \`bg\` via \`data-on-bg\`, and CSS handles the visual step-up. See "Neutral level capping" below for details on how levels are bounded. + + **Hooks:** + + - \`useBgProvider(bg?)\` — for provider components. Returns \`{ bg: undefined }\` when no \`bg\` is given (transparent). Supports \`'neutral-auto'\` to auto-increment from the parent context. + - \`useBgConsumer()\` — for consumer components. Returns the parent container's \`bg\` unchanged. + + **Component roles:** + + - **Provider-only** (Box, Flex, Grid): set \`data-bg\`, wrap children in \`BgProvider\`. **Transparent by default** — they do _not_ auto-increment; pass \`bg="neutral-auto"\` explicitly if you want automatic neutral stepping. + - **Consumer-only** (Button, ButtonIcon, ButtonLink): set \`data-on-bg\`, inherit the parent container's \`bg\` unchanged. + - **Provider + Consumer** (Card): sets both \`data-bg\` and \`data-on-bg\`, wraps children. Card passes \`bg="neutral-auto"\` to its inner Box, so it auto-increments from the parent context. + + **Neutral level capping:** + + Provider components cap at \`neutral-3\`. There is no \`neutral-4\` prop value. The \`neutral-4\` level exists only in consumer component CSS — for example, a Button sitting on a \`neutral-3\` surface uses \`neutral-4\` tokens internally via \`data-on-bg\`.`, + migration: `Rename the \`surface\` prop to \`bg\` on provider components and update values: + +\`\`\`diff +- ++ + +- ++ + +- ++ + +- ++ +\`\`\` + +Remove \`onSurface\` from consumer components — they now always inherit from the parent container: + +\`\`\`diff +- ++ +\`\`\``, + breaking: true, + commitSha: '058ffd9', + }, + { + components: ['link'], + version: '0.12.0', + prs: ['32608'], + description: `**BREAKING**: Removed link and tint color tokens, added new status foreground tokens, and improved Link component styling + + The following color tokens have been removed: + + - \`--bui-fg-link\` (and all related tokens: \`-hover\`, \`-pressed\`, \`-disabled\`) + - \`--bui-fg-tint\` (and all related tokens: \`-hover\`, \`-pressed\`, \`-disabled\`) + - \`--bui-bg-tint\` (and all related tokens: \`-hover\`, \`-pressed\`, \`-disabled\`) + - \`--bui-border-tint\` (and all related tokens) + + **New Status Tokens:** + + Added dedicated tokens for status colors that distinguish between usage on status backgrounds vs. standalone usage: + + - \`--bui-fg-danger-on-bg\` / \`--bui-fg-danger\` + - \`--bui-fg-warning-on-bg\` / \`--bui-fg-warning\` + - \`--bui-fg-success-on-bg\` / \`--bui-fg-success\` + - \`--bui-fg-info-on-bg\` / \`--bui-fg-info\` + + The \`-on-bg\` variants are designed for text on colored backgrounds, while the base variants are for standalone status indicators with improved visibility and contrast.`, + migration: `For link colors, migrate to one of the following alternatives: + +\`\`\`diff +.custom-link { +- color: var(--bui-fg-link); ++ color: var(--bui-fg-info); /* For informational links */ ++ /* or */ ++ color: var(--bui-fg-primary); /* For standard text links */ +} +\`\`\` + +For tint colors (backgrounds, foregrounds, borders), migrate to appropriate status or neutral colors: + +\`\`\`diff +.info-section { +- background: var(--bui-bg-tint); ++ background: var(--bui-bg-info); /* For informational sections */ ++ /* or */ ++ background: var(--bui-bg-neutral-1); /* For neutral emphasis */ +} +\`\`\` + +If you're using status foreground colors on colored backgrounds, update to the new \`-on-bg\` tokens: + +\`\`\`diff +.error-badge { +- color: var(--bui-fg-danger); ++ color: var(--bui-fg-danger-on-bg); + background: var(--bui-bg-danger); +} +\`\`\``, + breaking: true, + commitSha: '110fec0', + }, + { + components: ['full-page'], + version: '0.12.0', + prs: ['32822'], + description: `Added a new \`FullPage\` component that fills the remaining viewport height below the \`PluginHeader\`. + + \`\`\`tsx + + + {/* content fills remaining height */} + + \`\`\``, + + commitSha: '644e303', + }, + { + components: [], + version: '0.12.0', + prs: ['32825'], + description: `Fixed dark theme \`--bui-fg-secondary\` and \`--bui-fg-disabled\` tokens using black-based \`oklch(0% ...)\` instead of white-based \`oklch(100% ...)\`, making secondary and disabled text visible on dark backgrounds.`, + + commitSha: '44877e4', + }, + { + components: ['box'], + version: '0.12.0', + prs: ['32536'], + description: `Fixed Box component to forward HTML attributes to the underlying div element.`, + + commitSha: '350c948', + }, + { + components: [], + version: '0.12.0', + prs: ['32516'], + description: `Use node prefix on native imports`, + + commitSha: '7455dae', + }, + { + components: ['accordion'], + version: '0.12.0', + prs: ['32488'], + description: `Fixed nested Accordion icon state issue where the inner accordion's arrow icon would incorrectly show as expanded when only the outer accordion was expanded. The CSS selector now uses a direct parent selector to ensure the icon only responds to its own accordion's expanded state.`, + + commitSha: 'c8ae765', + }, + { + components: ['popover', 'tooltip'], + version: '0.12.0', + prs: ['32575'], + description: `Fixed CSS Module syntax to comply with Next.js 16 Turbopack validation by flattening nested dark theme selectors.`, + + commitSha: '4d1b7f4', + }, + { + components: ['button'], + version: '0.12.0', + prs: ['32554'], + description: `Added \`destructive\` prop to Button for dangerous actions like delete or remove. Works with all variants (primary, secondary, tertiary).`, + + commitSha: '2c219b9', + }, + { + components: [], + version: '0.12.0', + prs: ['32553'], + description: `Fixed \`useDefinition\` hook adding literal "undefined" class name when no className prop was passed.`, + + commitSha: '5af9e14', + }, + { + components: ['tag'], + version: '0.12.0', + prs: ['32742'], + description: `Allow \`ref\` as a prop on the \`Tag\` component`, + + commitSha: '5c76d13', + }, + { + components: [], + version: '0.12.0', + prs: ['32799'], + description: `Cleaned up \`useDefinition\` \`ownProps\` types to remove never-typed ghost properties from autocomplete.`, + + commitSha: 'ab25658', + }, + { + components: ['table'], + version: '0.12.0', + prs: ['32685'], + description: `Allow data to be passed directly to the \`useTable\` hook using the property \`data\` instead of \`getData()\` for mode \`"complete"\`. + + This simplifies usage as data changes, rather than having to perform a \`useEffect\` when data changes, and then reloading the data. It also happens immediately, so stale data won't remain until a rerender (with an internal async state change), so less flickering.`, + + commitSha: '741a98d', + }, + { + components: ['table'], + version: '0.12.0', + prs: ['32684'], + description: `Fixed changing columns after first render from crashing. It now renders the table with the new column layout as columns change.`, + + commitSha: 'a0fe1b2', + }, + { + components: ['alert'], + version: '0.12.0', + prs: ['32520'], + description: `Added new \`Alert\` component with support for status variants (info, success, warning, danger), icons, loading states, and custom actions. + + Updated status color tokens for improved contrast and consistency across light and dark themes: + + - Added new \`--bui-bg-info\` and \`--bui-fg-info\` tokens for info status + - Updated \`--bui-bg-danger\`, \`--bui-fg-danger\` tokens + - Updated \`--bui-bg-warning\`, \`--bui-fg-warning\` tokens + - Updated \`--bui-bg-success\`, \`--bui-fg-success\` tokens`, + + commitSha: '508bd1a', + }, + { + components: [ + 'tabs', + 'tab', + 'tag-group', + 'tag', + 'menu', + 'menu-item', + 'menu-autocomplete', + ], + version: '0.12.0', + prs: ['32373'], + description: `Fixed client-side navigation for container components by wrapping the container (not individual items) in RouterProvider. Components now conditionally provide routing context only when children have internal links, removing the Router context requirement when not needed. This also removes the need to wrap these components in MemoryRouter during tests when they are not using the \`href\` prop. + + Additionally, when multiple tabs match the current URL via prefix matching, the tab with the most specific path (highest segment count) is now selected. For example, with URL \`/catalog/users/john\`, a tab with path \`/catalog/users\` is now selected over a tab with path \`/catalog\`.`, + + commitSha: 'da30862', + }, + { + components: [], + version: '0.12.0', + prs: ['32540'], + description: `Fixed an infinite render loop in Tabs when navigating to a URL that doesn't match any tab \`href\`.`, + + commitSha: '092c453', + }, + { + components: [], + version: '0.12.0', + prs: ['32643'], + description: `export PasswordField component`, + + commitSha: 'becf851', + }, + { + components: [], + version: '0.12.0', + prs: ['32843'], + description: `Migrated Accordion components to use \`useDefinition\` instead of \`useStyles\`, and added automatic background adaptation based on parent container context.`, + + commitSha: 'becee36', + }, + { + components: ['link', 'button-link', 'row'], + version: '0.12.0', + prs: ['32373'], + description: `Fixed components to not require a Router context when rendering without internal links.`, + + commitSha: '5320aa8', + }, + { + components: [], + version: '0.12.0', + prs: ['31818'], + description: `Updated \`react-router-dom\` peer dependency to \`^6.30.2\` and explicitly disabled v7 future flags to suppress deprecation warnings.`, + + commitSha: 'a7e0d50', + }, + { + components: ['table'], + version: '0.12.0', + prs: ['32686'], + description: `The Table component now wraps the react-aria-components \`Table\` with a \`ResizableTableContainer\` only if any column has a width property set. This means that column widths can adapt to the content otherwise (if no width is explicitly set).`, + + commitSha: '8c39412', + }, + { + components: [], + version: '0.12.0', + prs: ['32537'], + description: `Bump react-aria-components to v1.14.0`, + + commitSha: 'cb090b4', + }, + { + components: [], + version: '0.12.0', + prs: ['32428'], + description: `Fixed React 17 compatibility by using \`useId\` from \`react-aria\` instead of the built-in React hook which is only available in React 18+.`, + + commitSha: 'c429101', + }, + { + components: ['switch'], + version: '0.12.0', + prs: ['32551'], + description: `Fixed Switch component disabled state styling to show \`not-allowed\` cursor and disabled text color.`, + + commitSha: '74c5a76', + }, + { + components: [], + version: '0.12.0', + prs: ['32761'], + description: `Migrated to use the standard \`backstage-cli package build\` for CSS bundling instead of a custom build script.`, + + commitSha: '20131c5', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.13.0.ts b/docs-ui/src/utils/changelogs/v0.13.0.ts new file mode 100644 index 0000000000..8b4f93afda --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.13.0.ts @@ -0,0 +1,527 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_13_0: ChangelogProps[] = [ + { + components: [ + 'box', + 'flex', + 'grid', + 'card', + 'accordion', + 'popover', + 'tooltip', + 'dialog', + 'menu', + ], + version: '0.13.0', + prs: ['33002'], + description: `**BREAKING**: Simplified the neutral background prop API for container components. The explicit \`neutral-1\`, \`neutral-2\`, \`neutral-3\`, and \`neutral-auto\` values have been removed from \`ProviderBg\`. They are replaced by a single \`'neutral'\` value that always auto-increments from the parent context, making it impossible to skip or pin to an explicit neutral level.`, + migration: `Replace any explicit \`bg="neutral-1"\`, \`bg="neutral-2"\`, \`bg="neutral-3"\`, or \`bg="neutral-auto"\` props with \`bg="neutral"\`. To achieve a specific neutral level in stories or tests, use nested containers — each additional \`bg="neutral"\` wrapper increments by one level. + +\`\`\`tsx +// Before +... + +// After + + ... + +\`\`\``, + breaking: true, + commitSha: '768f09d', + }, + { + components: ['popover', 'tooltip', 'menu', 'dialog'], + version: '0.13.0', + prs: ['32979'], + description: `**BREAKING**: Removed \`--bui-bg-popover\` CSS token. Popover, Tooltip, Menu, and Dialog now use \`--bui-bg-app\` for their outer shell and \`Box bg="neutral-1"\` for content areas, providing better theme consistency and eliminating a redundant token.`, + migration: `Replace any usage of \`--bui-bg-popover\` with \`--bui-bg-neutral-1\` (for content surfaces) or \`--bui-bg-app\` (for outer shells): + +\`\`\`diff +- background: var(--bui-bg-popover); ++ background: var(--bui-bg-neutral-1); +\`\`\``, + breaking: true, + commitSha: 'b42fcdc', + }, + { + components: ['searchfield'], + version: '0.13.0', + prs: ['33050'], + description: `**BREAKING**: Data attributes rendered by components are now always lowercase. This affects CSS selectors targeting camelCase data attributes.`, + migration: `Update any custom CSS selectors that target camelCase data attributes to use lowercase instead: + +\`\`\`diff +- [data-startCollapsed='true'] { ... } ++ [data-startcollapsed='true'] { ... } +\`\`\``, + breaking: true, + commitSha: 'bd3a76e', + }, + { + components: [], + version: '0.13.0', + prs: ['33050'], + description: `**BREAKING**: Removed deprecated types \`ComponentDefinition\`, \`ClassNamesMap\`, \`DataAttributeValues\`, and \`DataAttributesMap\` from the public API. These were internal styling infrastructure types that have been replaced by the \`defineComponent\` system.`, + migration: `Remove any direct usage of these types. Component definitions now use \`defineComponent()\` and their shapes are not part of the public API contract. + +\`\`\`diff +- import type { ComponentDefinition, ClassNamesMap } from '@backstage/ui'; +\`\`\` + +If you were reading \`definition.dataAttributes\`, use \`definition.propDefs\` instead — props with \`dataAttribute: true\` in \`propDefs\` are the equivalent.`, + breaking: true, + commitSha: '95702ab', + }, + { + components: ['link', 'button-link', 'tabs', 'menu', 'tag-group', 'table'], + version: '0.13.0', + prs: ['33267'], + description: `**BREAKING**: Centralized client-side routing in \`BUIProvider\`. Components like Link, ButtonLink, Tabs, Menu, TagGroup, and Table now require a \`BUIProvider\` rendered inside a React Router context for client-side navigation to work.`, + migration: `This change requires updating \`@backstage/plugin-app\` and \`@backstage/core-app-api\` alongside \`@backstage/ui\`. If you only upgrade \`@backstage/ui\`, BUI components will fall back to full-page navigation. + +If you cannot upgrade all packages together, or if you have a custom app shell, add a \`BUIProvider\` inside your Router: + +\`\`\`diff ++ import { BUIProvider } from '@backstage/ui'; + + ++ + ++ + +\`\`\``, + breaking: true, + commitSha: '42f8c9b', + }, + { + components: ['header'], + version: '0.13.0', + prs: ['33354'], + description: `**BREAKING**: Renamed internal CSS classes to match the \`Header\` component name. + + **Migration:** If you are targeting these classes directly in your styles, update the following: + + - \`bui-HeaderPage\` → \`bui-Header\` + - \`bui-HeaderPageContent\` → \`bui-HeaderContent\` + - \`bui-HeaderPageBreadcrumbs\` → \`bui-HeaderBreadcrumbs\` + - \`bui-HeaderPageTabsWrapper\` → \`bui-HeaderTabsWrapper\` + - \`bui-HeaderPageControls\` → \`bui-HeaderControls\``, + breaking: true, + commitSha: '17d6398', + }, + { + components: ['checkbox'], + version: '0.13.0', + prs: ['33323'], + description: `Removed redundant \`selected\` and \`indeterminate\` props from the \`Checkbox\` component. Use the \`isSelected\` and \`isIndeterminate\` props instead, which are the standard React Aria props and already handle both the checkbox behaviour and the corresponding CSS data attributes.`, + migration: `Replace any usage of the \`selected\` and \`indeterminate\` props on \`Checkbox\` with the \`isSelected\` and \`isIndeterminate\` props. Note that the checked state and related CSS data attributes (such as \`data-selected\` and \`data-indeterminate\`) are now driven by React Aria, so any custom logic that previously inspected or set these via the old props should instead rely on the React Aria-managed state and attributes exposed through the new props.`, + breaking: true, + commitSha: '9d5f3ba', + }, + { + components: ['list', 'list-row'], + version: '0.13.0', + prs: ['33358'], + description: `Added \`List\` and \`ListRow\` components. These provide a standalone, accessible list of interactive rows built on top of React Aria's \`GridList\` and \`GridListItem\` primitives. Rows support icons, descriptions, actions, menus, and single or multiple selection modes.`, + + commitSha: '04d9d8d', + }, + { + components: ['accordion'], + version: '0.13.0', + prs: ['32935'], + description: `Made Accordion a \`bg\` provider so nested components like Button auto-increment their background level. Updated \`useDefinition\` to resolve \`bg\` \`propDef\` defaults for provider components.`, + + commitSha: 'a1f4bee', + }, + { + components: ['card'], + version: '0.13.0', + prs: ['33116'], + description: `Added interactive support to the \`Card\` component. Pass \`onPress\` to make the entire card surface pressable, or \`href\` to make it navigate to a URL. A transparent overlay handles the interaction while nested buttons and links remain independently clickable.`, + + commitSha: 'db92751', + }, + { + components: ['link', 'button-link', 'tab', 'menu-item', 'tag', 'row'], + version: '0.13.0', + prs: ['33150'], + description: `Added analytics capabilities to the component library. Components with navigation behavior (Link, ButtonLink, Tab, MenuItem, Tag, Row) now fire analytics events on click when a \`BUIProvider\` is present. + + New exports: \`BUIProvider\`, \`useAnalytics\`, \`getNodeText\`, and associated types (\`AnalyticsTracker\`, \`UseAnalyticsFn\`, \`BUIProviderProps\`, \`AnalyticsEventAttributes\`). + + Components with analytics support now accept a \`noTrack\` prop to suppress event firing.`, + + commitSha: '12d8afe', + }, + { + components: ['table-root'], + version: '0.13.0', + prs: ['33322'], + description: `Added a \`loading\` prop and \`data-loading\` data attribute to \`TableRoot\`, allowing consumers to distinguish between stale data and initial loading states. Both \`stale\` and \`loading\` set \`aria-busy\` on the table.`, + + commitSha: 'b838cc9', + }, + { + components: ['table'], + version: '0.13.0', + prs: ['33322'], + description: `Improved the \`Table\` component loading state to show a skeleton UI with visible headers instead of plain "Loading..." text. The table now renders its full structure during loading, with animated skeleton rows in place of data. The loading state includes proper accessibility support with \`aria-busy\` on the table and screen reader announcements.`, + + commitSha: '690786f', + }, + { + components: [], + version: '0.13.0', + prs: ['33078'], + description: `Fixed neutral-1 hover & pressed state in light mode.`, + + commitSha: '58224d3', + }, + { + components: [ + 'avatar', + 'checkbox', + 'container', + 'dialog', + 'field-error', + 'field-label', + 'flex', + 'full-page', + 'grid', + 'header-page', + 'link', + 'menu', + 'password-field', + 'plugin-header', + 'popover', + 'radio-group', + 'searchfield', + 'select', + 'skeleton', + 'switch', + 'table', + 'table-pagination', + 'tabs', + 'tag-group', + 'text', + 'textfield', + 'toggle-button', + 'toggle-button-group', + 'tooltip', + 'visually-hidden', + ], + version: '0.13.0', + prs: ['33050'], + description: `Migrated all components from \`useStyles\` to \`useDefinition\` hook. Exported \`OwnProps\` types for each component, enabling better type composition for consumers.`, + + commitSha: '95702ab', + }, + { + components: ['card'], + version: '0.13.0', + prs: ['33151'], + description: `Fixed interactive cards so that CardBody can scroll when the card has a constrained height. Previously, the overlay element blocked scroll events.`, + + commitSha: '430d5ed', + }, + { + components: ['container'], + version: '0.13.0', + prs: ['32984'], + description: `Removed the \`transition\` on \`Container\` padding to prevent an unwanted animation when the viewport is resized.`, + + commitSha: '4c2c350', + }, + { + components: [], + version: '0.13.0', + prs: ['32542'], + description: `Fixed --bui-fg-success token in light mode to be more accessible.`, + + commitSha: 'e0b7eb0', + }, + { + components: [], + version: '0.13.0', + prs: ['33188'], + description: `Deprecated the \`HeaderPage\` component name in favor of \`Header\`. The old \`HeaderPage\`, \`HeaderPageProps\`, \`HeaderPageOwnProps\`, \`HeaderPageBreadcrumb\`, and \`HeaderPageDefinition\` exports are still available as deprecated aliases.`, + + commitSha: 'ad7c883', + }, + { + components: [], + version: '0.13.0', + prs: ['33379'], + description: `Added documentation for the table cell wrapper requirement to TSDoc comments for \`Cell\`, \`CellText\`, \`CellProfile\`, \`ColumnConfig\`, and \`RowRenderFn\`.`, + + commitSha: '0ebde15', + }, + { + components: ['search-autocomplete', 'search-autocomplete-item'], + version: '0.13.0', + prs: ['33340'], + description: `Added \`SearchAutocomplete\` and \`SearchAutocompleteItem\` components for building accessible search-with-results patterns. Built on React Aria's Autocomplete with keyboard navigation and screen reader support. Designed for async/external search results with a configurable popover width.`, + + commitSha: 'd9d2dd6', + }, + { + components: ['checkbox'], + version: '0.13.0', + prs: ['33394'], + description: `Made Checkbox \`children\` optional and added a dev warning when neither a visible label, \`aria-label\`, nor \`aria-labelledby\` is provided. The label wrapper div is no longer rendered when there are no children, removing the unnecessary gap.`, + + commitSha: 'a6b84e1', + }, + { + components: ['dialog'], + version: '0.13.0', + prs: ['33352'], + description: `Fixed \`Dialog\` content overflowing when no \`height\` prop is set. The dialog now grows with its content and scrolls when content exceeds the viewport height.`, + + commitSha: 'b99f6d5', + }, + { + components: [ + 'accordion', + 'button', + 'button-icon', + 'button-link', + 'card', + 'list', + 'menu', + 'select', + 'toggle-button-group', + ], + version: '0.13.0', + prs: ['33358'], + description: `Fixed focus ring styles to use React Aria's \`[data-focus-visible]\` data attribute instead of the native CSS \`:focus-visible\` pseudo-class. This ensures keyboard focus rings render reliably when focus is managed programmatically by React Aria (e.g. inside a GridList, Menu, or Select).`, + + commitSha: '2f581de', + }, + { + components: ['container', 'header'], + version: '0.13.0', + prs: ['33354'], + description: `Fixed incorrect bottom spacing caused by \`Container\` using \`padding-bottom\` for its default bottom spacing. Changed to \`margin-bottom\` and prevented it from applying when \`Container\` is used as the \`Header\` root element.`, + + commitSha: '17d6398', + }, + { + components: ['plugin-header'], + version: '0.13.0', + prs: ['33368'], + description: `Fixed \`PluginHeader\` to avoid triggering \`ResizeObserver loop completed with undelivered notifications\` warnings when used in layouts that react to the header height, such as pages that use \`FullPage\`.`, + + commitSha: '2e5c651', + }, + { + components: ['tabs', 'plugin-header'], + version: '0.13.0', + prs: ['33047'], + description: `Fixed tab \`matchStrategy\` matching to ignore query parameters and hash fragments in tab \`href\` values. Previously, tabs with query params in their \`href\` (e.g., \`/page?group=foo\`) would never show as active since matching compared the full \`href\` string against \`location.pathname\` which never includes query params.`, + + commitSha: 'd4fa5b4', + }, + { + components: [], + version: '0.13.0', + prs: ['33363'], + description: `Fixed Table component to use current \`--bui-bg-neutral-1\` tokens instead of the removed \`--bui-bg-tint\` tokens, restoring row hover, selected, pressed, and disabled background colors.`, + + commitSha: 'bc42b60', + }, + { + components: [], + version: '0.13.0', + prs: ['33378'], + description: `Fixed a bug in the \`useTable\` hook where the loading skeleton was never shown for \`complete\` mode when using \`getData\`. The initial data state was an empty array instead of \`undefined\`, causing the \`Table\` component to skip the loading state.`, + + commitSha: '9314ff5', + }, + { + components: ['table'], + version: '0.13.0', + prs: ['33256'], + description: `Fixed Table column headers overflowing and wrapping when there is not enough space. Headers now truncate with ellipsis instead.`, + + commitSha: 'f42f4cc', + }, + { + components: ['row'], + version: '0.13.0', + prs: ['33394'], + description: `Fixed Table row hover, selected, pressed, and disabled background states to use the correct neutral token level based on the container background.`, + + commitSha: '1f9682b', + }, + { + components: ['row'], + version: '0.13.0', + prs: ['33256'], + description: `Fixed Table rows showing a pointer cursor when not interactive. Rows now only show \`cursor: pointer\` when they have an \`href\`, are selectable, or are pressable.`, + + commitSha: 'fbd5c5a', + }, + { + components: ['row'], + version: '0.13.0', + prs: ['33353'], + description: `Fixed \`Table\` rows with external \`href\` values to open in a new tab by automatically applying \`target="_blank"\` and \`rel="noopener noreferrer"\`.`, + + commitSha: '612c217', + }, + { + components: ['table'], + version: '0.13.0', + prs: ['33394'], + description: `Updated Table selection checkboxes to use \`aria-label\` instead of empty fragment children, improving accessibility and removing the unnecessary label gap in the selection cells.`, + + commitSha: '545129a', + }, + { + components: ['button', 'button-icon', 'button-link'], + version: '0.13.0', + prs: ['33095'], + description: `Fixed handling of the \`style\` prop on \`Button\`, \`ButtonIcon\`, and \`ButtonLink\` so that it is now correctly forwarded to the underlying element instead of being silently dropped.`, + + commitSha: '36987db', + }, + { + components: ['link'], + version: '0.13.0', + prs: ['33050'], + description: `Fixed Link variant default from \`'body'\` to \`'body-medium'\` to match actual CSS selectors. The previous default did not correspond to a valid variant value.`, + + commitSha: '95702ab', + }, + { + components: ['menu', 'select'], + version: '0.13.0', + prs: ['33049'], + description: `Fixed scroll overflow in Menu and Select popover content when constrained by viewport height.`, + + commitSha: '9027b10', + }, + { + components: ['flex', 'grid', 'grid-item'], + version: '0.13.0', + prs: ['33136'], + description: `Added support for native HTML div attributes on the \`Flex\`, \`Grid\`, and \`Grid.Item\` components.`, + + commitSha: '7960d54', + }, + { + components: [], + version: '0.13.0', + prs: ['33246'], + description: `Added \`virtualized\` prop to \`Table\` component for virtualized rendering of large datasets. Accepts \`true\` for default row height, \`{ rowHeight: number }\` for fixed height, or \`{ estimatedRowHeight: number }\` for variable height rows.`, + + commitSha: '0559408', + }, + { + components: ['menu', 'select'], + version: '0.13.0', + prs: ['32983'], + description: `Fixed focus-visible outline styles for Menu and Select components.`, + + commitSha: '8909359', + }, + { + components: [], + version: '0.13.0', + prs: ['33150'], + description: `Fixed MenuItem \`onAction\` prop ordering so user-provided \`onAction\` handlers are chained rather than silently overwritten.`, + + commitSha: '12d8afe', + }, + { + components: [], + version: '0.13.0', + prs: ['33389'], + description: `Pages created with \`PageBlueprint\` now render the plugin header by default in the new frontend system.`, + + commitSha: 'aa29b50', + }, + { + components: ['select'], + version: '0.13.0', + prs: ['33102'], + description: `The \`Select\` trigger now automatically adapts its background colour based on the parent background context.`, + + commitSha: 'bb66b86', + }, + { + components: ['plugin-header'], + version: '0.13.0', + prs: ['33085'], + description: `Merged the internal \`PluginHeaderToolbar\` component into \`PluginHeader\`, removing the separate component and its associated types (\`PluginHeaderToolbarOwnProps\`, \`PluginHeaderToolbarProps\`) and definition (\`PluginHeaderToolbarDefinition\`). This is an internal refactor with no changes to the public API of \`PluginHeader\`.`, + + commitSha: '4105a78', + }, + { + components: [], + version: '0.13.0', + prs: ['33251'], + description: `Updated dependency \`globals\` to \`^17.0.0\`.`, + + commitSha: '9599697', + }, + { + components: [], + version: '0.13.0', + prs: ['32971'], + description: `Improved type safety in \`useDefinition\` by centralizing prop resolution and strengthening the \`BgPropsConstraint\` to require that \`bg\` provider components declare \`children\` as a required prop in their OwnProps type.`, + + commitSha: '0f462f8', + }, + { + components: ['radio-group'], + version: '0.13.0', + prs: ['32983'], + description: `Added proper cursor styles for RadioGroup items.`, + + commitSha: '8909359', + }, + { + components: ['card'], + version: '0.13.0', + prs: ['33343'], + description: `Fixed \`Card\` interactive cards not firing the \`onPress\` handler when clicking the card surface.`, + + commitSha: 'fcaac3b', + }, + { + components: ['textfield', 'searchfield', 'password-field'], + version: '0.13.0', + prs: ['33050'], + description: `Fixed \`isRequired\` prop not being passed to the underlying React Aria field components in TextField, SearchField, and PasswordField. Previously, \`isRequired\` was consumed locally for the secondary label text but never forwarded, which meant the input elements lacked \`aria-required="true"\` and React Aria's built-in required validation was not activated.`, + + commitSha: 'b303857', + }, + { + components: ['searchfield', 'textfield'], + version: '0.13.0', + prs: ['33081'], + description: `\`SearchField\` and \`TextField\` now automatically adapt their background color based on the parent bg context, stepping up one neutral level (e.g. neutral-1 → neutral-2) when placed on a neutral background. \`TextField\` also gains a focus ring using the \`--bui-ring\` token.`, + + commitSha: '934ac03', + }, + { + components: [], + version: '0.13.0', + prs: ['33045'], + description: `Improved \`useBreakpoint\` performance by sharing a single set of \`matchMedia\` listeners across all component instances instead of creating independent listeners per hook call.`, + + commitSha: 'cd3cb0f', + }, + { + components: ['alert', 'container', 'dialog-body', 'field-label'], + version: '0.13.0', + prs: ['33095'], + description: `Extended \`AlertProps\`, \`ContainerProps\`, \`DialogBodyProps\`, and \`FieldLabelProps\` with native div element props to allow passing attributes like \`aria-*\` and \`data-*\`.`, + + commitSha: '36987db', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.9.0.ts b/docs-ui/src/utils/changelogs/v0.9.0.ts index de5c40c5de..e0a3993d33 100644 --- a/docs-ui/src/utils/changelogs/v0.9.0.ts +++ b/docs-ui/src/utils/changelogs/v0.9.0.ts @@ -114,7 +114,7 @@ After: 'switch', 'skeleton', 'plugin-header', - 'header-page', + 'header', 'tabs', ], version: '0.9.0', diff --git a/docs-ui/src/utils/data.ts b/docs-ui/src/utils/data.ts index a1ef483785..bd37760ea4 100644 --- a/docs-ui/src/utils/data.ts +++ b/docs-ui/src/utils/data.ts @@ -62,13 +62,17 @@ export const components: Page[] = [ slug: 'plugin-header', }, { - title: 'HeaderPage', - slug: 'header-page', + title: 'Header', + slug: 'header', }, { title: 'Link', slug: 'link', }, + { + title: 'List', + slug: 'list', + }, { title: 'Menu', slug: 'menu', @@ -85,6 +89,10 @@ export const components: Page[] = [ title: 'RadioGroup', slug: 'radio-group', }, + { + title: 'SearchAutocomplete', + slug: 'search-autocomplete', + }, { title: 'SearchField', slug: 'search-field', @@ -97,6 +105,10 @@ export const components: Page[] = [ title: 'Skeleton', slug: 'skeleton', }, + { + title: 'Slider', + slug: 'slider', + }, { title: 'Switch', slug: 'switch', @@ -138,3 +150,10 @@ export const components: Page[] = [ slug: 'visually-hidden', }, ]; + +export const hooks: Page[] = [ + { + title: 'useBreakpoint', + slug: 'use-breakpoint', + }, +]; diff --git a/docs-ui/src/utils/types.ts b/docs-ui/src/utils/types.ts index ec762536c6..8e03a1df07 100644 --- a/docs-ui/src/utils/types.ts +++ b/docs-ui/src/utils/types.ts @@ -1,5 +1,8 @@ export type Component = | 'accordion' + | 'accordion-group' + | 'accordion-panel' + | 'accordion-trigger' | 'alert' | 'avatar' | 'box' @@ -7,42 +10,93 @@ export type Component = | 'button-icon' | 'button-link' | 'card' + | 'card-body' + | 'card-footer' + | 'card-header' + | 'cell' + | 'cell-profile' + | 'cell-text' | 'checkbox' | 'collapsible' + | 'column' | 'container' | 'datatable' | 'dialog' + | 'dialog-body' + | 'dialog-footer' + | 'dialog-header' + | 'dialog-trigger' + | 'field-error' + | 'field-label' | 'flex' + | 'full-page' | 'grid' - | 'plugin-header' + | 'grid-item' + | 'header' | 'header-page' | 'heading' | 'icon' | 'link' + | 'list' + | 'list-row' | 'menu' + | 'menu-autocomplete' + | 'menu-autocomplete-listbox' + | 'menu-item' + | 'menu-list-box' + | 'menu-list-box-item' + | 'menu-section' + | 'menu-separator' + | 'menu-trigger' | 'password-field' + | 'plugin-header' + | 'popover' + | 'radio' | 'radio-group' + | 'row' | 'scrollarea' + | 'search-autocomplete' + | 'search-autocomplete-item' | 'searchfield' | 'select' | 'skeleton' + | 'submenu-trigger' | 'switch' + | 'tab' + | 'tab-list' + | 'tab-panel' | 'table' + | 'table-body' + | 'table-header' + | 'table-pagination' + | 'table-root' | 'tabs' + | 'tag' | 'tag-group' | 'text' | 'textfield' + | 'toggle-button' + | 'toggle-button-group' | 'tooltip' + | 'tooltip-trigger' | 'visually-hidden'; +export type Hook = 'use-breakpoint'; + export type Version = `${number}.${number}.${number}`; -export interface ChangelogProps { - components: Component[]; +export type AtLeastOne = K extends string + ? Pick & Partial> + : never; + +export type ChangelogProps = { description: string; version: Version; prs: string[]; breaking?: boolean; commitSha?: string; migration?: string; -} +} & AtLeastOne<{ + components: Component[]; + hooks: Hook[]; +}>; diff --git a/docs-ui/yarn.lock b/docs-ui/yarn.lock index f76551a827..085b426dc6 100644 --- a/docs-ui/yarn.lock +++ b/docs-ui/yarn.lock @@ -393,14 +393,14 @@ __metadata: languageName: node linkType: hard -"@eslint/config-array@npm:^0.21.1": - version: 0.21.1 - resolution: "@eslint/config-array@npm:0.21.1" +"@eslint/config-array@npm:^0.21.2": + version: 0.21.2 + resolution: "@eslint/config-array@npm:0.21.2" dependencies: "@eslint/object-schema": "npm:^2.1.7" debug: "npm:^4.3.1" - minimatch: "npm:^3.1.2" - checksum: 10/6eaa0435972f735ce52d581f355a0b616e50a9b8a73304a7015398096e252798b9b3b968a67b524eefb0fdeacc57c4d960f0ec6432abe1c1e24be815b88c5d18 + minimatch: "npm:^3.1.5" + checksum: 10/148477ba995cf57fc725601916d5a7914aa249112d8bec2c3ac9122e2b2f540e6ef013ff4f6785346a4b565f09b20db127fa6f7322f5ffbdb3f1f8d2078a531c languageName: node linkType: hard @@ -422,27 +422,27 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^3.3.1": - version: 3.3.3 - resolution: "@eslint/eslintrc@npm:3.3.3" +"@eslint/eslintrc@npm:^3.3.5": + version: 3.3.5 + resolution: "@eslint/eslintrc@npm:3.3.5" dependencies: - ajv: "npm:^6.12.4" + ajv: "npm:^6.14.0" debug: "npm:^4.3.2" espree: "npm:^10.0.1" globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" js-yaml: "npm:^4.1.1" - minimatch: "npm:^3.1.2" + minimatch: "npm:^3.1.5" strip-json-comments: "npm:^3.1.1" - checksum: 10/b586a364ff15ce1b68993aefc051ca330b1fece15fb5baf4a708d00113f9a14895cffd84a5f24c5a97bd4b4321130ab2314f90aa462a250f6b859c2da2cba1f3 + checksum: 10/edabb65693d82a88cac3b2cf932a0f825e986b5e0a21ef08782d07e3a61ad87d39db67cfd5aeb146fd5053e5e24e389dbe5649ab22936a71d633c7b32a7e6d86 languageName: node linkType: hard -"@eslint/js@npm:9.39.3": - version: 9.39.3 - resolution: "@eslint/js@npm:9.39.3" - checksum: 10/91a1a1822cfeb2eb8a89aae86be5dfabad0b66b0915946516690a8485ddd80b91f43eee346789313fea1acbb7390a4958119ca7dc9a684a5c4014f12fcb3aaf3 +"@eslint/js@npm:9.39.4": + version: 9.39.4 + resolution: "@eslint/js@npm:9.39.4" + checksum: 10/0a7ab4c4108cf2cadf66849ebd20f5957cc53052b88d8807d0b54e489dbf6ffcaf741e144e7f9b187c395499ce2e6ddc565dbfa4f60c6df455cf2b30bcbdc5a3 languageName: node linkType: hard @@ -928,25 +928,25 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:16.1.6": - version: 16.1.6 - resolution: "@next/env@npm:16.1.6" - checksum: 10/52f17ead23b3dc42e613be469b3a179c9c199f43ab42dfcba1f1bc25adba3d7818b4159ab1c797ddfa64a081c21cc1f753a997c14e164d8a88873e0774395d37 +"@next/env@npm:16.2.1": + version: 16.2.1 + resolution: "@next/env@npm:16.2.1" + checksum: 10/c4f19f1767d7a1e8e9ff93cdee7e3b6a923d26d9d71f44124a797f03703ab9a18508b5ede997cc99d0307f2e0d0d1c426e9673a6c11ea10e170b87462a572236 languageName: node linkType: hard -"@next/eslint-plugin-next@npm:16.1.6": - version: 16.1.6 - resolution: "@next/eslint-plugin-next@npm:16.1.6" +"@next/eslint-plugin-next@npm:16.2.1": + version: 16.2.1 + resolution: "@next/eslint-plugin-next@npm:16.2.1" dependencies: fast-glob: "npm:3.3.1" - checksum: 10/74b427e005cd5f0ecf7b557fcbca1780f32b94c6e0fa3a774c20b79391ce660e6b52e2e70022c374f1473000de187188e58c812d53e4db440c3d8ee0848477be + checksum: 10/8892f8ea6b2a642d9284f05098827f6c15acf3c7e2ff592430080355f8eb3cec7a70ba7543960819d69eff4eba75430eb6ce2fee4c8918abf0d8a9366fa0a59a languageName: node linkType: hard -"@next/mdx@npm:16.1.6": - version: 16.1.6 - resolution: "@next/mdx@npm:16.1.6" +"@next/mdx@npm:16.2.1": + version: 16.2.1 + resolution: "@next/mdx@npm:16.2.1" dependencies: source-map: "npm:^0.7.0" peerDependencies: @@ -957,62 +957,62 @@ __metadata: optional: true "@mdx-js/react": optional: true - checksum: 10/830bc4c38f6c38c1420348e96a6f172c88bf32a2dc670f58593b3863bf8f0acd31c0880a231a59257c9f7acaf2a70a9e90e7fae6dd1a3dcf2e0ab3f643cdb1f5 + checksum: 10/eed6747ac8dd048384eb0fd2cc5668bef3e2bc9c27c45a07c03dae8a2466638a26f46b440d6d27546c5f0fafc0df7dbacfe8f503f870e6e77a7c336d915500c4 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-darwin-arm64@npm:16.1.6" +"@next/swc-darwin-arm64@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-darwin-arm64@npm:16.2.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-darwin-x64@npm:16.1.6" +"@next/swc-darwin-x64@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-darwin-x64@npm:16.2.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-linux-arm64-gnu@npm:16.1.6" +"@next/swc-linux-arm64-gnu@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-arm64-gnu@npm:16.2.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-linux-arm64-musl@npm:16.1.6" +"@next/swc-linux-arm64-musl@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-arm64-musl@npm:16.2.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-linux-x64-gnu@npm:16.1.6" +"@next/swc-linux-x64-gnu@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-x64-gnu@npm:16.2.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-linux-x64-musl@npm:16.1.6" +"@next/swc-linux-x64-musl@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-linux-x64-musl@npm:16.2.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-win32-arm64-msvc@npm:16.1.6" +"@next/swc-win32-arm64-msvc@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-win32-arm64-msvc@npm:16.2.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:16.1.6": - version: 16.1.6 - resolution: "@next/swc-win32-x64-msvc@npm:16.1.6" +"@next/swc-win32-x64-msvc@npm:16.2.1": + version: 16.2.1 + resolution: "@next/swc-win32-x64-msvc@npm:16.2.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1191,74 +1191,74 @@ __metadata: languageName: node linkType: hard -"@shikijs/core@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/core@npm:3.22.0" +"@shikijs/core@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/core@npm:3.23.0" dependencies: - "@shikijs/types": "npm:3.22.0" + "@shikijs/types": "npm:3.23.0" "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" hast-util-to-html: "npm:^9.0.5" - checksum: 10/fc716bb042accd5061d0de142ee28c20b6e6d489f6516b901ee4db9ed5d802f59c9033106d8140c111a909b761d79523fced92c1367a6f97c4f0e0dad0f29bc9 + checksum: 10/b692850d79d36f90cb92d517de60c3739e888a3ce0b49450090fa954166eae6655ae1884dbbb971e254b907644cc6aa7757fa84fc2437c45208e09143d4f75ab languageName: node linkType: hard -"@shikijs/engine-javascript@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/engine-javascript@npm:3.22.0" +"@shikijs/engine-javascript@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/engine-javascript@npm:3.23.0" dependencies: - "@shikijs/types": "npm:3.22.0" + "@shikijs/types": "npm:3.23.0" "@shikijs/vscode-textmate": "npm:^10.0.2" oniguruma-to-es: "npm:^4.3.4" - checksum: 10/2fcadb897d0220ca70cc63d697e474ce13addc462a387249a852c882a58b9a1e7d6f9b42f694d324403c4acde8486dd54823228602f5ff4270e4298a43c10f51 + checksum: 10/0ca854fb05a14a97fc83c6a54291af6b387fb1c319bd09426eeca3e0ed597bb0b81a79459838c65d0fadce012ba3f166bebb587828d0cc5511b943c743eae2be languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/engine-oniguruma@npm:3.22.0" +"@shikijs/engine-oniguruma@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/engine-oniguruma@npm:3.23.0" dependencies: - "@shikijs/types": "npm:3.22.0" + "@shikijs/types": "npm:3.23.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10/611654868bc2538ab4d7c3770ad2829a623fcf354ce5c09ba8fde29ecc106b5e4a6270de7d970da4524c1ad00d4f7ed3e5afef2be2ff0b94f8bb8541d0775320 + checksum: 10/edd8983be86f6b055793813e80ecf31c3cefdd896f3742797ae03f2cbb9f467ac736c4b152d4a5c42dbd17da17d24ff798a15d37bcf6205d7f8cd8f44e2a11e0 languageName: node linkType: hard -"@shikijs/langs@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/langs@npm:3.22.0" +"@shikijs/langs@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/langs@npm:3.23.0" dependencies: - "@shikijs/types": "npm:3.22.0" - checksum: 10/091cdaeda7763e1170a6a289315a8371f07af541ad4d8fe17a247b45c4a3be82dc9d321a1e4589cdc8464a694692a5c8bfdd1909372b6ec52b0caa53d69e4a1f + "@shikijs/types": "npm:3.23.0" + checksum: 10/115b1afb9eb4eb300eb68b146e442f7e6d196878798c5b9d75dd53a6ef1e1c3b27e325353a10973e3fa47d88630e937b8a3cf3b37b6eef80bf2aec3d51657bb3 languageName: node linkType: hard -"@shikijs/themes@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/themes@npm:3.22.0" +"@shikijs/themes@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/themes@npm:3.23.0" dependencies: - "@shikijs/types": "npm:3.22.0" - checksum: 10/ba60849b4056ea4e243e2c2047382312e504d10f8e1ee09d73041d9de54bce30e28c79168406d8a8e3b7a7ab19d0f9c610e3469679f96145aa975460ac7e1407 + "@shikijs/types": "npm:3.23.0" + checksum: 10/741987380445b788aea6cc1e03492bc06950f1a0461edf45083bd226889c5ba78c7ed1af9724afacab7d6471777f0c0e8871577183dfb2cfbceb255663374835 languageName: node linkType: hard "@shikijs/transformers@npm:^3.13.0": - version: 3.22.0 - resolution: "@shikijs/transformers@npm:3.22.0" + version: 3.23.0 + resolution: "@shikijs/transformers@npm:3.23.0" dependencies: - "@shikijs/core": "npm:3.22.0" - "@shikijs/types": "npm:3.22.0" - checksum: 10/782569a5a8a09dae18402162ad10bba36d8c4e4b6f01c613ccc8151071b06872c9bc32f06bb31147bb58b545b034cd5340d21b1c80c2862cef3983fac6eaef3c + "@shikijs/core": "npm:3.23.0" + "@shikijs/types": "npm:3.23.0" + checksum: 10/d3c86e75668254beda1d1bbd34a00995f684dffd4efdaf60edaa8284ecc9130255c7615c7bca9400a1c50724dd0cd0133469b6e75ffe2033613fd64dcfca5821 languageName: node linkType: hard -"@shikijs/types@npm:3.22.0": - version: 3.22.0 - resolution: "@shikijs/types@npm:3.22.0" +"@shikijs/types@npm:3.23.0": + version: 3.23.0 + resolution: "@shikijs/types@npm:3.23.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10/c5abd9050d4645bbf9f6c9af1a3df31d24d823d21c232e47b171cc68bd4865adab20533503a5c97ffb9e87eae2f88e7a3835d64a0a8aa11a69dbfd45aabd58bf + checksum: 10/18b5703d445d53dd6782a3e2c7332009302c6c046f301d9cd99f1a26b9c8329b3e502b096894bffac61f78835c533827bab2ce78a39666ab87b78f8d7ca11f7b languageName: node linkType: hard @@ -1534,9 +1534,9 @@ __metadata: languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.25.4": - version: 4.25.4 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.4" +"@uiw/codemirror-extensions-basic-setup@npm:4.25.8": + version: 4.25.8 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.8" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -1553,13 +1553,13 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/8fa523af7cb4ea36db5263221e5a34ecbf18e57ee5c57fbb46f7bfd08ff08523b9fe2c5ae376117d98edaa1a904d1a2966123710e0d866a78ec2d1359955773c + checksum: 10/a8d83465f9f3393b6e95d98ae7f3616ad57f819bce64224831d3db19647524538fc013973074a63551afa69daad9a8ab05f2e5c7441db7e30e722495d7e991d3 languageName: node linkType: hard "@uiw/codemirror-themes@npm:^4.23.7": - version: 4.25.7 - resolution: "@uiw/codemirror-themes@npm:4.25.7" + version: 4.25.8 + resolution: "@uiw/codemirror-themes@npm:4.25.8" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" @@ -1568,19 +1568,19 @@ __metadata: "@codemirror/language": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/6910a41090611b608dfd16eaf82c8e9e9edbab528fe06edfff5947050de6d1363749099a7462ecd3a6544c093feb8d8f1e2c1c7b687b889134c0e59966b1ff1f + checksum: 10/e9983b0f6e663ca200d36437b6b52b4061ce5ccefece6f738b15370a8a7ac6774e7139a82e9e28ae273692e25d0c0804693587ea0967e163a1c7ac8cf3859cd1 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.23.7": - version: 4.25.4 - resolution: "@uiw/react-codemirror@npm:4.25.4" + version: 4.25.8 + resolution: "@uiw/react-codemirror@npm:4.25.8" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.25.4" + "@uiw/codemirror-extensions-basic-setup": "npm:4.25.8" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -1590,7 +1590,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 10/679966cfa5cc2e7d5b7c8b40060018bebfc3a2d66492672c64e659e1c719cedd7a10ed7fb3aa014d77c42927581c4ebdf6760ab56568225781798b35dc13b8c6 + checksum: 10/8c974e22dad1ad6231f33f7db42cd5b68caaf9bea545539b06b8a89dda3427eebadf47c8f48ee0d74cdf5a25000a8fcc02bac9fe560b624955eedf1f9bb47a85 languageName: node linkType: hard @@ -1754,15 +1754,15 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" +"ajv@npm:^6.14.0": + version: 6.14.0 + resolution: "ajv@npm:6.14.0" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10/48d6ad21138d12eb4d16d878d630079a2bda25a04e745c07846a4ad768319533031e28872a9b3c5790fa1ec41aabdf2abed30a56e5a03ebc2cf92184b8ee306c + checksum: 10/c71f14dd2b6f2535d043f74019c8169f7aeb1106bafbb741af96f34fdbf932255c919ddd46344043d03b62ea0ccb319f83667ec5eedf612393f29054fe5ce4a5 languageName: node linkType: hard @@ -1956,12 +1956,12 @@ __metadata: languageName: node linkType: hard -"baseline-browser-mapping@npm:^2.8.3, baseline-browser-mapping@npm:^2.9.0": - version: 2.9.19 - resolution: "baseline-browser-mapping@npm:2.9.19" +"baseline-browser-mapping@npm:^2.9.0, baseline-browser-mapping@npm:^2.9.19": + version: 2.10.8 + resolution: "baseline-browser-mapping@npm:2.10.8" bin: - baseline-browser-mapping: dist/cli.js - checksum: 10/8d7bbb7fe3d1ad50e04b127c819ba6d059c01ed0d2a7a5fc3327e23a8c42855fa3a8b510550c1fe1e37916147e6a390243566d3ef85bf6130c8ddfe5cc3db530 + baseline-browser-mapping: dist/cli.cjs + checksum: 10/820972372c87c65c2e665134d70aa44d5722492fb907aa79170fec84086a75de4675f6a7b717cf0a31b4c4f71cd0289b056b71e32007de97a37973a501d31dcb languageName: node linkType: hard @@ -2336,7 +2336,7 @@ __metadata: "@lezer/highlight": "npm:^1.2.1" "@mdx-js/loader": "npm:^3.1.0" "@mdx-js/react": "npm:^3.1.0" - "@next/mdx": "npm:16.1.6" + "@next/mdx": "npm:16.2.1" "@octokit/rest": "npm:^22.0.1" "@remixicon/react": "npm:^4.6.0" "@shikijs/transformers": "npm:^3.13.0" @@ -2348,10 +2348,10 @@ __metadata: "@uiw/react-codemirror": "npm:^4.23.7" clsx: "npm:^2.1.1" eslint: "npm:^9" - eslint-config-next: "npm:16.1.6" + eslint-config-next: "npm:16.2.1" html-react-parser: "npm:^5.2.5" motion: "npm:^12.4.1" - next: "npm:16.1.6" + next: "npm:16.2.1" next-mdx-remote-client: "npm:^2.1.2" postcss: "npm:^8.5.6" postcss-import: "npm:^16.1.1" @@ -2629,11 +2629,11 @@ __metadata: languageName: node linkType: hard -"eslint-config-next@npm:16.1.6": - version: 16.1.6 - resolution: "eslint-config-next@npm:16.1.6" +"eslint-config-next@npm:16.2.1": + version: 16.2.1 + resolution: "eslint-config-next@npm:16.2.1" dependencies: - "@next/eslint-plugin-next": "npm:16.1.6" + "@next/eslint-plugin-next": "npm:16.2.1" eslint-import-resolver-node: "npm:^0.3.6" eslint-import-resolver-typescript: "npm:^3.5.2" eslint-plugin-import: "npm:^2.32.0" @@ -2648,7 +2648,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/94828d947fe88d921ca9e59931a31d111344bbf23bd8baad50de463b05b23a823c526cb60576443c6c818136d054779970369f049c5c6a6ef7e92fae12f888d7 + checksum: 10/3622048ff1883f801c14a21205e9f92fd83172362d6d006fc7a32ea178687a9e11aff0db3aa5fbfb86b32541b03ac127f12da8da12e8fff4430f4757e0ceecfd languageName: node linkType: hard @@ -2821,22 +2821,22 @@ __metadata: linkType: hard "eslint@npm:^9": - version: 9.39.3 - resolution: "eslint@npm:9.39.3" + version: 9.39.4 + resolution: "eslint@npm:9.39.4" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" - "@eslint/config-array": "npm:^0.21.1" + "@eslint/config-array": "npm:^0.21.2" "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" - "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.3" + "@eslint/eslintrc": "npm:^3.3.5" + "@eslint/js": "npm:9.39.4" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" "@types/estree": "npm:^1.0.6" - ajv: "npm:^6.12.4" + ajv: "npm:^6.14.0" chalk: "npm:^4.0.0" cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" @@ -2855,7 +2855,7 @@ __metadata: is-glob: "npm:^4.0.0" json-stable-stringify-without-jsonify: "npm:^1.0.1" lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" + minimatch: "npm:^3.1.5" natural-compare: "npm:^1.4.0" optionator: "npm:^0.9.3" peerDependencies: @@ -2865,7 +2865,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10/1c95c92983ddf435e7f7d54edd06d703a15773a7d189583d3388e5b5ac714f0a2450b91c0b3bb9b9ccec9bd20994fd8e48d231ed6dabca0be56ef314b32820ff + checksum: 10/de95093d710e62e8c7e753220d985587c40f4a05247ed4393ffb6e6cb43a60e825a47fc5b4263151bb2fc5871a206a31d563ccbabdceee1711072ae12db90adf languageName: node linkType: hard @@ -3088,9 +3088,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.3 - resolution: "flatted@npm:3.3.3" - checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe + version: 3.4.2 + resolution: "flatted@npm:3.4.2" + checksum: 10/a9e78fe5c2c1fcd98209a015ccee3a6caa953e01729778e83c1fe92e68601a63e1e69cd4e573010ca99eaf585a581b80ccf1018b99283e6cbc2117bcba1e030f languageName: node linkType: hard @@ -3103,11 +3103,11 @@ __metadata: languageName: node linkType: hard -"framer-motion@npm:^12.35.0": - version: 12.35.0 - resolution: "framer-motion@npm:12.35.0" +"framer-motion@npm:^12.35.2": + version: 12.35.2 + resolution: "framer-motion@npm:12.35.2" dependencies: - motion-dom: "npm:^12.35.0" + motion-dom: "npm:^12.35.2" motion-utils: "npm:^12.29.2" tslib: "npm:^2.4.0" peerDependencies: @@ -3121,7 +3121,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/9c2dd8a44efcf15d787ea1d1a24dbb2352b44824c4c33273f176f3feabe602278b9571541c89cc5673b3590b483daf9e0761889412feaafd4feba758cfdc1c96 + checksum: 10/10af699ff1e35a166ef60ceab464479b81624ef74de3ec9e11b427f86bd7bf2c8c8a9f24fb0646288b2d4b0c1b219203da351821fc568c7b91c6821594af4a3f languageName: node linkType: hard @@ -4475,12 +4475,12 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" +"minimatch@npm:^3.1.2, minimatch@npm:^3.1.5": + version: 3.1.5 + resolution: "minimatch@npm:3.1.5" dependencies: brace-expansion: "npm:^1.1.7" - checksum: 10/e0b25b04cd4ec6732830344e5739b13f8690f8a012d73445a4a19fbc623f5dd481ef7a5827fde25954cd6026fede7574cc54dc4643c99d6c6b653d6203f94634 + checksum: 10/b11a7ee5773cd34c1a0c8436cdbe910901018fb4b6cb47aa508a18d567f6efd2148507959e35fba798389b161b8604a2d704ccef751ea36bd4582f9852b7d63f languageName: node linkType: hard @@ -4500,12 +4500,12 @@ __metadata: languageName: node linkType: hard -"motion-dom@npm:^12.35.0": - version: 12.35.0 - resolution: "motion-dom@npm:12.35.0" +"motion-dom@npm:^12.35.2": + version: 12.35.2 + resolution: "motion-dom@npm:12.35.2" dependencies: motion-utils: "npm:^12.29.2" - checksum: 10/1a50cd2600d04dc8243c193af45b067aa65d853213f14aea15858a94fd3e901511ff258a91b4dffc1585eb43b61706a6f73fb98fb39dedd87e4b58a48ed8f593 + checksum: 10/dd009e58b178dd80b123a86199ae78ecd6b2fc6c8e03464b2daf43b4218dfcc36042ec0af8fad2c6c157198f56849f90dc033b58f46478b45fbaeaefcc2710ad languageName: node linkType: hard @@ -4517,10 +4517,10 @@ __metadata: linkType: hard "motion@npm:^12.4.1": - version: 12.35.0 - resolution: "motion@npm:12.35.0" + version: 12.35.2 + resolution: "motion@npm:12.35.2" dependencies: - framer-motion: "npm:^12.35.0" + framer-motion: "npm:^12.35.2" tslib: "npm:^2.4.0" peerDependencies: "@emotion/is-prop-valid": "*" @@ -4533,7 +4533,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/ef7f4df7337147a0012ba2bfe3fd1f23d76081b4094ab94a7bc9f3f8338074e7a290873a9ea94427aea1aa9c63021804972f62d6c4289e011ddf5ef59865fa01 + checksum: 10/3d99a53816634cbee1b38ed8a9a5d88bafbd29eb3bc02e78fc741c604972b4b88d317cf374bba30a1486f727bb1657ef8826f83e669a3b04fd1ec3ef75bfb62d languageName: node linkType: hard @@ -4587,24 +4587,24 @@ __metadata: languageName: node linkType: hard -"next@npm:16.1.6": - version: 16.1.6 - resolution: "next@npm:16.1.6" +"next@npm:16.2.1": + version: 16.2.1 + resolution: "next@npm:16.2.1" dependencies: - "@next/env": "npm:16.1.6" - "@next/swc-darwin-arm64": "npm:16.1.6" - "@next/swc-darwin-x64": "npm:16.1.6" - "@next/swc-linux-arm64-gnu": "npm:16.1.6" - "@next/swc-linux-arm64-musl": "npm:16.1.6" - "@next/swc-linux-x64-gnu": "npm:16.1.6" - "@next/swc-linux-x64-musl": "npm:16.1.6" - "@next/swc-win32-arm64-msvc": "npm:16.1.6" - "@next/swc-win32-x64-msvc": "npm:16.1.6" + "@next/env": "npm:16.2.1" + "@next/swc-darwin-arm64": "npm:16.2.1" + "@next/swc-darwin-x64": "npm:16.2.1" + "@next/swc-linux-arm64-gnu": "npm:16.2.1" + "@next/swc-linux-arm64-musl": "npm:16.2.1" + "@next/swc-linux-x64-gnu": "npm:16.2.1" + "@next/swc-linux-x64-musl": "npm:16.2.1" + "@next/swc-win32-arm64-msvc": "npm:16.2.1" + "@next/swc-win32-x64-msvc": "npm:16.2.1" "@swc/helpers": "npm:0.5.15" - baseline-browser-mapping: "npm:^2.8.3" + baseline-browser-mapping: "npm:^2.9.19" caniuse-lite: "npm:^1.0.30001579" postcss: "npm:8.4.31" - sharp: "npm:^0.34.4" + sharp: "npm:^0.34.5" styled-jsx: "npm:5.1.6" peerDependencies: "@opentelemetry/api": ^1.1.0 @@ -4643,7 +4643,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 10/00322378df865d4f00d232f8b1f42f4f0ad114e1d14f660d483b01ccd533459af6202e2f80067bf41a97aa0c99c3ae1d21a0aef2c081b0a9f456b978de4bf757 + checksum: 10/319c0b18173a90e53b5e5ffafa8a8fecb7cc340b77728796743edd996c7ee7652201892bff60c32f6a3b75abdff1449b77f13f6fab8fd56d4f9da47cf0fb9299 languageName: node linkType: hard @@ -4916,13 +4916,13 @@ __metadata: linkType: hard "postcss@npm:^8.5.6": - version: 8.5.6 - resolution: "postcss@npm:8.5.6" + version: 8.5.8 + resolution: "postcss@npm:8.5.8" dependencies: nanoid: "npm:^3.3.11" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 + checksum: 10/cbacbfd7f767e2c820d4bf09a3a744834dd7d14f69ff08d1f57b1a7defce9ae5efcf31981890d9697a972a64e9965de677932ef28e4c8ba23a87aad45b82c459 languageName: node linkType: hard @@ -5365,7 +5365,7 @@ __metadata: languageName: node linkType: hard -"sharp@npm:^0.34.4": +"sharp@npm:^0.34.5": version: 0.34.5 resolution: "sharp@npm:0.34.5" dependencies: @@ -5466,18 +5466,18 @@ __metadata: linkType: hard "shiki@npm:^3.13.0": - version: 3.22.0 - resolution: "shiki@npm:3.22.0" + version: 3.23.0 + resolution: "shiki@npm:3.23.0" dependencies: - "@shikijs/core": "npm:3.22.0" - "@shikijs/engine-javascript": "npm:3.22.0" - "@shikijs/engine-oniguruma": "npm:3.22.0" - "@shikijs/langs": "npm:3.22.0" - "@shikijs/themes": "npm:3.22.0" - "@shikijs/types": "npm:3.22.0" + "@shikijs/core": "npm:3.23.0" + "@shikijs/engine-javascript": "npm:3.23.0" + "@shikijs/engine-oniguruma": "npm:3.23.0" + "@shikijs/langs": "npm:3.23.0" + "@shikijs/themes": "npm:3.23.0" + "@shikijs/types": "npm:3.23.0" "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10/f9977e75f666253cc679e74b774af2afdfa48d52c631ab1448f47a90cd97f2290bcf50356f5b0d01a282da7f9e9f7e1938d585b213688e0d842fcba4a785f870 + checksum: 10/4c2751cac9dbcd61b6c80aed6c97ea4954b083c0cdf0d29fab71dbf90042c82b29f104c2843b24ea593e6d56608973b7c153dd3c05520ae001bc2f294651e398 languageName: node linkType: hard diff --git a/docs/.well-known/skills/app-frontend-system-migration/SKILL.md b/docs/.well-known/skills/app-frontend-system-migration/SKILL.md new file mode 100644 index 0000000000..0bfbf0714c --- /dev/null +++ b/docs/.well-known/skills/app-frontend-system-migration/SKILL.md @@ -0,0 +1,651 @@ +--- +name: app-frontend-system-migration +description: Migrate a Backstage app from the old frontend system to the new one. Use this skill when converting an app to use the new extension-based frontend system, including the hybrid migration phase and the full migration of routes, sidebar, plugins, APIs, themes, and other app-level concerns. +--- + +# App Frontend System Migration Skill + +This skill helps migrate a Backstage app package (`packages/app`) from the old frontend system (`@backstage/app-defaults`) to the new extension-based frontend system (`@backstage/frontend-defaults`). + +The migration follows a two-phase approach: first get the app running in hybrid mode with compatibility helpers, then gradually remove legacy code until the app is fully on the new system. + +## Key Concepts + +- **Old system:** `createApp` from `@backstage/app-defaults`, plugins installed via `` elements in `FlatRoutes`, manual app shell with `AppRouter` + `Root` +- **New system:** `createApp` from `@backstage/frontend-defaults`, plugins installed as `features`, extensions wired into an extension tree, no manual app shell +- **Feature discovery:** The new system can automatically discover and install plugins from your app's dependencies — no manual imports needed. This is the default for new apps and should be enabled early in migration. +- **Hybrid mode:** The new `createApp` with `convertLegacyAppRoot` and `convertLegacyAppOptions` from `@backstage/core-compat-api` to bridge old code + +## Feature Discovery + +Feature discovery is one of the biggest quality-of-life improvements in the new frontend system. Once enabled, any plugin added as a `package.json` dependency that exports a new-system plugin is automatically detected and installed — no code changes in `App.tsx` needed. + +### Enabling Feature Discovery + +Add this to your `app-config.yaml`: + +```yaml +app: + packages: all +``` + +This is the **recommended default** for all apps using the new frontend system. Enable it as early as Phase 1. + +### Filtering Discovered Packages + +You can control which packages are discovered using `include` or `exclude` filters: + +```yaml +# Only discover specific packages +app: + packages: + include: + - '@backstage/plugin-catalog' + - '@backstage/plugin-scaffolder' +``` + +```yaml +# Discover all except specific packages +app: + packages: + exclude: + - '@backstage/plugin-techdocs' +``` + +### Disabling Individual Extensions + +Even with feature discovery enabled, you can disable specific extensions via config without removing the package: + +```yaml +app: + extensions: + - page:techdocs: false + - nav-item:search: false +``` + +### How Discovery Works with Manual Imports + +Plugins that are both manually imported in `features` and auto-discovered are deduplicated — no conflicts. This means you can safely enable discovery while still explicitly importing plugins that need customization via `.withOverrides()`. + +### When NOT to Use Discovery + +Omit `app.packages` from config entirely (not `app.packages: none` — just leave it out) to disable discovery. You might do this if: + +- You need full control over which plugins are loaded +- You're in early Phase 1 and want to introduce features one at a time +- You're running in an environment where the `@backstage/cli` webpack integration isn't available + +Feature discovery requires that the app is built using `@backstage/cli`, which is the default for all Backstage apps. + +## Phase 1: Minimal Hybrid Migration + +### Step 1: Switch `createApp` + +Replace the import source for `createApp`: + +```typescript +// OLD +import { createApp } from '@backstage/app-defaults'; + +// NEW +import { createApp } from '@backstage/frontend-defaults'; +``` + +### Step 2: Convert `createApp` options + +Use `convertLegacyAppOptions` to wrap legacy options (`apis`, `icons`, `featureFlags`, `components`, `themes`) as a feature: + +```tsx +import { createApp } from '@backstage/frontend-defaults'; +import { convertLegacyAppOptions } from '@backstage/core-compat-api'; + +const convertedOptionsModule = convertLegacyAppOptions({ + apis, + icons: { alert: AlarmIcon }, + featureFlags: [ + { + name: 'scaffolder-next-preview', + description: 'Preview the new Scaffolder Next', + pluginId: '', + }, + ], + components: { + SignInPage: props => ( + + ), + }, +}); + +const app = createApp({ + features: [convertedOptionsModule], +}); +``` + +### Step 3: Convert the app root + +Use `convertLegacyAppRoot` to convert the entire app element tree (routes, sidebar, root elements) into features: + +```tsx +import { convertLegacyAppRoot } from '@backstage/core-compat-api'; + +const convertedRootFeatures = convertLegacyAppRoot( + <> + + + + + {routes} + + , +); + +const app = createApp({ + features: [convertedOptionsModule, ...convertedRootFeatures], +}); + +export default app.createRoot(); +``` + +Note: `app.createRoot()` now takes **no arguments** and returns a React **element** (not a component). + +### Step 4: Update `index.tsx` + +The default export is now an element, not a component: + +```typescript +// OLD +import App from './App'; +ReactDOM.createRoot(document.getElementById('root')!).render(); + +// NEW +import app from './App'; +ReactDOM.createRoot(document.getElementById('root')!).render(app); +``` + +### Step 5: Update `App.test.tsx` + +Same change for the test file: + +```typescript +import app from './App'; + +const rendered = render(app); +``` + +## Phase 2: Full Migration + +Once the app works in hybrid mode, gradually remove legacy code and compatibility helpers. + +### Migrating `createApp` Options + +Legacy options become extensions. App-level extensions (themes, icons, sign-in page, translations) must be installed via `createFrontendModule` targeting `pluginId: 'app'`: + +```typescript +import { createFrontendModule } from '@backstage/frontend-plugin-api'; + +const app = createApp({ + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [ + lightTheme, + signInPage, + exampleIconBundle, + catalogTranslations, + ], + }), + ], +}); +``` + +#### APIs → `ApiBlueprint` + +In the new system, APIs are extensions that follow **ownership rules**. Understanding which `pluginId` to use when wrapping an API in a `createFrontendModule` is critical — using the wrong one will cause conflict errors at runtime. + +**Ownership rules:** + +- Each API has an **owner plugin**. This can be set explicitly via `pluginId` on the `ApiRef`, or inferred from the `ApiRef` ID string: + - Explicit `pluginId` on the ref (recommended) → that plugin owns it + - `core.*` ID → owned by the `app` plugin + - `plugin..*` ID → owned by that plugin (e.g. `plugin.catalog.starred-entities` is owned by `catalog`) + - Other ID prefixes → the prefix itself is the owner +- **Only modules for the owning plugin can provide or override an API.** If plugin `A` tries to provide an API owned by plugin `B`, the system reports an `API_FACTORY_CONFLICT` error and rejects the override. +- **Modules for the same plugin override the plugin's own factory.** This is how apps replace default implementations. + +The recommended way to create API refs in the new system uses the builder pattern with an explicit `pluginId`: + +```typescript +import { createApiRef } from '@backstage/frontend-plugin-api'; + +// Recommended: explicit pluginId makes ownership unambiguous +const myApiRef = createApiRef().with({ + id: 'plugin.my-plugin.my-api', + pluginId: 'my-plugin', +}); + +// Legacy form: ownership inferred from the id string pattern +const legacyRef = createApiRef({ id: 'plugin.my-plugin.my-api' }); +``` + +The builder form (`createApiRef().with(...)`) is preferred because the `pluginId` is explicit rather than parsed from the ID string. The `id` must still be globally unique across the app — the `pluginId` is ownership metadata, not a namespace prefix. + +**Practical impact for app migration:** + +Most APIs that were in the old `createApp({ apis: [...] })` are either core APIs (owned by `app`) or plugin-specific APIs. You need to group them into the right modules: + +```typescript +import { createFrontendModule, ApiBlueprint } from '@backstage/frontend-plugin-api'; + +// Core/app-level APIs → module for 'app' +const appApisModule = createFrontendModule({ + pluginId: 'app', + extensions: [ + ApiBlueprint.make({ + name: 'scm-integrations', + params: defineParams => + defineParams({ + api: scmIntegrationsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), + }), + }), + ], +}); + +// Overriding a plugin's API → module for THAT plugin +const catalogApiOverride = createFrontendModule({ + pluginId: 'catalog', + extensions: [ + ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: catalogApiRef, // id: 'plugin.catalog' + deps: { ... }, + factory: ({ ... }) => new CustomCatalogClient({ ... }), + }), + }), + ], +}); + +const app = createApp({ + features: [appApisModule, catalogApiOverride], +}); +``` + +**Common mistake:** Putting all API overrides in a single `createFrontendModule({ pluginId: 'app' })`. This only works for APIs owned by `app` (i.e. `core.*` APIs like `core.config`, `core.discovery`, etc.). Plugin-specific APIs like `plugin.catalog.*` or `plugin.scaffolder.*` must be overridden using a module with the matching `pluginId`. + +The old `createApp({ apis: [...] })` pattern didn't have these restrictions — any API could be overridden from the app. In the new system, the ownership model is stricter to prevent accidental conflicts between plugins. + +#### Sign-in Page → `SignInPageBlueprint` + +```tsx +import { SignInPageBlueprint } from '@backstage/plugin-app-react'; + +const signInPage = SignInPageBlueprint.make({ + params: { + loader: async () => props => + ( + + ), + }, +}); +``` + +#### Themes → `ThemeBlueprint` + +```tsx +import { ThemeBlueprint } from '@backstage/plugin-app-react'; + +const customLightTheme = ThemeBlueprint.make({ + name: 'custom-light', + params: { + theme: { + id: 'custom-light', + title: 'Light Theme', + variant: 'light', + icon: , + Provider: ({ children }) => ( + + ), + }, + }, +}); +``` + +#### Icons → `IconBundleBlueprint` + +Icon bundles attach to the `app` plugin's icons input, so they must be installed via a module for `app`: + +```typescript +import { IconBundleBlueprint } from '@backstage/plugin-app-react'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; + +const exampleIconBundle = IconBundleBlueprint.make({ + name: 'example-bundle', + params: { + icons: { user: MyOwnUserIcon }, + }, +}); + +const app = createApp({ + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [exampleIconBundle], + }), + ], +}); +``` + +#### Translations → `TranslationBlueprint` + +Translations attach to the `app` plugin's translations input. Note that `createTranslationMessages` takes a `messages` object with key-value pairs: + +```typescript +import { TranslationBlueprint } from '@backstage/plugin-app-react'; +import { createTranslationMessages } from '@backstage/frontend-plugin-api'; +import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + +const catalogTranslations = TranslationBlueprint.make({ + name: 'catalog-overrides', + params: { + resource: createTranslationMessages({ + ref: catalogTranslationRef, + messages: { + 'indexPage.title': 'Service directory', + 'indexPage.createButtonTitle': 'Register new service', + }, + }), + }, +}); + +const app = createApp({ + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [catalogTranslations], + }), + ], +}); +``` + +For adding full language translations, use `createTranslationResource` instead: + +```typescript +import { createTranslationResource } from '@backstage/frontend-plugin-api'; + +const userSettingsTranslations = TranslationBlueprint.make({ + name: 'user-settings-zh', + params: { + resource: createTranslationResource({ + ref: userSettingsTranslationRef, + translations: { + zh: () => import('./userSettings-zh'), + }, + }), + }, +}); +``` + +### Migrating Root Elements + +Built-in elements like `AlertDisplay`, `OAuthRequestDialog`, and `VisitListener` are provided by the framework automatically. Remove them from `convertLegacyAppRoot`: + +```tsx +// Before +const convertedRootFeatures = convertLegacyAppRoot( + <> + + + + + {routes} + + , +); + +// After +const convertedRootFeatures = convertLegacyAppRoot(routes); +``` + +Custom root elements use `AppRootElementBlueprint`, and custom wrappers use `AppRootWrapperBlueprint` from `@backstage/plugin-app-react`. + +### Migrating the Sidebar + +Create a `NavContentBlueprint` extension to replace the legacy `Root` component: + +```tsx +import { NavContentBlueprint } from '@backstage/plugin-app-react'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; + +const SidebarContent = NavContentBlueprint.make({ + params: { + component: ({ navItems }) => { + const nav = navItems.withComponent(item => ( + item.icon} to={item.href} text={item.title} /> + )); + + return ( + + + } to="/search"> + + + + }> + {nav.take('page:catalog')} + {nav.take('page:scaffolder')} + + + {nav.rest({ sortBy: 'title' })} + + + + ); + }, + }, +}); + +export const navModule = createFrontendModule({ + pluginId: 'app', + extensions: [SidebarContent], +}); +``` + +Nav items are auto-discovered from page extensions. Use `nav.take('page:')` to place specific items, and `nav.rest()` for the remainder. Items that are `take`n are excluded from `rest()`. + +### Migrating Routes + +Remove routes from `FlatRoutes` one at a time. With feature discovery enabled (the recommended default), this is the only step needed — the new plugin version is already discovered and waiting; it was simply overridden by the legacy route which had higher priority: + +```tsx +// BEFORE: plugin page as a legacy route +const routes = ( + + } /> + } /> + +); + +// AFTER: just remove the route — discovery handles the rest +const routes = ( + + } /> + +); +``` + +If you are **not** using feature discovery, you need to manually import and install the new plugin version: + +```typescript +import scaffolderPlugin from '@backstage/plugin-scaffolder/alpha'; + +const app = createApp({ + features: [scaffolderPlugin, ...convertedRootFeatures], +}); +``` + +#### All-at-once rule for plugin routes + +Only one version of a plugin can be active in the app at a time. When legacy routes remain in `FlatRoutes`, `convertLegacyAppRoot` creates a plugin from them using the same plugin ID as the real plugin. This shadow plugin overrides the new-system version entirely. Because of this: + +- **All routes from a single plugin must be removed at the same time.** You cannot migrate one route of a multi-route plugin while keeping others in `FlatRoutes`. For example, if a plugin provides both `/foo` and `/foo/settings`, you must remove both routes together. +- **Entity page content counts as part of the plugin.** Many plugins contribute both a top-level route (in `FlatRoutes`) _and_ entity page cards/content (in the entity pages). These are all part of the same plugin. If you remove the route from `FlatRoutes` but keep the entity page card as JSX in your entity pages, the old entity card JSX is now orphaned — and the new plugin may auto-provide its own version of that card, leading to duplicates or missing content. + +The practical consequence: when you migrate a plugin, remove _all_ of its legacy touchpoints — routes _and_ entity page extensions — at the same time. + +### Migrating Entity Pages + +Entity pages are typically the most complex part of the migration because they pull in content from many different plugins. The `entityPage` option in `convertLegacyAppRoot` provides a way to migrate them gradually. + +#### Setting up gradual entity page migration + +Pass your entity pages to `convertLegacyAppRoot`: + +```typescript +const convertedRootFeatures = convertLegacyAppRoot(routes, { entityPage }); +``` + +This converts your legacy entity page JSX tree into extensions. The structural pieces (`EntityLayout`, `EntitySwitch`) are preserved, while entity cards and content are converted into extensions that live alongside any auto-discovered new-system cards. + +#### Migrating the catalog plugin itself + +The catalog plugin is special because it owns both the `/catalog` route and the entity page route (`/catalog/:namespace/:kind/:name`). You must migrate both together: + +1. Remove the catalog routes from `FlatRoutes`: + +```tsx +const routes = ( + + {/* Remove both catalog routes */} + {/* } /> */} + {/* }> */} + {/* {entityPage} */} + {/* */} + } /> + +); +``` + +2. Install the catalog plugin explicitly (before the converted features so it takes priority): + +```typescript +import catalogPlugin from '@backstage/plugin-catalog/alpha'; + +const app = createApp({ + features: [catalogPlugin, convertedOptionsModule, ...convertedRootFeatures], +}); +``` + +3. Pass `entityPage` to `convertLegacyAppRoot` (if not already done) so your existing entity page layout is preserved. + +#### Migrating individual plugins out of entity pages + +Once the catalog plugin itself is migrated, you can gradually remove legacy entity content from the entity pages. For each plugin that provides entity cards or content: + +1. **Remove the legacy JSX** from your entity page components (e.g. remove ``, ``, ``) +2. The new-system plugin auto-provides these as `EntityCardBlueprint` / `EntityContentBlueprint` extensions that are discovered automatically + +If you see **duplicate cards** after removing routes but before removing entity page JSX, that's expected — the new plugin is auto-providing cards while the legacy JSX still renders them. Remove the legacy JSX to resolve the duplication. + +#### Migrating entity page tabs + +Tabs in entity pages (the `EntityLayout.Route` entries) are provided by `EntityContentBlueprint` extensions in the new system. As you remove legacy entity content JSX, the tabs are automatically sourced from the new-system extensions. The order and grouping of tabs can be configured via `app-config.yaml`: + +```yaml +app: + extensions: + - page:catalog/entity: + config: + groups: + - overview: + title: Overview + - documentation: + title: Docs +``` + +#### When is it done? + +Once all plugins contributing to entity pages have been migrated, the `entityPage` option can be removed from `convertLegacyAppRoot`, and the entity page component files in `packages/app/src/components/catalog/` can be deleted. + +### Migrating Route Bindings + +In the new system, plugins should define `defaultTarget` on their external route refs (e.g. `createExternalRouteRef({ defaultTarget: 'scaffolder.root' })`). When plugins set sensible defaults, most `bindRoutes` calls in the app become unnecessary — the routes resolve automatically when the target plugin is installed. + +Review your existing `bindRoutes` configuration and remove any bindings that are already covered by default targets in the plugins. For the remaining cases that need custom bindings, you can still use `bindRoutes` or configure them via static config: + +```yaml +# app-config.yaml +app: + routes: + bindings: + catalog.createComponent: scaffolder.root +``` + +## Dependencies + +| Purpose | Old Package | New Package | +| --------------------- | ---------------------------- | -------------------------------- | +| App creation | `@backstage/app-defaults` | `@backstage/frontend-defaults` | +| Plugin/extension APIs | `@backstage/core-plugin-api` | `@backstage/frontend-plugin-api` | +| App components | `@backstage/core-components` | `@backstage/ui` + CSS Modules | +| Compatibility bridge | — | `@backstage/core-compat-api` | +| App blueprints | — | `@backstage/plugin-app-react` | + +## Migration Checklist + +### Phase 1 (Hybrid) + +1. [ ] Add `@backstage/frontend-defaults` and `@backstage/core-compat-api` dependencies +2. [ ] Switch `createApp` import to `@backstage/frontend-defaults` +3. [ ] Enable feature discovery: add `app.packages: all` to `app-config.yaml` +4. [ ] Wrap legacy options with `convertLegacyAppOptions` +5. [ ] Wrap app element tree with `convertLegacyAppRoot` +6. [ ] Change `app.createRoot()` to take no arguments +7. [ ] Update `index.tsx` to render element instead of component +8. [ ] Update `App.test.tsx` +9. [ ] Verify app starts and works in hybrid mode + +### Phase 2 (Full Migration) + +1. [ ] Convert APIs to `ApiBlueprint` extensions +2. [ ] Convert sign-in page to `SignInPageBlueprint` +3. [ ] Convert themes to `ThemeBlueprint` +4. [ ] Convert icons to `IconBundleBlueprint` +5. [ ] Convert translations to `TranslationBlueprint` +6. [ ] Migrate sidebar to `NavContentBlueprint` +7. [ ] Remove built-in root elements (`AlertDisplay`, `OAuthRequestDialog`, etc.) +8. [ ] Migrate routes from `FlatRoutes` to plugin features (one plugin at a time, removing all routes + entity content for each plugin together) +9. [ ] Set up entity page migration with `convertLegacyAppRoot(routes, { entityPage })` +10. [ ] Migrate catalog plugin: remove catalog routes from `FlatRoutes`, install `catalogPlugin` as a feature +11. [ ] Gradually remove legacy entity card/content JSX as each contributing plugin is migrated +12. [ ] Remove `entityPage` option and legacy entity page component files +13. [ ] Remove `convertLegacyAppRoot` and `convertLegacyAppOptions` calls +14. [ ] Remove `@backstage/app-defaults`, `@backstage/core-app-api` dependencies +15. [ ] Run `yarn tsc` and `yarn lint` to verify + +## Troubleshooting + +- Install `@backstage/plugin-app-visualizer` to inspect the extension tree at `/visualizer` +- Duplicate entity cards: remove legacy card JSX from entity pages — plugins auto-provide them +- `Invalid element inside FlatRoutes`: push `FeatureFlagged`/`RequirePermissions` wrappers into plugin code instead of the route table + +## Reference + +- [App migration guide](https://backstage.io/docs/frontend-system/building-apps/migrating) +- [Architecture overview](https://backstage.io/docs/frontend-system/architecture/index) +- [Extension blueprints](https://backstage.io/docs/frontend-system/building-plugins/common-extension-blueprints) +- [Installing plugins](https://backstage.io/docs/frontend-system/building-apps/installing-plugins) diff --git a/docs/.well-known/skills/index.json b/docs/.well-known/skills/index.json new file mode 100644 index 0000000000..e66c7ea791 --- /dev/null +++ b/docs/.well-known/skills/index.json @@ -0,0 +1,24 @@ +{ + "skills": [ + { + "name": "mui-to-bui-migration", + "description": "Migrate Backstage plugins from Material-UI (MUI) to Backstage UI (BUI). Use this skill when migrating components, updating imports, replacing styling patterns, or converting MUI components to their BUI equivalents.", + "files": ["SKILL.md"] + }, + { + "name": "app-frontend-system-migration", + "description": "Migrate a Backstage app from the old frontend system to the new one. Use this skill when converting an app to use the new extension-based frontend system, including the hybrid migration phase and the full migration of routes, sidebar, plugins, APIs, themes, and other app-level concerns.", + "files": ["SKILL.md"] + }, + { + "name": "plugin-new-frontend-system-support", + "description": "Add new frontend system support to an existing Backstage plugin while keeping the old system working. Use this skill for published or shared plugins that need to work in both old and new frontend system apps.", + "files": ["SKILL.md"] + }, + { + "name": "plugin-full-frontend-system-migration", + "description": "Fully migrate a Backstage plugin to the new frontend system, dropping all old system support. Use this skill for internal plugins that only need to run in a single app, or when you are ready to remove backward compatibility entirely.", + "files": ["SKILL.md"] + } + ] +} diff --git a/docs/.well-known/skills/mui-to-bui-migration/SKILL.md b/docs/.well-known/skills/mui-to-bui-migration/SKILL.md new file mode 100644 index 0000000000..94e2bcfdcd --- /dev/null +++ b/docs/.well-known/skills/mui-to-bui-migration/SKILL.md @@ -0,0 +1,778 @@ +--- +name: mui-to-bui-migration +description: Migrate Backstage plugins from Material-UI (MUI) to Backstage UI (BUI). Use this skill when migrating components, updating imports, replacing styling patterns, or converting MUI components to their BUI equivalents. +--- + +# MUI to BUI Migration Skill + +This skill helps migrate Backstage plugins from Material-UI (@material-ui/core, @material-ui/icons) to Backstage UI ( +@backstage/ui). + +## Prerequisites + +Before starting migration: + +1. Install the BUI package: + + ```bash + yarn add @backstage/ui + ``` + +2. Add the CSS import to your root file (typically `src/index.ts` or app entry point): + ```typescript + import '@backstage/ui/css/styles.css'; + ``` + +## Available BUI Components + +### Layout Components + +- `Box` - Basic layout container with CSS properties +- `Container` - Centered content container with max-width +- `Flex` - Flex layout component +- `FullPage` - Full-page layout wrapper +- `Grid` - CSS Grid-based layout (`Grid.Root`, `Grid.Item`) + +### UI Components + +- `Accordion` - Collapsible content panels (`Accordion`, `AccordionTrigger`, `AccordionPanel`, `AccordionGroup`) +- `Alert` - Alert/notification banners (`status`, `title`, `description`) +- `Avatar` - User/entity avatars +- `Button` - Action buttons (`variant="primary"`, `variant="secondary"`, `variant="tertiary"`, `isDisabled`, `destructive`, `loading`) +- `ButtonIcon` - Icon-only buttons (`icon`, `onPress`, `variant`) +- `ButtonLink` - Link styled as button +- `Card` - Content cards (`Card`, `CardHeader`, `CardBody`, `CardFooter`) +- `Checkbox` - Checkbox input +- `Dialog` - Modal dialogs (`DialogTrigger`, `Dialog`, `DialogHeader`, `DialogBody`, `DialogFooter`) +- `FieldLabel` - Form field label with description and secondary label +- `Header` - Page headers with breadcrumbs and tabs +- `Link` - Navigation links +- `List` - List component (`List`, `ListRow`) +- `Menu` - Dropdown menus (`MenuTrigger`, `Menu`, `MenuItem`, `MenuSection`, `MenuSeparator`, `SubmenuTrigger`) +- `PasswordField` - Password input field +- `PluginHeader` - Plugin-level header with icon, title, tabs, and actions +- `Popover` - Popover overlays +- `RadioGroup` - Radio button groups (`RadioGroup`, `Radio`) +- `SearchAutocomplete` - Search input with autocomplete popover (`SearchAutocomplete`, `SearchAutocompleteItem`) +- `SearchField` - Search input +- `Select` - Dropdown select (single and multiple selection modes) +- `Skeleton` - Loading skeleton +- `Switch` - Toggle switch +- `Table` - Data tables (with `useTable` hook for data management) +- `TablePagination` - Standalone pagination component +- `Tabs` - Tab navigation (`Tabs`, `TabList`, `Tab`, `TabPanel`) +- `Tag` - Tag/chip component (replaces MUI Chip) +- `TagGroup` - Tag/chip groups +- `Text` - Typography component (`variant`, `color`, `weight`, `truncate`) +- `TextField` - Text input (`isRequired`, `onChange` receives string directly) +- `ToggleButton` - Toggle buttons +- `ToggleButtonGroup` - Grouped toggle buttons +- `Tooltip` - Tooltip overlays (`TooltipTrigger`, `Tooltip` — both from `@backstage/ui`) +- `VisuallyHidden` - Accessibility helper + +### Hooks + +- `useBreakpoint` - Responsive breakpoint hook +- `useTable` - Table data management hook (supports `complete`, `offset`, and `cursor` pagination modes) + +## Migration Patterns + +### 1. Import Changes + +**Remove MUI imports:** + +```typescript +// REMOVE these imports +import { Box, Typography, Tooltip, Paper } from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import SomeIcon from '@material-ui/icons/SomeIcon'; +``` + +**Add BUI imports:** + +```typescript +// ADD these imports +import { Box, Flex, Text, Tooltip, Card } from '@backstage/ui'; +import { RiSomeIcon } from '@remixicon/react'; +import styles from './MyComponent.module.css'; +``` + +### 2. Styling: `makeStyles` to CSS Modules + +Create a `.module.css` file alongside your component using BUI CSS variables. + +**Before (MUI `makeStyles`):** + +```typescript +// MyComponent.tsx +import {makeStyles, Theme} from '@material-ui/core/styles'; + +const useStyles = makeStyles((theme: Theme) => ({ + container: { + padding: theme.spacing(2), + backgroundColor: theme.palette.background.paper, + borderRadius: theme.shape.borderRadius, + }, + title: { + marginBottom: theme.spacing(1), + color: theme.palette.text.primary, + }, + listItem: { + display: 'flex', + alignItems: 'center', + }, + icon: { + minWidth: 56, + color: theme.palette.text.secondary, + }, +})); + +function MyComponent() { + const classes = useStyles(); + return ( +
+ Title < /Typography> + < div + className = {classes.listItem} > +
+ +
+ < span > Content < /span> + < /div> + < /div> +) + ; +} +``` + +**After (CSS Modules with BUI variables):** + +```css +/* MyComponent.module.css */ +@layer components { + .container { + padding: var(--bui-space-4); + background-color: var(--bui-bg-neutral-1); + border-radius: var(--bui-radius-2); + } + + .title { + margin-bottom: var(--bui-space-2); + color: var(--bui-fg-primary); + } + + .listItem { + display: flex; + align-items: center; + padding: var(--bui-space-2) 0; + } + + .icon { + min-width: 56px; + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-secondary); + } +} +``` + +```typescript +// MyComponent.tsx +import {Box, Text} from '@backstage/ui'; +import {RiSomeIcon} from '@remixicon/react'; +import styles from './MyComponent.module.css'; + +function MyComponent() { + return ( + + Title < /Text> + < div + className = {styles.listItem} > +
+ + < /div> + < span > Content < /span> + < /div> + < /Box> +) + ; +} +``` + +### 3. Layout: Box with display to `Flex` + +**Before (MUI Box with display prop):** + +```typescript + + + {children} + < /Box> + < /Box> +``` + +**After (BUI `Flex` component):** + +```typescript + + +{ + children +} + +< /Flex> +``` + +Note: BUI `Flex` uses `justify="between"` not `justify="space-between"`. + +### 4. Grid Layout + +**Before (MUI Grid):** + +```typescript + + + {content} + < /Grid> + < /Grid> +``` + +**After (BUI Grid):** + +```typescript + + +{ + content +} + +< /Grid.Root> +``` + +### 5. Typography to Text + +**Before (MUI Typography):** + +```typescript + Heading < /Typography> + < Typography +variant = "h6" > Subheading < /Typography> + < Typography +variant = "body1" > Body +text < /Typography> +< Typography +variant = "body2" +color = "textSecondary" > Secondary +text < /Typography> +``` + +**After (BUI Text):** + +```typescript + Heading < /Text> + < Text +variant = "title-small" > Subheading < /Text> + < Text +variant = "body-medium" > Body +text < /Text> +< Text +variant = "body-small" +color = "secondary" > Secondary +text < /Text> +``` + +Valid Text variants: `title-large`, `title-medium`, `title-small`, `title-x-small`, `body-large`, `body-medium`, +`body-small`, `body-x-small` + +### 6. Tooltip Pattern + +**Before (MUI Tooltip):** + +```typescript +import {Tooltip, Typography} from '@material-ui/core'; + + Tooltip +content < /Typography>}> +< span > Hover +me < /span> +< /Tooltip>; +``` + +**After (BUI TooltipTrigger pattern):** + +```typescript +import { Tooltip, TooltipTrigger, Text } from '@backstage/ui'; + + + Hover me + Tooltip content +; +``` + +### 7. Dialog Pattern + +**Before (MUI Dialog):** + +```typescript +import {Dialog, DialogTitle, DialogActions, Button} from '@material-ui/core'; + + +Title < /DialogTitle> +< DialogActions > + + +); +``` + +You will see how the initial dictionary structure and nesting get converted into dot notation, so we encourage `camelCase` in key names and lean on the nesting structure to separate keys. + +### Guidelines for `i18n` messages and keys + +The API for `i18n` messages and keys can be pretty tricky to get right, as it's a pretty flexible API. We've put together some guidelines to help you get started that encourage good practices when thinking about translating plugins: + +#### Key names + +When defining messages it is recommended to use a nested structure that represents the semantic hierarchy in your translations. This allows for better organization and understanding of the structure. For example: + +```ts +export const myPluginTranslationRef = createTranslationRef({ + id: 'plugin.my-plugin', + messages: { + dashboardPage: { + title: 'All your components', + subtitle: 'Create new component', + widgets: { + weather: { + title: 'Weather', + description: 'Shows the weather', + }, + calendar: { + title: 'Calendar', + description: 'Shows the calendar', + }, + }, + }, + entityPage: { + notFound: 'Entity not found', + }, + }, +}); +``` + +Think about the semantic placement of content rather than the text content itself. Group related translations under a common prefix, and use nesting to represent relationships between different parts of your application. It's good to start grouping under extensions, page sections, or visual scopes and experiences. + +Translations should avoid using their own text content as key where possible, as this can lead to confusion if the translation changes. Instead prefer to use keys that describe the location or usage of the text. + +#### Common Key names + +This list is intended to grow over time, but below are some examples of common key names and patterns that we encourage you to use where possible: + +- `${page}.title` +- `${page}.subtitle` +- `${page}.description` + +- `${page}.header.title` + +#### Key reuse + +Reusing the same key in multiple places is discouraged. This helps prevent ambiguity, and instead keeps the usage of each key as clear as possible. Consider creating duplicate keys that are grouped under a semantic section instead. + +#### Flat keys + +Avoid a flat key structure at the root level, as it can lead to naming conflicts and make the translation file harder to manage and change evolve over time. Instead, group translations under a common prefix. + +```ts +export const myPluginTranslationRef = createTranslationRef({ + id: 'plugin.my-plugin', + messages: { + // this is BAD + title: 'My page', + subtitle: 'My subtitle', + // this is GOOD + dashboardPage: { + header: { + title: 'All your components', + subtitle: 'Create new component', + }, + }, + }, +}); +``` + +#### Plurals + +The `i18next` library, which is used as the underlying implementation, has built-in support for pluralization. You can use this feature as is described in [the documentation](https://www.i18next.com/translation-function/plurals). + +We encourage you to use this feature and avoid creating different key prefixes for pluralized content. For example: + +```ts +export const myPluginTranslationRef = createTranslationRef({ + id: 'plugin.my-plugin', + messages: { + dashboardPage: { + title: 'All your components', + subtitle: 'Create new component', + cards: { + title_one: 'You have one card', + title_two: 'You have two cards', + title_other: 'You have many cards ({{count}})', + }, + }, + entityPage: { + notFound: 'Entity not found', + }, + }, +}); +``` + +#### JSX Elements + +The translation API supports interpolation of JSX elements by passing them directly as values to the translation function. If any of the provided interpolation values are JSX elements, the translation function will return a JSX element instead of a string. + +For example, you might define the following messages: + +```ts title="define the message" +export const myPluginTranslationRef = createTranslationRef({ + id: 'plugin.my-plugin', + messages: { + entityPage: { + redirect: { + message: 'The entity you are looking for has been moved to {{link}}.', + link: 'new location', + }, + }, + }, +}); +``` + +Which can be used within a component like this: + +```tsx title="use within a component" +const { t } = useTranslationRef(myPluginTranslationRef); + +return ( +
+ {t('entityPage.redirect.message', { + link: {t('entityPage.redirect.link')}, + })} +
+); +``` + +The return type of the outer `t` function will be a `JSX.Element`, with the underlying value being a React fragment of the different parts of the message. + +## For an application developer + +As an app developer you can both override the default English messages of any plugin, and provide translations for additional languages. + +### Overriding messages + +To customize specific messages without adding new languages, create a translation extension using `TranslationBlueprint` from `@backstage/plugin-app-react` together with `createTranslationMessages` from `@backstage/frontend-plugin-api`: + +```ts +import { createTranslationMessages } from '@backstage/frontend-plugin-api'; +import { TranslationBlueprint } from '@backstage/plugin-app-react'; +import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + +const catalogTranslations = TranslationBlueprint.make({ + name: 'catalog-overrides', + params: { + resource: createTranslationMessages({ + ref: catalogTranslationRef, + messages: { + 'indexPage.title': 'Service directory', + 'indexPage.createButtonTitle': 'Register new service', + }, + }), + }, +}); +``` + +Then install it as a feature in your app: + +```ts +import { createApp } from '@backstage/frontend-defaults'; + +const app = createApp({ + features: [catalogTranslations], +}); +``` + +You only need to include the keys you want to override — any missing keys fall back to the plugin's defaults. + +### Adding language translations + +To add support for additional languages, create a translation resource with lazy-loaded message files for each language, and install it using `TranslationBlueprint`: + +```ts +import { createTranslationResource } from '@backstage/frontend-plugin-api'; +import { TranslationBlueprint } from '@backstage/plugin-app-react'; +import { userSettingsTranslationRef } from '@backstage/plugin-user-settings/alpha'; + +const userSettingsTranslations = TranslationBlueprint.make({ + name: 'user-settings-zh', + params: { + resource: createTranslationResource({ + ref: userSettingsTranslationRef, + translations: { + zh: () => import('./userSettings-zh'), + }, + }), + }, +}); +``` + +The translation messages can be defined using `createTranslationMessages` for type safety: + +```ts +// packages/app/src/translations/userSettings-zh.ts + +import { createTranslationMessages } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '@backstage/plugin-user-settings/alpha'; + +const zh = createTranslationMessages({ + ref: userSettingsTranslationRef, + full: false, // False means that this is a partial translation + messages: { + 'languageToggle.title': '语言', + 'languageToggle.select': '选择{{language}}', + }, +}); + +export default zh; +``` + +Or as a plain object export: + +```ts +// packages/app/src/translations/userSettings-zh.ts +export default { + 'languageToggle.title': '语言', + 'languageToggle.select': '选择{{language}}', + 'languageToggle.description': '切换语言', + 'themeToggle.title': '主题', + 'themeToggle.description': '切换主题', + 'themeToggle.select': '选择{{theme}}', + 'themeToggle.selectAuto': '选择自动主题', + 'themeToggle.names.auto': '自动', + 'themeToggle.names.dark': '暗黑', + 'themeToggle.names.light': '明亮', +}; +``` + +Install the translation extension in your app: + +```ts +import { createApp } from '@backstage/frontend-defaults'; + +const app = createApp({ + features: [userSettingsTranslations], +}); +``` + +Go to the Settings page — you should see language switching buttons. Switch languages to verify your translations are loaded correctly. + +### Using the CLI for full translation workflows + +When translating your app to other languages at scale — especially when working with external translation systems — the Backstage CLI provides `translations export` and `translations import` commands that automate the extraction and wiring of translation messages across all your plugin dependencies. + +#### Exporting default messages + +From your app package directory (e.g. `packages/app`), run: + +```bash +yarn backstage-cli translations export +``` + +This scans all frontend plugin dependencies (including transitive ones) for `TranslationRef` definitions and writes their default English messages as JSON files: + +```text +translations/ + manifest.json + messages/ + catalog.en.json + org.en.json + scaffolder.en.json + ... +``` + +Each `.en.json` file contains the flattened message keys and their default values: + +```json +{ + "indexPage.title": "All your components", + "indexPage.createButtonTitle": "Create new component", + "entityPage.notFound": "Entity not found" +} +``` + +#### Creating translations + +Copy the exported files and translate them for your target languages: + +```bash +cp translations/messages/catalog.en.json translations/messages/catalog.zh.json +``` + +Then edit `catalog.zh.json` with the translated strings. You only need to include the keys you want to translate — missing keys fall back to the English defaults at runtime. + +#### Generating wiring code + +Once you have translated files in place, run: + +```bash +yarn backstage-cli translations import +``` + +This generates a TypeScript module at `src/translations/resources.ts` that wires everything together: + +```ts +// This file is auto-generated by backstage-cli translations import +// Do not edit manually. + +import { createTranslationResource } from '@backstage/frontend-plugin-api'; +import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + +export default [ + createTranslationResource({ + ref: catalogTranslationRef, + translations: { + zh: () => import('../../translations/messages/catalog.zh.json'), + }, + }), +]; +``` + +Install the generated resources as features in your app: + +```ts +import { createApp } from '@backstage/frontend-defaults'; +import translationResources from './translations/resources'; + +const app = createApp({ + features: translationResources, +}); +``` + +#### Custom file patterns + +By default, message files use the pattern `messages/{id}.{lang}.json` (e.g. `messages/catalog.en.json`). You can change this with the `--pattern` option: + +```bash +yarn backstage-cli translations export --pattern '{lang}/{id}.json' +``` + +This produces a directory structure grouped by language instead: + +```text +translations/en/catalog.json +translations/zh/catalog.json +``` + +The pattern is stored in the manifest, so the `import` command automatically uses the same layout. + +#### Integration with external translation systems + +The exported JSON files are standard key-value pairs compatible with most external translation systems. A typical workflow looks like: + +1. Run `translations export` to generate the source English files +2. Upload the `.en.json` files to your translation system +3. Download the translated files back into the translations directory +4. Run `translations import` to regenerate the wiring code + +For full command reference, see the [CLI commands documentation](../../tooling/cli/03-commands.md#translations-export). diff --git a/docs/frontend-system/building-plugins/08-analytics.md b/docs/frontend-system/building-plugins/08-analytics.md new file mode 100644 index 0000000000..0b51b5ae1a --- /dev/null +++ b/docs/frontend-system/building-plugins/08-analytics.md @@ -0,0 +1,317 @@ +--- +id: analytics +title: Plugin Analytics +sidebar_label: Analytics +description: Measuring usage of your Backstage instance +--- + +Setting up, maintaining, and iterating on an instance of Backstage can be a +large investment. To help measure return on this investment, Backstage comes +with an event-based Analytics API that grants app integrators the flexibility to +collect and analyze Backstage usage in the analytics tool of their choice, while +providing plugin developers a standard interface for instrumenting key user +interactions. + +## Concepts + +- **Events** consist of, at a minimum, an `action` (like `click`) and a + `subject` (like `thing that was clicked on`). +- **Attributes** represent additional dimensional data (in the form of key/value + pairs) that may be provided on an event-by-event basis. To continue the above + example, the URL a user clicked to might look like `{ "to": "/a/page" }`. +- **Context** represents the broader context in which an event took place. By + default, information like `pluginId`, `extension`, and `routeRef` are + provided. + +This composition of events aims to allow analysis at different levels of detail, +enabling very granular questions (like "what is the most clicked on thing on a +particular route") as well as very high-level questions (like "what is the most +used plugin in my Backstage instance") to be answered. + +## Supported Analytics Tools + +While all that's needed to consume and forward these events to an analytics tool +is a concrete implementation of [AnalyticsApi][analytics-api-type], common +integrations are packaged and provided as plugins. Find your analytics tool of +choice below. + +| Analytics Tool | Support Status | +| ------------------------------------- | -------------- | +| [Google Analytics][ga] | Yes ✅ | +| [Google Analytics 4][ga4] | Yes ✅ | +| [New Relic Browser][newrelic-browser] | Community ✅ | +| [Matomo][matomo] | Community ✅ | +| [Quantum Metric][qm] | Community ✅ | +| [Generic HTTP][generic-http] | Community ✅ | + +To suggest an integration, please [open an issue][add-tool] for the analytics +tool your organization uses. Or jump to [Writing Integrations][int-howto] to +learn how to contribute the integration yourself! + +[ga]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga/README.md +[ga4]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga4/README.md +[newrelic-browser]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-newrelic-browser/README.md +[qm]: https://github.com/quantummetric/analytics-module-qm/blob/main/README.md +[matomo]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-matomo/README.md +[add-tool]: https://github.com/backstage/backstage/issues/new?assignees=&labels=plugin&template=plugin_template.md&title=%5BAnalytics+Module%5D+THE+ANALYTICS+TOOL+TO+INTEGRATE +[int-howto]: #writing-integrations +[analytics-api-type]: https://backstage.io/api/stable/types/_backstage_frontend-plugin-api.index.AnalyticsApi.html +[generic-http]: https://github.com/pfeifferj/backstage-plugin-analytics-generic/blob/main/README.md + +## Key Events + +The following table summarizes events that, depending on the plugins you have +installed, may be captured. + +| Action | Subject | Other Notes | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `navigate` | The URL of the page that was navigated to. | Fired immediately when route location changes (unless associated plugin/route data is ambiguous, in which case the event is fired after plugin/route data becomes known, immediately before the next event or document unload). The parameters of the current route will be included as attributes. | +| `click` | The text of the link that was clicked on. | The `to` attribute represents the URL clicked to. | +| `create` | The `name` of the software being created; if no `name` property is requested by the given Software Template, then the string `new {templateName}` is used instead. | The context holds an `entityRef`, set to the template's ref (e.g. `template:default/template-name`). The `value` represents the number of minutes saved by running the template (based on the template's `backstage.io/time-saved` annotation, if available). | +| `search` | The search term entered in any search bar component. | The context holds `searchTypes`, representing `types` constraining the search. The `value` represents the total number of search results for the query. This may not be visible if the permission framework is being used. | +| `discover` | The title of the search result that was clicked on | The `value` is the result rank. A `to` attribute is also provided. | +| `not-found` | The path of the resource that resulted in a not found page | Fired by at least TechDocs. | + +If there is an event you'd like to see captured, please [open an issue](https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md&title=[Analytics%20Event]:%20THE+EVENT+TO+CAPTURE) describing the event you want to see and the questions it +would help you answer. Or jump to [Capturing Events](#capturing-events) to learn how +to contribute the instrumentation yourself! + +_OSS plugin maintainers: feel free to document your events in the table above._ + +## Writing Integrations + +Analytics event forwarding is implemented as a Backstage [Utility API](../utility-apis/01-index.md). The +provided API need only provide a single method `captureEvent`, which takes +an `AnalyticsEvent` object. + +A simple implementation using `AnalyticsImplementationBlueprint`: + +```ts +import { AnalyticsImplementationBlueprint } from '@backstage/plugin-app-react'; + +export const acmeAnalyticsImplementation = + AnalyticsImplementationBlueprint.make({ + name: 'acme', + params: define => + define({ + deps: {}, + factory() { + return { + captureEvent: event => { + window._AcmeAnalyticsQ.push(event); + }, + }; + }, + }), + }); +``` + +In reality, you would likely want to encapsulate instantiation logic and pull +some details from configuration. A more complete example might look like: + +```ts +import { + AnalyticsApi, + AnalyticsEvent, + configApiRef, +} from '@backstage/frontend-plugin-api'; +import { AnalyticsImplementationBlueprint } from '@backstage/plugin-app-react'; +import { AcmeAnalytics } from 'acme-analytics'; + +class AcmeAnalyticsImpl implements AnalyticsApi { + private constructor(accountId: number) { + AcmeAnalytics.init(accountId); + } + + static fromConfig(config) { + const accountId = config.getString('app.analytics.acme.id'); + return new AcmeAnalyticsImpl(accountId); + } + + captureEvent(event: AnalyticsEvent) { + const { action, ...rest } = event; + AcmeAnalytics.send(action, rest); + } +} + +export const acmeAnalyticsImplementation = + AnalyticsImplementationBlueprint.make({ + name: 'acme', + params: define => + define({ + deps: { configApi: configApiRef }, + factory: ({ configApi }) => AcmeAnalyticsImpl.fromConfig(configApi), + }), + }); +``` + +If you are integrating with an analytics service (as opposed to an internal +tool), consider contributing your API implementation as a plugin! + +By convention, such packages should be named +`@backstage/analytics-module-[name]`, and any configuration should be keyed +under `app.analytics.[name]`. + +### Handling User Identity + +If the analytics platform you are integrating with has a first-class concept of +user identity, you can (optionally) choose to support this by the following this +convention: + +- Allow your implementation to be instantiated with the `identityApi` as one of + its dependencies. +- Use the `userEntityRef` resolved by `identityApi`'s `getBackstageIdentity()` + method as the basis for the user ID you send to your analytics platform. + +## Capturing Events + +To instrument an event in a component, start by retrieving an analytics tracker +using the `useAnalytics()` hook provided by `@backstage/frontend-plugin-api`. The +tracker includes a `captureEvent` method which takes an `action` and a `subject` +as arguments. + +```ts +import { useAnalytics } from '@backstage/frontend-plugin-api'; + +const analytics = useAnalytics(); +analytics.captureEvent('deploy', serviceName); +``` + +### Providing Extra Attributes + +Additional dimensional `attributes` as well as a numeric `value` can be provided +on a third `options` argument if/when relevant for the event: + +```ts +analytics.captureEvent('merge', pullRequestName, { + value: pullRequestAgeInMinutes, + attributes: { + org, + repo, + }, +}); +``` + +In the above example, an event resembling the following object would be +captured: + +```json +{ + "action": "merge", + "subject": "Name of Pull Request", + "value": 60, + "attributes": { + "org": "some-org", + "repo": "some-repo" + } +} +``` + +### Providing Context for Events + +The `attributes` option is good for capturing details available to you within +the component that you're instrumenting. For capturing metadata only available +further up the react tree, or to help app integrators aggregate distinct events +by some common value, use an ``. + +```tsx +import { AnalyticsContext, useAnalytics } from '@backstage/frontend-plugin-api'; + +const MyComponent = ({ value }) => { + const analytics = useAnalytics(); + const handleClick = () => analytics.captureEvent('check', value); + return ; +}; + +const MyWrapper = () => { + return ( + + + + ); +}; +``` + +In the above example, clicking on `` would result in an analytics +event resembling: + +```json +{ + "action": "check", + "subject": "Some Value", + "context": { + "segment": "xyz" + } +} +``` + +Note that, for brevity in the example above, the context keys provided by +Backstage core (`pluginId`, `extension`, and `routeRef`) have been omitted. In +reality, those details would be included alongside any additional context +provided by you. + +Analytics contexts can be nested; their values are merged down the react tree, +allowing keys to be overwritten. + +### Event Naming Considerations + +An event is split into its constituent parts to enable analysis at various +levels of granularity. In order to maintain this flexibility at analysis-time, +it's important to keep each of these levels of detail disaggregated. + +- Avoid providing an overly specific `action`. For example, instead of + `filterEntityTable`, consider just using `filter` as the action, and allowing + `EntityTable` to be specified as part of the event's `context` (most likely + automatically as part of the `extension` in which the `filter` event was + captured). + +- On the flip side, when adding `attributes` to or `context` around an event, + look at existing events and see if the data you are capturing matches the + intention, type, or even the content of _their_ `attributes` or `context`. + For instance, it's common for events that involve the Catalog to include an + `entityRef` contextual key. Using the same keys and values in your event will + ensure that events instrumented across plugins can easily be aggregated. + +### Unit Testing Event Capture + +The `@backstage/frontend-test-utils` package includes a `MockAnalyticsApi` implementation +that you can use in your unit tests to spy on and make assertions about any +analytics events captured. + +Use it like this: + +```tsx +import { render, fireEvent, waitFor } from '@testing-library/react'; +import { analyticsApiRef } from '@backstage/frontend-plugin-api'; +import { + MockAnalyticsApi, + TestApiProvider, + wrapInTestApp, +} from '@backstage/frontend-test-utils'; + +describe('SomeComponent', () => { + it('should capture event on click', () => { + const apiSpy = new MockAnalyticsApi(); + + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + fireEvent.click(getByText('some component text')); + + await waitFor(() => { + expect(apiSpy.getEvents()[0]).toMatchObject({ + action: 'expected action', + subject: 'expected subject', + attributes: { + foo: 'bar', + }, + }); + }); + }); +}); +``` diff --git a/docs/frontend-system/building-plugins/09-feature-flags.md b/docs/frontend-system/building-plugins/09-feature-flags.md new file mode 100644 index 0000000000..06ee56be24 --- /dev/null +++ b/docs/frontend-system/building-plugins/09-feature-flags.md @@ -0,0 +1,78 @@ +--- +id: feature-flags +title: Feature Flags +sidebar_label: Feature Flags +description: Defining and using feature flags in plugins and apps +--- + +Backstage offers the ability to define feature flags inside a plugin or during application creation. This allows you to restrict parts of your plugin to those individual users who have toggled the feature flag to on. + +This page describes the process of defining, setting and reading a feature flag. If you are looking for using feature flags specifically with software templates please see [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#remove-sections-or-fields-based-on-feature-flags). + +## Defining a Feature Flag + +### In a plugin + +Feature flags are declared via the `featureFlags` option in `createFrontendPlugin`: + +```ts title="src/plugin.ts" +import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; + +export const examplePlugin = createFrontendPlugin({ + pluginId: 'example', + featureFlags: [ + { + name: 'show-example-feature', + description: 'Enables the new beta dashboard view', + }, + ], + extensions: [ + // ... + ], +}); +``` + +Note that the `description` property is optional. If not provided, the default "Registered in {pluginId} plugin" message is shown. + +### In the application + +Defining a feature flag in the application is done by adding feature flags in the `featureFlags` array in the +`createApp()` function call: + +```ts title="packages/app/src/App.tsx" +import { createApp } from '@backstage/frontend-defaults'; + +const app = createApp({ + // ... + featureFlags: [ + { + name: 'tech-radar', + description: 'Enables the tech radar plugin', + }, + ], + // ... +}); +``` + +## Enabling Feature Flags + +Feature flags are defaulted to off and can be updated by individual users in the backstage interface. These are set by navigating to the page under `Settings` > `Feature Flags`. + +The user's selection is saved in the user's browser local storage. Once a feature flag is toggled it may be required for a user to refresh the page to see the change. + +## Evaluating Feature Flag State + +You can query a feature flag using the [FeatureFlagsApi](https://backstage.io/api/stable/interfaces/_backstage_frontend-plugin-api.index.FeatureFlagsApi.html): + +```tsx +import { useApi, featureFlagsApiRef } from '@backstage/frontend-plugin-api'; + +function MyComponent() { + const featureFlagsApi = useApi(featureFlagsApiRef); + + if (featureFlagsApi.isActive('show-example-feature')) { + return ; + } + return ; +} +``` diff --git a/docs/getting-started/config/authentication--old.md b/docs/getting-started/config/authentication--old.md new file mode 100644 index 0000000000..cc02eb2b7f --- /dev/null +++ b/docs/getting-started/config/authentication--old.md @@ -0,0 +1,213 @@ +--- +id: authentication--old +title: Authentication +description: How to setup authentication for your Backstage app +--- + +:::info +This documentation is written for the old frontend system. If you are on the [new frontend system](../../frontend-system/index.md) you may want to read [its own article](./authentication.md) instead. +::: + +Audience: Admins or Developers + +## Summary + +We'll be walking you through how to setup authentication for your Backstage app using GitHub. After finishing this guide, you'll have both working authentication and users in your Backstage app to match to the users logging in! + +There are multiple authentication providers available for you to use with Backstage, feel free to follow [their instructions for adding authentication](../../auth/index--old.md). + +:::note Note + +The default Backstage app comes with a guest Sign In Resolver. This resolver makes all users share a single "guest" identity and is only intended as a minimum requirement to quickly get up and running. You can read more about how [Sign In Resolvers](../../auth/identity-resolver.md#sign-in-resolvers) play a role in creating a [Backstage User Identity](../../auth/identity-resolver.md#backstage-user-identity) for logged in users. + +::: + +## Setting up authentication + +For this tutorial we choose to use GitHub, a free service most of you might be familiar with, and we'll be using an OAuth app. For detailed options, see +[the GitHub auth provider documentation](../../auth/github/provider.md#create-an-oauth-app-on-github). + +Go to [https://github.com/settings/applications/new](https://github.com/settings/applications/new) to create your OAuth App. The "Homepage URL" should point to Backstage's frontend, in our tutorial it would be `http://localhost:3000`. The "Authorization callback URL" will point to the auth backend, which will most likely be `http://localhost:7007/api/auth/github/handler/frame`. + +![Screenshot of the GitHub OAuth creation page](../../assets/getting-started/gh-oauth.png) + +Take note of the `Client ID` and the `Client Secret` (clicking the "Generate a new client secret" button will get this value for you). Open `app-config.yaml`, and add them as `clientId` and `clientSecret` in this file. It should end up looking like this: + +```yaml title="app-config.yaml" +auth: + # see https://backstage.io/docs/auth/ to learn about auth providers + /* highlight-add-start */ + environment: development + /* highlight-add-end */ + providers: + # See https://backstage.io/docs/auth/guest/provider + guest: {} + /* highlight-add-start */ + github: + development: + clientId: YOUR CLIENT ID + clientSecret: YOUR CLIENT SECRET + /* highlight-add-end */ +``` + +## Add sign-in option to the frontend + +The next step is to change the sign-in page. For this, you'll actually need to write some code. + +Open `packages/app/src/App.tsx` and below the last `import` line, add: + +```typescript title="packages/app/src/App.tsx" +import { githubAuthApiRef } from '@backstage/core-plugin-api'; +``` + +Search for `const app = createApp({` in this file, and replace: + +```tsx title="packages/app/src/App.tsx" +components: { + SignInPage: props => , +}, +``` + +with + +```tsx title="packages/app/src/App.tsx" +components: { + SignInPage: props => ( + + ), +}, +``` + +## Add sign-in resolver(s) + +Next we need to add the sign-in resolver to our configuration. Here's how: + +```yaml title="app-config.yaml" +auth: + # see https://backstage.io/docs/auth/ to learn about auth providers + environment: development + providers: + # See https://backstage.io/docs/auth/guest/provider + guest: {} + github: + development: + clientId: YOUR CLIENT ID + clientSecret: YOUR CLIENT SECRET + /* highlight-add-start */ + signIn: + resolvers: + # Matches the GitHub username with the Backstage user entity name. + # See https://backstage.io/docs/auth/github/provider#resolvers for more resolvers. + - resolver: usernameMatchingUserEntityName + /* highlight-add-end */ +``` + +What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get an "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections. + +Learn more about this topic in the [Sign-in Resolvers](../../auth/identity-resolver.md#sign-in-resolvers) documentation. + +## Add the auth provider to the backend + +To add the auth provider to the backend, we will first need to install the package by running this command: + +```bash title="from your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-github-provider +``` + +Then we will need to add this line: + +```ts title="in packages/backend/src/index.ts" +backend.add(import('@backstage/plugin-auth-backend')); +/* highlight-add-start */ +backend.add(import('@backstage/plugin-auth-backend-module-github-provider')); +/* highlight-add-end */ +``` + +Restart Backstage from the terminal, by stopping it with `Ctrl+C`, and starting it with `yarn start`. You should be welcomed by a login prompt! If you try to login at this point you will get a "Failed to sign-in, unable to resolve user identity" message, read on as we'll fix that next. + +:::note Note + +Sometimes the frontend starts before the backend resulting in errors on the sign in page. Wait for the backend to start and then reload Backstage to proceed. + +::: + +## Adding a User + +The recommended approach for adding Users, and Groups, into your Catalog is to use one of the existing Org Entity Providers - [like this one for GitHub](https://backstage.io/docs/integrations/github/org) - or if those don't work you may need to [create one](https://backstage.io/docs/features/software-catalog/external-integrations#custom-entity-providers) that fits your Organization's needs. + +For the sake of this guide we'll simply step you though adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that: + +1. First open the `/examples/org.yaml` file in your text editor of choice +2. At the bottom we'll add the following YAML: + + ```yaml + --- + apiVersion: backstage.io/v1alpha1 + kind: User + metadata: + name: YOUR GITHUB USERNAME + spec: + memberOf: [guests] + ``` + +3. Now make sure to replace the text "YOUR GITHUB USERNAME" with your actual GitHub User name. + +Let's restart Backstage from the terminal once more, by stopping it with `Ctrl+C`, and starting it with `yarn start`. You should now be able to log into Backstage and see items in your Catalog. + +To learn more about Authentication in Backstage, here are some docs you +could read: + +- [Authentication in Backstage](../../auth/index.md) +- [Using organizational data from GitHub](../../integrations/github/org.md) + +## Setting up a GitHub Integration + +The GitHub integration supports loading catalog entities from GitHub or GitHub Enterprise. Entities can be added to static catalog configuration, registered with the catalog-import plugin, or discovered from a GitHub organization. Users and Groups can also be loaded from an organization. While using [GitHub Apps](../../integrations/github/github-apps.md) might be the best way to set up integrations, for this tutorial you'll use a Personal Access Token. + +Create your Personal Access Token by opening [the GitHub token creation page](https://github.com/settings/tokens/new). Use a name to identify this token and put it in the notes field. Choose a number of days for expiration. If you have a hard time picking a number, we suggest to go for 7 days, it's a lucky number. + +![Screenshot of the GitHub Personal Access Token creation page](../../assets/getting-started/gh-pat.png) + +Set the scope to your likings. For this tutorial, selecting `repo` and `workflow` is required as the scaffolding job in this guide configures a GitHub actions workflow for the newly created project. + +For this tutorial, we will be writing the token to `app-config.local.yaml`. This file might not exist for you, so if it doesn't go ahead and create it alongside the `app-config.yaml` at the root of the project. This file should also be excluded in `.gitignore`, to avoid accidental committing of this file. More details on this file can be found in the [Static Configuration documentation](../../conf/index.md). + +In your `app-config.local.yaml` go ahead and add the following: + +```yaml title="app-config.local.yaml" +integrations: + github: + - host: github.com + token: ghp_urtokendeinfewinfiwebfweb # this should be the token from GitHub +``` + +That's settled. This information will be leveraged by other plugins. + +If you're looking for a more production way to manage this secret, then you can do the following with the token being stored in an environment variable called `GITHUB_TOKEN`. + +```yaml title="app-config.local.yaml" +integrations: + github: + - host: github.com + token: ${GITHUB_TOKEN} # this will use the environment variable GITHUB_TOKEN +``` + +:::note Note + +If you've updated the configuration for your integration, it's likely that the backend will need a restart to apply these changes. To do this, stop the running instance in your terminal with `Control-C`, then start it again with `yarn start`. Once the backend has restarted, retry the operation. + +::: + +Some helpful links, for if you want to learn more about: + +- [Other available integrations](../../integrations/index.md) +- [Using GitHub Apps instead of a Personal Access Token](../../integrations/github/github-apps.md#docsNav) diff --git a/docs/getting-started/config/authentication.md b/docs/getting-started/config/authentication.md index e25f357ff8..9df27692b8 100644 --- a/docs/getting-started/config/authentication.md +++ b/docs/getting-started/config/authentication.md @@ -4,6 +4,10 @@ title: Authentication description: How to setup authentication for your Backstage app --- +:::info +This documentation is written for [the new frontend system](../../frontend-system/index.md). If you are on the old frontend system you may want to read [its own article](./authentication--old.md) instead. +::: + Audience: Admins or Developers ## Summary @@ -50,37 +54,63 @@ auth: The next step is to change the sign-in page. For this, you'll actually need to write some code. -Open `packages/app/src/App.tsx` and below the last `import` line, add: +First let's add the packages we need, do this from the root: + +```shell +yarn --cwd packages/app add @backstage/core-plugin-api @backstage/plugin-app-react +``` + +Then open `packages/app/src/App.tsx` and below the last `import` line, add: ```typescript title="packages/app/src/App.tsx" import { githubAuthApiRef } from '@backstage/core-plugin-api'; +import { SignInPageBlueprint } from '@backstage/plugin-app-react'; +import { SignInPage } from '@backstage/core-components'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; ``` -Search for `const app = createApp({` in this file, and replace: +Now below this we are going to use the `SignInPageBlueprint` to create an extension, add this code block to do that: + +```tsx +const signInPage = SignInPageBlueprint.make({ + params: { + loader: async () => props => + ( + + ), + }, +}); +``` + +Search for the `createApp()` function call in this file, and replace: ```tsx title="packages/app/src/App.tsx" -components: { - SignInPage: props => , -}, +export default createApp({ + features: [catalogPlugin, navModule], +}); ``` with ```tsx title="packages/app/src/App.tsx" -components: { - SignInPage: props => ( - - ), -}, +export default createApp({ + features: [ + catalogPlugin, + navModule, + createFrontendModule({ + pluginId: 'app', + extensions: [signInPage], + }), + ], +}); ``` ## Add sign-in resolver(s) @@ -107,7 +137,7 @@ auth: /* highlight-add-end */ ``` -What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get an "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections. +What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get a "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections. Learn more about this topic in the [Sign-in Resolvers](../../auth/identity-resolver.md#sign-in-resolvers) documentation. @@ -140,7 +170,7 @@ Sometimes the frontend starts before the backend resulting in errors on the sign The recommended approach for adding Users, and Groups, into your Catalog is to use one of the existing Org Entity Providers - [like this one for GitHub](https://backstage.io/docs/integrations/github/org) - or if those don't work you may need to [create one](https://backstage.io/docs/features/software-catalog/external-integrations#custom-entity-providers) that fits your Organization's needs. -For the sake of this guide we'll simply step you though adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that: +For the sake of this guide we'll simply step you through adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that: 1. First open the `/examples/org.yaml` file in your text editor of choice 2. At the bottom we'll add the following YAML: diff --git a/docs/getting-started/configure-app-with-plugins--old.md b/docs/getting-started/configure-app-with-plugins--old.md new file mode 100644 index 0000000000..1c9898fe27 --- /dev/null +++ b/docs/getting-started/configure-app-with-plugins--old.md @@ -0,0 +1,131 @@ +--- +id: configure-app-with-plugins--old +title: Configuring App with plugins (Old Frontend System) +description: Documentation on How Configuring App with plugins +--- + +::::info +This documentation is for Backstage apps that still use the old frontend +system. If your app uses the new frontend system, read the +[current guide](./configure-app-with-plugins.md) instead. +:::: + +Audience: Developers + +:::note Note +Backstage plugins are primarily written using [TypeScript](https://www.typescriptlang.org), [Node.js](https://nodejs.org) and [React](https://reactjs.org). Having an understanding of these technologies will be beneficial on your journey to customizing Backstage! +::: + +## Summary + +Backstage plugins customize the app for your needs. There is a +[plugin directory](https://backstage.io/plugins) with plugins for many common +infrastructure needs - CI/CD, monitoring, auditing, and more. + +## Adding existing plugins to your app + +The following steps assume that you have +[created a Backstage app](./index.md) and want to add an existing plugin +to it. + +You can find many wonderful plugins out there for Backstage, for example through the [Community Plugins Repository](https://github.com/backstage/community-plugins) and the [Backstage Plugin Directory](https://backstage.io/plugins). + +Adding plugins to your Backstage app is generally a simple process, and ideally each plugin will come with its own documentation on how to install and configure it. In this example we will add the [Tech Radar plugin](https://github.com/backstage/community-plugins/tree/main/workspaces/tech-radar/plugins/tech-radar) to our Backstage app. + +1. Add the plugin's npm package to the repo: + + ```bash title="From your Backstage root directory" + yarn --cwd packages/app add @backstage-community/plugin-tech-radar + ``` + + Note the plugin is added to the `app` package, rather than the root + `package.json`. Backstage Apps are set up as monorepos with + [Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/). Frontend UI Plugins are generally added to the `app` folder, while Backend Plugins are added to the `backend` folder. In the example above, the plugin is added to the `app` package because we are adding the frontend plugin. + +2. Now, modify your app routes to include the Router component exported from the tech radar, for example: + + ```tsx title="packages/app/src/App.tsx" + /* highlight-add-start */ + import { TechRadarPage } from '@backstage-community/plugin-tech-radar'; + /* highlight-add-end */ + + const routes = ( + + /* highlight-add-start */ + } + /> + /* highlight-add-end */ + + ); + ``` + + This is just one example, and if you'd like to continue adding the Tech Radar plugin you can do so by going [here](https://github.com/backstage/community-plugins/tree/main/workspaces/tech-radar/plugins/tech-radar), keep in mind each Backstage instance may integrate content or + cards to suit their needs on different pages, tabs, etc. In addition, while some + plugins such as this example are designed to be used in a stand-alone fashion, + others may be intended to annotate or support specific software catalog entities + and would be added elsewhere in the app. + +### Adding a plugin page to the Sidebar + +In a standard Backstage app created with +[@backstage/create-app](./index.md), the sidebar is managed inside +`packages/app/src/components/Root/Root.tsx`. The file exports the entire +`Sidebar` element of your app, which you can extend with additional entries by +adding new `SidebarItem` elements. + +For example, if you install the `api-docs` plugin, a matching `SidebarItem` +could be something like this: + +```tsx title="packages/app/src/components/Root/Root.tsx" +// Import icon from Material UI +import ExtensionIcon from '@material-ui/icons/Extension'; + +// ... inside the AppSidebar component +; +``` + +You can also use your own SVGs directly as icon components. Just make sure they +are sized according to the Material UI's +[SvgIcon](https://material-ui.com/api/svg-icon/) default of 24x24px, and wrap +the SVG elements in a `SvgIcon` component like this: + +```tsx +import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; + +export const ExampleIcon = (props: SvgIconProps) => ( + + + + + + +); +``` + +On mobile devices the `Sidebar` is displayed at the bottom of the screen. For +customizing the experience you can group `SidebarItems` in a `SidebarGroup` +(Example 1) or create a `SidebarGroup` with a link (Example 2). All +`SidebarGroup`s are displayed in the bottom navigation with an icon. + +```tsx +// Example 1 +} label="Menu"> + ... + + ... + +``` + +```tsx +// Example 2 +} to="/search"> + ... + + ... + +``` + +If no `SidebarGroup` is provided a default menu will display the `Sidebar` +content. diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index 010917f6c8..0bd69d4144 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -4,6 +4,13 @@ title: Configuring App with plugins description: Documentation on How Configuring App with plugins --- +::::info +This documentation is written for the new frontend system, which is the default +in new Backstage apps. If your Backstage app still uses the old frontend system, +read the [old frontend system version of this guide](./configure-app-with-plugins--old.md) +instead. +:::: + Audience: Developers :::note Note @@ -26,100 +33,64 @@ You can find many wonderful plugins out there for Backstage, for example through Adding plugins to your Backstage app is generally a simple process, and ideally each plugin will come with its own documentation on how to install and configure it. In this example we will add the [Tech Radar plugin](https://github.com/backstage/community-plugins/tree/main/workspaces/tech-radar/plugins/tech-radar) to our Backstage app. -1. Add the plugin's npm package to the repo: +### 1. Install the plugin package - ```bash title="From your Backstage root directory" - yarn --cwd packages/app add @backstage-community/plugin-tech-radar - ``` +Add the plugin's npm package to the repo: - Note the plugin is added to the `app` package, rather than the root - `package.json`. Backstage Apps are set up as monorepos with - [Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/). Frontend UI Plugins are generally added to the `app` folder, while Backend Plugins are added to the `backend` folder. In the example above, the plugin is added to the `app` package because we are adding the frontend plugin. - -2. Now, modify your app routes to include the Router component exported from the tech radar, for example: - - ```tsx title="packages/app/src/App.tsx" - /* highlight-add-start */ - import { TechRadarPage } from '@backstage-community/plugin-tech-radar'; - /* highlight-add-end */ - - const routes = ( - - /* highlight-add-start */ - } - /> - /* highlight-add-end */ - - ); - ``` - - This is just one example, and if you'd like to continue adding the Tech Radar plugin you can do so by going [here](https://github.com/backstage/community-plugins/tree/main/workspaces/tech-radar/plugins/tech-radar), keep in mind each Backstage instance may integrate content or - cards to suit their needs on different pages, tabs, etc. In addition, while some - plugins such as this example are designed to be used in a stand-alone fashion, - others may be intended to annotate or support specific software catalog entities - and would be added elsewhere in the app. - -### Adding a plugin page to the Sidebar - -In a standard Backstage app created with -[@backstage/create-app](./index.md), the sidebar is managed inside -`packages/app/src/components/Root/Root.tsx`. The file exports the entire -`Sidebar` element of your app, which you can extend with additional entries by -adding new `SidebarItem` elements. - -For example, if you install the `api-docs` plugin, a matching `SidebarItem` -could be something like this: - -```tsx title="packages/app/src/components/Root/Root.tsx" -// Import icon from Material UI -import ExtensionIcon from '@material-ui/icons/Extension'; - -// ... inside the AppSidebar component -; +```bash title="From your Backstage root directory" +yarn --cwd packages/app add @backstage-community/plugin-tech-radar ``` -You can also use your own SVGs directly as icon components. Just make sure they -are sized according to the Material UI's -[SvgIcon](https://material-ui.com/api/svg-icon/) default of 24x24px, and wrap -the SVG elements in a `SvgIcon` component like this: +Note the plugin is added to the `app` package, rather than the root +`package.json`. Backstage Apps are set up as monorepos with +[Yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/). Frontend UI plugins are generally added to the `app` folder, while backend plugins are added to the `backend` folder. -```tsx -import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; +### 2. Verify the plugin is available -export const ExampleIcon = (props: SvgIconProps) => ( - - - - - - -); +With the new frontend system, plugins are automatically discovered and installed in your app through [feature discovery](../frontend-system/building-apps/05-installing-plugins.md#feature-discovery). This is enabled by the default `app-config.yaml` setting: + +```yaml title="app-config.yaml" +app: + packages: all ``` -On mobile devices the `Sidebar` is displayed at the bottom of the screen. For -customizing the experience you can group `SidebarItems` in a `SidebarGroup` -(Example 1) or create a `SidebarGroup` with a link (Example 2). All -`SidebarGroup`s are displayed in the bottom navigation with an icon. +Once the package is installed, the plugin is ready to use — no code changes needed! Start your app with `yarn start` and navigate to `/tech-radar` to see the plugin in action. -```tsx -// Example 1 -} label="Menu"> - ... - - ... - +This is just one example, and if you'd like to continue adding the Tech Radar plugin you can do so by going [here](https://github.com/backstage/community-plugins/tree/main/workspaces/tech-radar/plugins/tech-radar). Keep in mind each Backstage instance may integrate content or cards to suit their needs on different pages, tabs, etc. In addition, while some plugins such as this example are designed to be used in a stand-alone fashion, others may be intended to annotate or support specific software catalog entities and would be added elsewhere in the app. + +### 3. Optional: Configure the plugin + +Plugins can be further customized through configuration in your `app-config.yaml`. For example, you can configure extension settings under the `app.extensions` section: + +```yaml title="app-config.yaml" +app: + extensions: + - page:tech-radar: + config: + path: /tech-radar ``` -```tsx -// Example 2 -} to="/search"> - ... - - ... - +For details on what configuration options are available, refer to the plugin's own documentation or the [Configuring Extensions](../frontend-system/building-apps/02-configuring-extensions.md) guide. + +### 4. Optional: Manually install a plugin + +If you need more control over plugin installation, or if [feature discovery](../frontend-system/building-apps/05-installing-plugins.md#feature-discovery) is not enabled, you can install plugins manually by importing them and passing them to `createApp`: + +```tsx title="packages/app/src/App.tsx" +import { createApp } from '@backstage/frontend-defaults'; +import techRadarPlugin from '@backstage-community/plugin-tech-radar/alpha'; + +const app = createApp({ + features: [techRadarPlugin], +}); + +export default app.createRoot(); ``` -If no `SidebarGroup` is provided a default menu will display the `Sidebar` -content. +For more details and alternative installation methods, see [Installing Plugins](../frontend-system/building-apps/05-installing-plugins.md). + +## How the sidebar works + +In the new frontend system, plugins that provide a page automatically register a navigation item in the sidebar. You don't need to manually add `SidebarItem` elements for most plugins. + +If you want to customize sidebar behavior — for example, reordering items, grouping them, or adding custom entries — you can override the built-in `app/nav` extension. See the [migration guide's sidebar section](../frontend-system/building-apps/08-migrating.md#app-root-sidebar) for details on how to create a custom sidebar layout. diff --git a/docs/getting-started/homepage--old.md b/docs/getting-started/homepage--old.md new file mode 100644 index 0000000000..98021d76a2 --- /dev/null +++ b/docs/getting-started/homepage--old.md @@ -0,0 +1,201 @@ +--- +id: homepage--old +title: Backstage homepage - Setup and Customization (Old Frontend System) +description: Documentation on setting up and customizing Backstage homepage +--- + +::::info +This documentation is for Backstage apps that still use the old frontend +system. If your app uses the new frontend system, read the +[current homepage guide](./homepage.md) instead. +:::: + +## Homepage + +Having a good Backstage homepage can significantly improve the discoverability +of the platform. You want your users to find all the things they need right +from the homepage and never have to remember direct URLs in Backstage. The +[Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home) +introduces a system for composing a homepage for Backstage in order to surface +relevant info and provide convenient shortcuts for common tasks. It's designed +with composability in mind with an open ecosystem that allows anyone to +contribute with any component, to be included in any homepage. + +For App Integrators, the system is designed to be composable to give total +freedom in designing a Homepage that suits the needs of the organization. From +the perspective of a Component Developer who wishes to contribute with building +blocks to be included in Homepages, there's a convenient interface for bundling +the different parts and exporting them with both error boundary and lazy +loading handled under the surface. + +At the end of this tutorial, you can expect: + +- Your Backstage app to have a dedicated homepage instead of Software Catalog. +- Understand the composability of homepage and how to start customizing it for + your own organization. + +### Prerequisites + +Before we begin, make sure + +- You have created your own standalone Backstage app using + [`@backstage/create-app`](./index.md#1-create-your-backstage-app) and not + using a fork of the [backstage](https://github.com/backstage/backstage) + repository. +- You do not have an existing homepage, and by default you are redirected to + Software Catalog when you open Backstage. + +Now, let's get started by installing the home plugin and creating a simple +homepage for your Backstage app. + +## Setup + +### 1. Install the plugin + +```bash title="From your Backstage root directory" +yarn --cwd packages/app add @backstage/plugin-home +``` + +### 2. Create a new HomePage component + +Inside your `packages/app` directory, create a new file where our new homepage +component is going to live. Create `packages/app/src/components/home/HomePage.tsx` +with the following initial code + +```tsx +export const HomePage = () => ( + /* We will shortly compose a pretty homepage here. */ +

Welcome to Backstage!

+); +``` + +### 3. Update router for the root `/` route + +If you don't have a homepage already, most likely you have a redirect setup to +use the Catalog homepage as a homepage. + +Inside your `packages/app/src/App.tsx`, look for + +```tsx title="packages/app/src/App.tsx" +const routes = ( + + + {/* ... */} + +); +``` + +Let's replace the `` line and use the new component we created in the +previous step as the new homepage. + +```tsx title="packages/app/src/App.tsx" +/* highlight-add-start */ +import { HomepageCompositionRoot } from '@backstage/plugin-home'; +import { HomePage } from './components/home/HomePage'; +/* highlight-add-end */ + +const routes = ( + + {/* highlight-remove-next-line */} + + {/* highlight-add-start */} + }> + + + {/* highlight-add-end */} + {/* ... */} + +); +``` + +### 4. Update sidebar items + +Let's update the route for "Home" in the Backstage sidebar to point to the new +homepage. We'll also add a Sidebar item to quickly open Catalog. + +| Before | After | +| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| ![Sidebar without Catalog](../assets/getting-started/sidebar-without-catalog.png) | ![Sidebar with Catalog](../assets/getting-started/sidebar-with-catalog.png) | + +The code for the Backstage sidebar is most likely inside your +[`packages/app-legacy/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app-legacy/src/components/Root/Root.tsx). + +Let's make the following changes + +```tsx title="packages/app/src/components/Root/Root.tsx" +/* highlight-add-next-line */ +import CategoryIcon from '@material-ui/icons/Category'; + +export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + + {/* ... */} + }> + {/* Global nav, not org-specific */} + {/* highlight-remove-next-line */} + + {/* highlight-add-start */} + + + {/* highlight-add-end */} + + + + + {/* End global nav */} + + {/* ... */} + + + +); +``` + +That's it! You should now have _(although slightly boring)_ a homepage! + + + +![Screenshot of a blank homepage](../assets/getting-started/simple-homepage.png) + +In the next steps, we will make it interesting and useful! + +#### Use the default template + +There is a default homepage template +([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template)) +which we will use to set up our homepage. Checkout the +[blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates) +about the Backstage homepage templates for more information. + + + +#### Composing your homepage + +Composing a homepage is no different from creating a regular React Component, +i.e. the App Integrator is free to include whatever content they like. However, +there are components developed with the homepage in mind. If you are looking +for components to use when composing your homepage, you can take a look at the +[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components) +in storybook. If you don't find a component that suits your needs but want to +contribute, check the +[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing). + +> If you want to use one of the available homepage templates you can find the +> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates) +> in the storybook under the "Home" plugin. And if you would like to contribute +> a template, please see the +> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing) + +```tsx +import Grid from '@material-ui/core/Grid'; +import { HomePageCompanyLogo } from '@backstage/plugin-home'; + +export const HomePage = () => ( + + + + + +); +``` diff --git a/docs/getting-started/homepage.md b/docs/getting-started/homepage.md index 05e422610a..22761eb6ed 100644 --- a/docs/getting-started/homepage.md +++ b/docs/getting-started/homepage.md @@ -4,6 +4,13 @@ title: Backstage homepage - Setup and Customization description: Documentation on setting up and customizing Backstage homepage --- +::::info +This documentation is written for the new frontend system, which is the default +in new Backstage apps. If your Backstage app still uses the old frontend system, +read the [old frontend system version of this guide](./homepage--old.md) +instead. +:::: + ## Homepage Having a good Backstage homepage can significantly improve the discoverability of the platform. You want your users to find all the things they need right from the homepage and never have to remember direct URLs in Backstage. The [Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home) introduces a system for composing a homepage for Backstage in order to surface relevant info and provide convenient shortcuts for common tasks. It's designed with composability in mind with an open ecosystem that allows anyone to contribute with any component, to be included in any homepage. @@ -24,39 +31,17 @@ Before we begin, make sure Now, let's get started by installing the home plugin and creating a simple homepage for your Backstage app. -## Setup Methods +## Setup -There are two ways to set up the home plugin, depending on which frontend system your Backstage app uses: - -1. **New Frontend System (Recommended)** - For apps using the new plugin system with extensions and blueprints -2. **Legacy Frontend System** - For existing apps using the legacy plugin architecture - -### New Frontend System Setup - -If your Backstage app uses the [new frontend system](../frontend-system/index.md), follow these steps: - -#### 1. Install the plugin +### 1. Install the plugin ```bash title="From your Backstage root directory" yarn --cwd packages/app add @backstage/plugin-home ``` -#### 2. Add the plugin to your app configuration +Once installed, the plugin is automatically available in your app through the default feature discovery. For more details and alternative installation methods, see [installing plugins](../frontend-system/building-apps/05-installing-plugins.md). -Update your `packages/app/src/app.tsx` to include the home plugin: - -```tsx title="packages/app/src/app.tsx" -import homePlugin from '@backstage/plugin-home/alpha'; - -const app = createApp({ - features: [ - // ... other plugins - homePlugin, - ], -}); -``` - -#### 3. Configure the homepage as your root route +### 2. Configure the homepage as your root route By default, the homepage will be available at `/home`. To make it your app's landing page at `/`, add this configuration to your `app-config.yaml`: @@ -70,7 +55,7 @@ app: The plugin will automatically add a "Home" navigation item to your sidebar and provide a basic homepage layout. -#### 4. Optional: Enable visit tracking +### 3. Optional: Enable visit tracking Visit tracking is an optional feature that allows users to see their recently visited and most visited pages on the homepage. This feature is **disabled by default** to give you control over what data is collected and stored. @@ -88,156 +73,12 @@ app: - app-root-element:home/visit-listener: true ``` -#### 5. Customizing your homepage +### 4. Customizing your homepage -The New Frontend System provides powerful customization options: +The home plugin provides powerful customization options: **Custom Homepage Layouts**: Use the `HomePageLayoutBlueprint` from `@backstage/plugin-home-react/alpha` to create custom homepage layouts with your own design and widget arrangements. A layout receives the installed widgets and is responsible for rendering them. If no custom layout is installed, the plugin provides a built-in default. **Adding Homepage Widgets**: Register custom widgets using the `HomePageWidgetBlueprint` from the `@backstage/plugin-home-react/alpha` package. For detailed instructions on creating custom layouts, registering widgets, and advanced configuration options, see the [Home plugin documentation](https://github.com/backstage/backstage/tree/master/plugins/home#readme). - -### Legacy Frontend System Setup - -If your Backstage app uses the legacy frontend system, follow these steps: - -#### 1. Install the plugin - -```bash title="From your Backstage root directory" -yarn --cwd packages/app add @backstage/plugin-home -``` - -#### 2. Create a new HomePage component - -Inside your `packages/app` directory, create a new file where our new homepage component is going to live. Create `packages/app/src/components/home/HomePage.tsx` with the following initial code - -```tsx -export const HomePage = () => ( - /* We will shortly compose a pretty homepage here. */ -

Welcome to Backstage!

-); -``` - -#### 3. Update router for the root `/` route - -If you don't have a homepage already, most likely you have a redirect setup to use the Catalog homepage as a homepage. - -Inside your `packages/app/src/App.tsx`, look for - -```tsx title="packages/app/src/App.tsx" -const routes = ( - - - {/* ... */} - -); -``` - -Let's replace the `` line and use the new component we created in the previous step as the new homepage. - -```tsx title="packages/app/src/App.tsx" -/* highlight-add-start */ -import { HomepageCompositionRoot } from '@backstage/plugin-home'; -import { HomePage } from './components/home/HomePage'; -/* highlight-add-end */ - -const routes = ( - - {/* highlight-remove-next-line */} - - {/* highlight-add-start */} - }> - - - {/* highlight-add-end */} - {/* ... */} - -); -``` - -#### 4. Update sidebar items - -Let's update the route for "Home" in the Backstage sidebar to point to the new homepage. We'll also add a Sidebar item to quickly open Catalog. - -| Before | After | -| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | -| ![Sidebar without Catalog](../assets/getting-started/sidebar-without-catalog.png) | ![Sidebar with Catalog](../assets/getting-started/sidebar-with-catalog.png) | - -The code for the Backstage sidebar is most likely inside your [`packages/app-legacy/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app-legacy/src/components/Root/Root.tsx). - -Let's make the following changes - -```tsx title="packages/app/src/components/Root/Root.tsx" -/* highlight-add-next-line */ -import CategoryIcon from '@material-ui/icons/Category'; - -export const Root = ({ children }: PropsWithChildren<{}>) => ( - - - - {/* ... */} - }> - {/* Global nav, not org-specific */} - {/* highlight-remove-next-line */} - - {/* highlight-add-start */} - - - {/* highlight-add-end */} - - - - - {/* End global nav */} - - {/* ... */} - - - -); -``` - -That's it! You should now have _(although slightly boring)_ a homepage! - - - -![Screenshot of a blank homepage](../assets/getting-started/simple-homepage.png) - -In the next steps, we will make it interesting and useful! - -### Use the default template - -There is a default homepage template ([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template)) which we will use to set up our homepage. Checkout the [blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates) about the Backstage homepage templates for more information. - - - -### Composing your homepage - -Composing a homepage is no different from creating a regular React Component, -i.e. the App Integrator is free to include whatever content they like. However, -there are components developed with the homepage in mind. If you are looking -for components to use when composing your homepage, you can take a look at the -[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components) -in storybook. If you don't find a component that suits your needs but want to -contribute, check the -[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing). - -> If you want to use one of the available homepage templates you can find the -> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates) -> in the storybook under the "Home" plugin. And if you would like to contribute -> a template, please see the -> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing) - -```tsx -import Grid from '@material-ui/core/Grid'; -import { HomePageCompanyLogo } from '@backstage/plugin-home'; - -export const HomePage = () => ( - - - - - -); -``` diff --git a/docs/getting-started/keeping-backstage-updated.md b/docs/getting-started/keeping-backstage-updated.md index c93c5200f6..a55f872f53 100644 --- a/docs/getting-started/keeping-backstage-updated.md +++ b/docs/getting-started/keeping-backstage-updated.md @@ -151,12 +151,14 @@ down the number of duplicate packages. ## Proxy -The Backstage CLI uses [global-agent](https://www.npmjs.com/package/global-agent) and `undici` to configure HTTP/HTTPS proxy settings using environment variables. This allows you to route the CLI’s network traffic through a proxy server, which can be useful in environments with restricted internet access. +On Node.js 22.21.0+, the Backstage CLI respects the standard `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables when `NODE_USE_ENV_PROXY=1` is set. See the [corporate proxy guide](../tutorials/corporate-proxy.md) for full details. + +On older Node.js versions, the CLI falls back to [global-agent](https://www.npmjs.com/package/global-agent) and `undici` for proxy support, which require their own environment variables (prefixed with `GLOBAL_AGENT_`). This allows you to route the CLI’s network traffic through a proxy server, which can be useful in environments with restricted internet access. Additionally, yarn needs a proxy too (sometimes), when in environments with restricted internet access. It uses different settings than the other modules. If you decide to use the backstage yarn plugin [mentioned above](#plugin), you will need to set additional proxy values. If you will always need proxy settings in all environments and situations, you can add `httpProxy` and `httpsProxy` values to [the yarnrc.yml file](https://yarnpkg.com/configuration/yarnrc). If some environments need it (say a developer workstation) but other environments do not (perhaps a CI build server running on AWS), then you may not want to update the yarnrc.yml file but just set environment variables `YARN_HTTP_PROXY` and `YARN_HTTPS_PROXY` in the environments/situations where you need to proxy. -**If you plan to use the backstage yarn plugin, you will need these extra yarn proxy settings to both install the plugin and run the `versions:bump` command**. If you do not plan to use the backstage yarn plugin, it seems like the global agent proxy settings alone are sufficient. +**If you plan to use the backstage yarn plugin, you will need these extra yarn proxy settings to both install the plugin and run the `versions:bump` command**. If you do not plan to use the backstage yarn plugin, it seems like the proxy settings alone are sufficient. ### Example Configuration @@ -164,9 +166,10 @@ If you will always need proxy settings in all environments and situations, you c export HTTP_PROXY=http://proxy.company.com:8080 export HTTPS_PROXY=https://secure-proxy.company.com:8080 export NO_PROXY=localhost,internal.company.com -export GLOBAL_AGENT_HTTP_PROXY=${HTTP_PROXY} -export GLOBAL_AGENT_HTTPS_PROXY=${HTTPS_PROXY} -export GLOBAL_AGENT_NO_PROXY=${NO_PROXY} +export NODE_USE_ENV_PROXY=1 # Node.js 22.21.0+ +export GLOBAL_AGENT_HTTP_PROXY=${HTTP_PROXY} # Node.js < 22.21.0 +export GLOBAL_AGENT_HTTPS_PROXY=${HTTPS_PROXY} # Node.js < 22.21.0 +export GLOBAL_AGENT_NO_PROXY=${NO_PROXY} # Node.js < 22.21.0 export YARN_HTTP_PROXY=${HTTP_PROXY} # optional export YARN_HTTPS_PROXY=${HTTPS_PROXY} # optional ``` diff --git a/docs/golden-path/adoption/001-getting-started.md b/docs/golden-path/adoption/001-getting-started.md index 574380f263..df5577527b 100644 --- a/docs/golden-path/adoption/001-getting-started.md +++ b/docs/golden-path/adoption/001-getting-started.md @@ -2,6 +2,7 @@ id: getting-started sidebar_label: 001 - Getting started title: Getting started with Backstage +description: An introduction to the Backstage adoption journey and what to expect --- The adoption journey is a bit different than the other Golden Paths. The goal of this guide is to prepare you for a successful implementation of Backstage in your organization. A technical understanding of Backstage is not needed for this Golden Path, just a desire to help the technical team that will be owning your Backstage instance. diff --git a/docs/golden-path/adoption/002-leadership-buy-in.md b/docs/golden-path/adoption/002-leadership-buy-in.md index 502970d3dc..ecb937c6e2 100644 --- a/docs/golden-path/adoption/002-leadership-buy-in.md +++ b/docs/golden-path/adoption/002-leadership-buy-in.md @@ -2,6 +2,7 @@ id: leadership-buy-in sidebar_label: 002 - Leadership buy-in title: Getting leadership buy-in +description: How to build a case for Backstage adoption and secure leadership support --- ## Summary diff --git a/docs/golden-path/adoption/003-setting-up-a-poc.md b/docs/golden-path/adoption/003-setting-up-a-poc.md index 155098c357..6d444de293 100644 --- a/docs/golden-path/adoption/003-setting-up-a-poc.md +++ b/docs/golden-path/adoption/003-setting-up-a-poc.md @@ -2,6 +2,7 @@ id: setting-up-a-poc sidebar_label: 003 - Setting up a PoC title: Setting up a PoC +description: How to set up a proof of concept Backstage instance for your organization --- If you're non-technical, this section should be completed by your technical partner. diff --git a/docs/golden-path/adoption/004-first-stakeholder-feedback.md b/docs/golden-path/adoption/004-first-stakeholder-feedback.md index 6207a49d10..d6cefe9461 100644 --- a/docs/golden-path/adoption/004-first-stakeholder-feedback.md +++ b/docs/golden-path/adoption/004-first-stakeholder-feedback.md @@ -2,6 +2,7 @@ id: first-stakeholder-feedback sidebar_label: 004 - Stakeholder Feedback title: First round of stakeholder feedback +description: How to gather and incorporate stakeholder feedback on your Backstage PoC --- Now that you have a PoC running, let's walk through how to get good feedback. You likely aren't the first person to hear about Backstage or maybe not even the first person to set up a PoC. There may be common pitfalls unique to your company that are worth knowing about - political, organizational or otherwise. diff --git a/docs/golden-path/adoption/005-customizing-your-instance.md b/docs/golden-path/adoption/005-customizing-your-instance.md index 9cc9a98d7a..ca33cba63a 100644 --- a/docs/golden-path/adoption/005-customizing-your-instance.md +++ b/docs/golden-path/adoption/005-customizing-your-instance.md @@ -2,6 +2,7 @@ id: customize-your-instance sidebar_label: 005 - Customizing your instance title: Customizing your instance +description: How to customize your Backstage instance based on user feedback --- You now have the knowledge of what your users want and the go from leadership to continue investing in Backstage. Your job now is to customize your instance for your users to really get the value from. Let's dive in! diff --git a/docs/golden-path/adoption/006-preparing-for-ga.md b/docs/golden-path/adoption/006-preparing-for-ga.md index 0b62f0fa25..0c6b820dbb 100644 --- a/docs/golden-path/adoption/006-preparing-for-ga.md +++ b/docs/golden-path/adoption/006-preparing-for-ga.md @@ -2,18 +2,130 @@ id: preparing-for-ga sidebar_label: 006 - Preparing for GA title: Preparing for GA +description: How to prepare your Backstage instance for a company-wide general availability launch --- We hope at this point that the developers you're working with have read the [golden path on deploying Backstage](../deployment/index.md). Your Backstage instance should be ready for the scale that comes with a full company launch. -## Launch Announcements +## Launch announcements - +Getting the word out is one of the most important parts of a successful general +availability (GA) launch. A good announcement does two things: it tells +developers that Backstage is available, and it tells them why they should care. + +### Use your internal communication channels + +Start with the channels your developers already use. Post in Slack or Teams +channels that reach engineering broadly, share a short write-up in your company +newsletter or engineering blog, and send a targeted email to team leads who can +cascade the message to their reports. Tailor the message for each channel; a +Slack announcement can be shorter and more conversational than a written post. + +Lead with the problem Backstage solves for your developers, not with a list of +features. Developers respond better to "you no longer need to chase down +ownership information across five different tools" than "we have launched a +software catalog." + +### Host an internal meetup or demo + +A live demo builds trust in a way that a written announcement cannot. Developers +can see the product in action, ask questions, and leave with a concrete +impression of how Backstage fits into their day-to-day work. + +Keep the demo short and focused. Walk through one or two high-value workflows, +ideally ones that address the pain points you identified during your stakeholder +feedback sessions. Leave time for questions. If the session is recorded, share +the recording in your communication channels so developers who couldn't attend can catch +up. + +Consider running multiple sessions to reach different time zones or teams. +Smaller, more targeted demos for specific teams can be more effective than a +single large all-hands. + +:::tip +Invite a developer from the teams that participated in your proof of concept +(PoC) to co-present. Peer endorsement carries more weight than a platform team +talking about their own product. +::: ## What to expect in the coming months - +The period immediately after GA is often slower than you expect. This is normal. +Developers are busy, habits are hard to change, and adoption takes time to build +momentum. The goal in these early months is not to force adoption but to remove +the friction that prevents it. + +### Listen to feedback early and often + +Set up a clear feedback channel from day one. This could be a dedicated Slack +channel, a form, or a recurring office hours session. Make it visible in your +launch announcement so developers know where to go. The feedback you receive in +the first few weeks is some of the most valuable you will ever get, because it +reflects the real first-time experience. + +Pay attention to the things developers are struggling with, not just the feature +requests. Struggles point to gaps in documentation, confusing workflows, or +missing integrations that are blocking adoption. + +### Use analytics to guide your decisions + +Backstage does not ship with usage analytics by default, but you can integrate +an analytics provider through the plugin ecosystem, you can find more information on this in the [Analytics](../../plugins/analytics.md) section of the Backstage documentation. Tracking which parts of +Backstage developers actually use helps you make informed decisions about where +to invest your time. + +Look for patterns: Are developers landing on the catalog but not drilling into +entity pages? Is the search feature underused? Are Software Templates being +triggered but not completed? These signals tell you where the experience is +breaking down and where it is working well. + +### Talk to your users directly + +Analytics tell you what is happening. Conversations tell you why. Schedule +regular check-ins with developers across different teams, especially those who +were early adopters. Ask them what they use, what they avoid, and what would +make Backstage more useful in their daily work. + +Short, informal conversations are often more revealing than formal surveys. +A five-minute chat with a developer who almost never opens Backstage can give +you more actionable insight than a month of dashboards. ## How to keep iterating - +GA is not the finish line. The most successful Backstage instances are the ones +that keep improving after launch, driven by a clear process for taking feedback +and turning it into changes. + +### Make decisions based on feedback + +Prioritize work that addresses real developer pain points over work that feels +interesting to build. When you receive recurring feedback about the same issue, +treat that as a strong signal. When feedback is mixed or unclear, go back to +your users and dig deeper before committing to a direction. + +Document the decisions you make and the reasoning behind them. This helps your +team stay aligned and gives you a record to reference when revisiting past +choices. + +### Look for processes that could be improved + +As Backstage matures in your organization, you will start to notice patterns in +how developers interact with it. Some of those patterns will reveal manual steps +that Backstage could automate, or workflows that exist outside Backstage that +would benefit from being brought in. + +Review your catalog regularly. Are entities going stale? Is ownership information +drifting out of date? These are signs that the processes around Backstage need +attention, not the product itself. Work with teams to build the habits and +automation that keep the data accurate. + +### Keep stakeholders informed + +Your leadership and key stakeholders backed this investment. Keep them updated +with regular progress reports that connect Backstage's impact to the outcomes +they care about: developer productivity, reduced toil, faster onboarding, and +improved system reliability. + +Share wins, but also be transparent about what is not working and what you plan +to do about it. Stakeholders who trust your judgment are more likely to continue +investing in the platform over time. diff --git a/docs/golden-path/adoption/007-plugin-ownership.md b/docs/golden-path/adoption/007-plugin-ownership.md index 17455f19e7..34aca366a4 100644 --- a/docs/golden-path/adoption/007-plugin-ownership.md +++ b/docs/golden-path/adoption/007-plugin-ownership.md @@ -2,16 +2,85 @@ id: plugin-ownership sidebar_label: 007 - Plugin Ownership title: Plugin Ownership +description: How to establish and manage plugin ownership across your organization --- -You're now well on your way to a healthy Backstage instance! It's been launched to the whole company and you're loving the feedback developers are giving you. Some developers have even started broaching writing their own plugins. +You're now well on your way to a healthy Backstage instance! It's been launched to the whole company and you're loving the feedback developers are giving you. Some developers have even started expressing interest in writing their own plugins. ## Inner source -Accepting internal contributions from other teams is a good sign that you are on the road to a developer portal tailored for your developers. This is a well paved path with many upsides, but a few downsides as well. As your Backstage instance grows in size and age, those same developers may be difficult to find. Your team may start to experience more and more struggle updating Backstage. +Accepting internal contributions from other teams is a good sign that you are on the road to a developer portal tailored for your developers. This is a well-paved path with many upsides, but a few downsides as well. As your Backstage instance grows in size and age, those same developers may be difficult to find and your team may start to experience more friction updating Backstage. - +### Readiness before you start -## Registering Plugins in Your Catalog +Inner sourcing is a genuinely rewarding initiative, but it works best when some +groundwork is already in place. Jumping into it too early can create unnecessary +friction for both the contributing teams and the team that owns Backstage. - +Before inviting contributions, its a good idea to have the following in place: + +- **A consistent starting point for new plugins.** Running `yarn new` out of the + box will scaffold a working Backstage plugin, which is a great starting point. + However, the CLI also supports + [custom templates](../../tooling/cli/04-templates.md#creating-your-own-cli-templates) + that you define yourself. With a custom template you can bake in your + company's best practices, coding conventions, and shared components from the + start, so every plugin begins from a baseline that already meets your + standards rather than having contributors piece that together themselves. +- **Style guides.** Document the coding conventions your plugins follow. This + includes TypeScript standards, test coverage expectations, and naming + conventions. +- **UI and UX guidelines.** Contributors should know how their plugin is + expected to look and behave within Backstage. Share your design system, any + component libraries you use, and patterns for things like loading states and + error handling. + +Sharing these resources with a contributing team before they start is far more +effective than reviewing them in a pull request after the fact. + +### Have a conversation before a team starts building + +When a team comes to you wanting to build a plugin, that is a great sign. Take +some time to chat with them about what they have in mind. This is not a review +process, it is a chance to understand what they are building and make sure you +can set them up for success. + +Some useful things to explore together: + +- What does the plugin do, and what problem does it solve? +- Is this something specific to their team, or would it be useful to a broader + audience across the organization? +- How do they plan to keep it maintained over time? + +These conversations give you the context you need to point them toward the right +starting template, flag any overlap with existing plugins, and think about where +it fits. + +## Registering plugins in your catalog + +Once a team has built a plugin and it is ready for wider use, they should register it in the Software Catalog. This makes the plugin discoverable, gives +it a clear owner, and surfaces any dependencies that other teams need to be +aware of. + +### Fill out catalog-info.yaml completely + +When the plugin is registered in the catalog, the contributing team should make +sure their `catalog-info.yaml` is complete. At a minimum this means listing +themselves as the owner and documenting any dependencies on backend APIs, +external services, or other Backstage plugins. This gives other teams a clear +point of contact for questions or feedback, and an accurate picture of what the +plugin depends on. + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: my-plugin + description: A short description of what this plugin does. +spec: + type: plugin + lifecycle: production + owner: team-name + dependsOn: + - component:my-backend-api +``` diff --git a/docs/golden-path/adoption/008-full-catalog.md b/docs/golden-path/adoption/008-full-catalog.md index 1725bf6dd2..aa3fae41be 100644 --- a/docs/golden-path/adoption/008-full-catalog.md +++ b/docs/golden-path/adoption/008-full-catalog.md @@ -2,6 +2,7 @@ id: full-catalog sidebar_label: 008 - A Full Catalog title: Ensuring your catalog stays complete +description: Strategies for maintaining a complete and up-to-date software catalog --- Along your Backstage journey (and any workflow migration journey), you will hit a point where incremental adoption is no longer easy. The new developers are no longer flowing into your tool like they once did. More and more projects are not being listed in your catalog. Something has to change. diff --git a/docs/golden-path/create-app/customize-theme--old.md b/docs/golden-path/create-app/customize-theme--old.md new file mode 100644 index 0000000000..3bae103379 --- /dev/null +++ b/docs/golden-path/create-app/customize-theme--old.md @@ -0,0 +1,619 @@ +--- +id: custom-theme--old +title: 005 - Customize your App's theme (Old Frontend System) +description: Documentation on customizing the look and feel of your Backstage app. +--- + +::::info +This documentation is for Backstage apps that still use the old frontend +system. If your app uses the new frontend system, read the +[current guide](./customize-theme.md) instead. +:::: + +Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes. + +## Creating a Custom Theme + +The easiest way to create a new theme is to use the `createUnifiedTheme` function exported by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You can use it to override some basic parameters of the default theme such as the color palette and font. + +For example, you can create a new theme based on the default light theme like this: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', +}); +``` + +:::note Note + +we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized. + +::: + +You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the +[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done. + +## Using your Custom Theme + +To add a custom theme to your Backstage app, you pass it as configuration to `createApp`. + +For example, adding the theme that we created in the previous section can be done like this: + +```tsx title="packages/app/src/App.tsx" +import { createApp } from '@backstage/app-defaults'; +import { ThemeProvider } from '@material-ui/core/styles'; +import CssBaseline from '@material-ui/core/CssBaseline'; +import LightIcon from '@material-ui/icons/WbSunny'; +import { UnifiedThemeProvider} from '@backstage/theme'; +import { myTheme } from './themes/myTheme'; + +const app = createApp({ + apis: ..., + plugins: ..., + themes: [{ + id: 'my-theme', + title: 'My Custom Theme', + variant: 'light', + icon: , + Provider: ({ children }) => ( + + ), + }] +}) +``` + +Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). + +## Example of a custom theme + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + genPageTheme, + palettes, + shapes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: { + ...palettes.light, + primary: { + main: '#343b58', + }, + secondary: { + main: '#565a6e', + }, + error: { + main: '#8c4351', + }, + warning: { + main: '#8f5e15', + }, + info: { + main: '#34548a', + }, + success: { + main: '#485e30', + }, + background: { + default: '#d5d6db', + paper: '#d5d6db', + }, + banner: { + info: '#34548a', + error: '#8c4351', + text: '#343b58', + link: '#565a6e', + }, + errorBackground: '#8c4351', + warningBackground: '#8f5e15', + infoBackground: '#343b58', + navigation: { + background: '#343b58', + indicator: '#8f5e15', + color: '#d5d6db', + selectedColor: '#ffffff', + }, + }, + }), + defaultPageTheme: 'home', + fontFamily: 'Comic Sans MS', + /* below drives the header colors */ + pageTheme: { + home: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + documentation: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave2, + }), + tool: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.round }), + service: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + website: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + library: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + other: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + app: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + apis: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + }, +}); +``` + +For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io). + +## Custom Typography + +When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + htmlFontSize: 16, + fontFamily: 'Arial, sans-serif', + h1: { + fontSize: 54, + fontWeight: 700, + marginBottom: 10, + }, + h2: { + fontSize: 40, + fontWeight: 700, + marginBottom: 8, + }, + h3: { + fontSize: 32, + fontWeight: 700, + marginBottom: 6, + }, + h4: { + fontWeight: 700, + fontSize: 28, + marginBottom: 6, + }, + h5: { + fontWeight: 700, + fontSize: 24, + marginBottom: 4, + }, + h6: { + fontWeight: 700, + fontSize: 20, + marginBottom: 2, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + defaultTypography, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + ...defaultTypography, + htmlFontSize: 16, + fontFamily: 'Roboto, sans-serif', + h1: { + fontSize: 72, + fontWeight: 700, + marginBottom: 10, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +## Custom Fonts + +To add custom fonts, you first need to store the font so that it can be imported. We suggest creating the `assets/fonts` directory in your front-end application `src` folder. + +You can then declare the font style following the `@font-face` syntax from [Material UI Typography](https://mui.com/material-ui/customization/typography/). + +After that you can then utilize the `styleOverrides` of `MuiCssBaseline` under components to add a font to the `@font-face` array. + +```ts title="packages/app/src/theme/myTheme.ts" +import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; + +const myCustomFont = { + fontFamily: 'My-Custom-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Custom-Font'), + url(${MyCustomFont}) format('woff2'), + `, +}; + +export const myTheme = createUnifiedTheme({ + fontFamily: 'My-Custom-Font', + palette: palettes.light, + components: { + MuiCssBaseline: { + styleOverrides: { + '@font-face': [myCustomFont], + }, + }, + }, +}); +``` + +If you want to utilize different or multiple fonts, then you can set the top level `fontFamily` to what you want for your body, and then override `fontFamily` in `typography` to control fonts for various headings. + +```ts title="packages/app/src/theme/myTheme.ts" +import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; +import myAwesomeFont from '../assets/fonts/My-Awesome-Font.woff2'; + +const myCustomFont = { + fontFamily: 'My-Custom-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Custom-Font'), + url(${MyCustomFont}) format('woff2'), + `, +}; + +const myAwesomeFont = { + fontFamily: 'My-Awesome-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Awesome-Font'), + url(${myAwesomeFont}) format('woff2'), + `, +}; + +export const myTheme = createUnifiedTheme({ + fontFamily: 'My-Custom-Font', + components: { + MuiCssBaseline: { + styleOverrides: { + '@font-face': [myCustomFont, myAwesomeFont], + }, + }, + }, + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + ...defaultTypography, + htmlFontSize: 16, + fontFamily: 'My-Custom-Font', + h1: { + fontSize: 72, + fontWeight: 700, + marginBottom: 10, + fontFamily: 'My-Awesome-Font', + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +## Overriding Backstage and Material UI components styles + +When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this: + +```tsx +const useStyles = makeStyles( + theme => ({ + header: { + padding: theme.spacing(3), + boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', + backgroundImage: theme.page.backgroundImage, + }, + }), + { name: 'BackstageHeader' }, +); +``` + +Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override. + +Here's how you would do that: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', + components: { + BackstageHeader: { + styleOverrides: { + header: ({ theme }) => ({ + width: 'auto', + margin: '20px', + boxShadow: 'none', + borderBottom: `4px solid ${theme.palette.primary.main}`, + }), + }, + }, + }, +}); +``` + +## Custom Logo + +In addition to a custom theme, you can also customize the logo displayed at the far top left of the site. + +In your frontend app, locate `src/components/Root/` folder. You'll find two components: + +- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened. +- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed. + +To replace the images, you can simply replace the relevant code in those components with raw SVG definitions. + +You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code: + +```tsx +import MyCustomLogoFull from './logo/my-company-logo.png'; + +const LogoFull = () => { + return ; +}; +``` + +## Icons + +So far you've seen how to create your own theme and add your own logo, in the following sections you'll be shown how to override the existing icons and how to add more icons + +### Custom Icons + +You can also customize the Project's _default_ icons. + +You can change the following [icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx). + +#### Requirements + +- Files in `.svg` format +- React components created for the icons + +#### Create React Component + +In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `CustomIcons.tsx` file. + +```tsx title="customIcons.tsx" +import { SvgIcon, SvgIconProps } from '@material-ui/core'; + +export const ExampleIcon = (props: SvgIconProps) => ( + + + +); +``` + +#### Using the custom icon + +Supply your custom icon in `packages/app/src/App.tsx` + +```tsx title="packages/app/src/App.tsx" +/* highlight-add-next-line */ +import { ExampleIcon } from './assets/customIcons' + + +const app = createApp({ + apis, + components: { + {/* ... */} + }, + themes: [ + {/* ... */} + ], + /* highlight-add-start */ + icons: { + github: ExampleIcon, + }, + /* highlight-add-end */ + bindRoutes({ bind }) { + {/* ... */} + } +}) +``` + +### Adding Icons + +You can add more icons, if the [default icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx) do not fit your needs, so that they can be used in other places like for Links in your entities. For this example we'll be using icons from[Material UI](https://v4.mui.com/components/material-icons/) and specifically the `AlarmIcon`. Here's how to do that: + +1. First you will want to open your `App.tsx` in `/packages/app/src` +2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';` +3. Next you want to add the icon like this to your `createApp`: + + ```tsx title="packages/app/src/App.tsx" + const app = createApp({ + apis: ..., + plugins: ..., + /* highlight-add-start */ + icons: { + alert: AlarmIcon, + }, + /* highlight-add-end */ + themes: ..., + components: ..., + }); + ``` + +4. Now we can reference `alert` for our icon in our entity links like this: + + ```yaml + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: artist-lookup + description: Artist Lookup + links: + - url: https://example.com/alert + title: Alerts + icon: alert + ``` + + And this is the result: + + ![Example Link with Alert icon](../../assets/getting-started/add-icons-links-example.png) + + Another way you can use these icons is from the `AppContext` like this: + + ```ts + import { useApp } from '@backstage/core-plugin-api'; + + const app = useApp(); + const alertIcon = app.getSystemIcon('alert'); + ``` + + You might want to use this method if you have an icon you want to use in several locations. + +:::note Note + +If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon` + +::: + +## Custom Sidebar + +As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar. + +### Sidebar Sub-menu + +For this example we'll show you how you can expand the sidebar with a sub-menu: + +1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives +2. Then we want to add the following import for `useApp`: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + import { useApp } from '@backstage/core-plugin-api'; + ``` + +3. Then update the `@backstage/core-components` import like this: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + import { + Sidebar, + sidebarConfig, + SidebarDivider, + SidebarGroup, + SidebarItem, + SidebarPage, + SidebarScrollWrapper, + SidebarSpace, + useSidebarOpenState, + Link, + /* highlight-add-start */ + GroupIcon, + SidebarSubmenu, + SidebarSubmenuItem, + /* highlight-add-end */ + } from '@backstage/core-components'; + ``` + +4. Finally replace `` with this: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + + + + + + + + + + + + + + ``` + +When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this: + +![Sidebar sub-menu example](../../assets/getting-started/sidebar-submenu-example.png) + +You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar) + +## Custom Homepage + +In addition to a custom theme, a custom logo, you can also customize the +homepage of your app. Read the full guide on the [next page](../../getting-started/homepage.md). + +## Migrating to Material UI v5 + +We now support Material UI v5 in Backstage. Check out our [migration guide](../../tutorials/migrate-to-mui5.md) to get started. diff --git a/docs/golden-path/create-app/customize-theme.md b/docs/golden-path/create-app/customize-theme.md index a79507de59..2c118b52ab 100644 --- a/docs/golden-path/create-app/customize-theme.md +++ b/docs/golden-path/create-app/customize-theme.md @@ -4,6 +4,13 @@ title: 005 - Customize your App's theme description: Documentation on customizing the look and feel of your Backstage app. --- +::::info +This documentation is written for the new frontend system, which is the default +in new Backstage apps. If your Backstage app still uses the old frontend system, +read the [old frontend system version of this guide](./customize-theme--old.md) +instead. +:::: + Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes. ## Creating a Custom Theme @@ -30,7 +37,7 @@ export const myTheme = createUnifiedTheme({ :::note Note -we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized. +We recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized. ::: @@ -39,34 +46,59 @@ You can also create a theme from scratch that matches the `BackstageTheme` type ## Using your Custom Theme -To add a custom theme to your Backstage app, you pass it as configuration to `createApp`. +In the new frontend system, themes are installed as extensions using `ThemeBlueprint` from `@backstage/plugin-app-react`. The theme extension is then bundled into a frontend module and passed to `createApp`. -For example, adding the theme that we created in the previous section can be done like this: +First, install the required packages: -```tsx title="packages/app/src/App.tsx" -import { createApp } from '@backstage/app-defaults'; -import { ThemeProvider } from '@material-ui/core/styles'; -import CssBaseline from '@material-ui/core/CssBaseline'; -import LightIcon from '@material-ui/icons/WbSunny'; -import { UnifiedThemeProvider} from '@backstage/theme'; -import { myTheme } from './themes/myTheme'; - -const app = createApp({ - apis: ..., - plugins: ..., - themes: [{ - id: 'my-theme', - title: 'My Custom Theme', - variant: 'light', - icon: , - Provider: ({ children }) => ( - - ), - }] -}) +```bash title="From your Backstage root directory" +yarn --cwd packages/app add @backstage/frontend-plugin-api @backstage/plugin-app-react ``` -Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). +Then create the theme extension and install it in your app: + +```tsx title="packages/app/src/App.tsx" +import { createApp } from '@backstage/frontend-defaults'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; +import { ThemeBlueprint } from '@backstage/plugin-app-react'; +import { UnifiedThemeProvider } from '@backstage/theme'; +import LightIcon from '@material-ui/icons/WbSunny'; +import { myTheme } from './theme/myTheme'; + +const myThemeExtension = ThemeBlueprint.make({ + name: 'my-theme', + params: { + theme: { + id: 'my-theme', + title: 'My Custom Theme', + variant: 'light', + icon: , + Provider: ({ children }) => ( + + ), + }, + }, +}); + +const app = createApp({ + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [myThemeExtension], + }), + ], +}); + +export default app.createRoot(); +``` + +Your custom theme extension will be added alongside the built-in light and dark themes. If you want your custom theme to _replace_ the default themes, you can disable them in `app-config.yaml`: + +```yaml title="app-config.yaml" +app: + extensions: + - theme:app/light: false + - theme:app/dark: false +``` ## Example of a custom theme @@ -396,117 +428,98 @@ const LogoFull = () => { ## Icons -So far you've seen how to create your own theme and add your own logo, in the following sections you'll be shown how to override the existing icons and how to add more icons +So far you've seen how to create your own theme and add your own logo. In the following sections you'll be shown how to override the existing icons and how to add more icons. ### Custom Icons -You can also customize the Project's _default_ icons. - -You can change the following [icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx). - -#### Requirements - -- Files in `.svg` format -- React components created for the icons - -#### Create React Component - -In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `CustomIcons.tsx` file. - -```tsx title="customIcons.tsx" -import { SvgIcon, SvgIconProps } from '@material-ui/core'; - -export const ExampleIcon = (props: SvgIconProps) => ( - - - -); -``` - -#### Using the custom icon - -Supply your custom icon in `packages/app/src/App.tsx` +You can customize the app's default icons using `IconBundleBlueprint` from `@backstage/plugin-app-react`. This creates an extension that overrides built-in icons. ```tsx title="packages/app/src/App.tsx" -/* highlight-add-next-line */ -import { ExampleIcon } from './assets/customIcons' +import { createApp } from '@backstage/frontend-defaults'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; +import { IconBundleBlueprint } from '@backstage/plugin-app-react'; +import { ExampleIcon } from './assets/customIcons'; +const customIconBundle = IconBundleBlueprint.make({ + name: 'custom-icons', + params: { + icons: { + github: ExampleIcon, + }, + }, +}); const app = createApp({ - apis, - components: { - {/* ... */} - }, - themes: [ - {/* ... */} + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [customIconBundle], + }), ], - /* highlight-add-start */ - icons: { - github: ExampleIcon, - }, - /* highlight-add-end */ - bindRoutes({ bind }) { - {/* ... */} - } -}) +}); + +export default app.createRoot(); ``` ### Adding Icons -You can add more icons, if the [default icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx) do not fit your needs, so that they can be used in other places like for Links in your entities. For this example we'll be using icons from[Material UI](https://v4.mui.com/components/material-icons/) and specifically the `AlarmIcon`. Here's how to do that: +You can register additional icons so that they can be used in other places like entity links. For example, to add an `alert` icon: -1. First you will want to open your `App.tsx` in `/packages/app/src` -2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';` -3. Next you want to add the icon like this to your `createApp`: +```tsx title="packages/app/src/App.tsx" +import { createApp } from '@backstage/frontend-defaults'; +import { createFrontendModule } from '@backstage/frontend-plugin-api'; +import AlarmIcon from '@material-ui/icons/Alarm'; +import { IconBundleBlueprint } from '@backstage/plugin-app-react'; - ```tsx title="packages/app/src/App.tsx" - const app = createApp({ - apis: ..., - plugins: ..., - /* highlight-add-start */ - icons: { - alert: AlarmIcon, - }, - /* highlight-add-end */ - themes: ..., - components: ..., - }); - ``` +const extraIcons = IconBundleBlueprint.make({ + name: 'extra-icons', + params: { + icons: { + alert: AlarmIcon, + }, + }, +}); -4. Now we can reference `alert` for our icon in our entity links like this: +const app = createApp({ + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [extraIcons], + }), + ], +}); - ```yaml - apiVersion: backstage.io/v1alpha1 - kind: Component - metadata: - name: artist-lookup - description: Artist Lookup - links: - - url: https://example.com/alert - title: Alerts - icon: alert - ``` +export default app.createRoot(); +``` - And this is the result: +You can then reference `alert` for your icon in entity links like this: - ![Example Link with Alert icon](../../assets/getting-started/add-icons-links-example.png) +```yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: artist-lookup + description: Artist Lookup + links: + - url: https://example.com/alert + title: Alerts + icon: alert +``` - Another way you can use these icons is from the `AppContext` like this: +And this is the result: - ```ts - import { useApp } from '@backstage/core-plugin-api'; +![Example Link with Alert icon](../../assets/getting-started/add-icons-links-example.png) - const app = useApp(); - const alertIcon = app.getSystemIcon('alert'); - ``` +Another way you can use these icons is from the `AppContext` like this: - You might want to use this method if you have an icon you want to use in several locations. +```ts +import { useApp } from '@backstage/core-plugin-api'; + +const app = useApp(); +const alertIcon = app.getSystemIcon('alert'); +``` + +You might want to use this method if you have an icon you want to use in several locations. :::note Note @@ -516,92 +529,7 @@ If the icon is not available as one of the default icons or one you've added the ## Custom Sidebar -As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar. - -### Sidebar Sub-menu - -For this example we'll show you how you can expand the sidebar with a sub-menu: - -1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives -2. Then we want to add the following import for `useApp`: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - import { useApp } from '@backstage/core-plugin-api'; - ``` - -3. Then update the `@backstage/core-components` import like this: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - import { - Sidebar, - sidebarConfig, - SidebarDivider, - SidebarGroup, - SidebarItem, - SidebarPage, - SidebarScrollWrapper, - SidebarSpace, - useSidebarOpenState, - Link, - /* highlight-add-start */ - GroupIcon, - SidebarSubmenu, - SidebarSubmenuItem, - /* highlight-add-end */ - } from '@backstage/core-components'; - ``` - -4. Finally replace `` with this: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - - - - - - - - - - - - - - ``` - -When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this: - -![Sidebar sub-menu example](../../assets/getting-started/sidebar-submenu-example.png) - -You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar) +In the new frontend system, the sidebar is managed by the built-in `app/nav` extension. You can customize it by creating a `NavContentBlueprint` extension. See the [sidebar customization](../../frontend-system/building-apps/08-migrating.md#app-root-sidebar) documentation for detailed instructions on creating a custom sidebar layout with sub-menus and custom grouping. ## Custom Homepage diff --git a/docs/golden-path/create-app/index.md b/docs/golden-path/create-app/index.md index ebd736594d..caa26c2a3a 100644 --- a/docs/golden-path/create-app/index.md +++ b/docs/golden-path/create-app/index.md @@ -1,6 +1,7 @@ --- id: index title: 'Creating your first Backstage app' +description: A guided walkthrough for creating and setting up your first Backstage application --- ### Prerequisites diff --git a/docs/golden-path/create-app/installing-plugins.md b/docs/golden-path/create-app/installing-plugins.md index ab1e1a68c5..f5f5931220 100644 --- a/docs/golden-path/create-app/installing-plugins.md +++ b/docs/golden-path/create-app/installing-plugins.md @@ -2,6 +2,7 @@ id: installing-plugins sidebar_label: 003 - Installing plugins title: 003 - Installing plugins +description: How to find and install plugins in your Backstage app --- Now that you have a working Backstage app, let's walk through the most valuable part of the Backstage ecosystem - plugins! diff --git a/docs/golden-path/create-app/keeping-backstage-updated.md b/docs/golden-path/create-app/keeping-backstage-updated.md index de7d99b2b8..b0561e5304 100644 --- a/docs/golden-path/create-app/keeping-backstage-updated.md +++ b/docs/golden-path/create-app/keeping-backstage-updated.md @@ -2,6 +2,7 @@ id: keeping-backstage-updated sidebar_label: 006 - Keep Backstage updated title: 006 - Keeping Backstage up to date +description: How to keep your Backstage instance up to date with the latest releases --- Audience: Developers and Admins @@ -141,12 +142,14 @@ down the number of duplicate packages. ## Proxy -The Backstage CLI uses [global-agent](https://www.npmjs.com/package/global-agent) and `undici` to configure HTTP/HTTPS proxy settings using environment variables. This allows you to route the CLI’s network traffic through a proxy server, which can be useful in environments with restricted internet access. +On Node.js 22.21.0+, the Backstage CLI respects the standard `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables when `NODE_USE_ENV_PROXY=1` is set. See the [corporate proxy guide](../../tutorials/corporate-proxy.md) for full details. + +On older Node.js versions, the CLI falls back to [global-agent](https://www.npmjs.com/package/global-agent) and `undici` for proxy support, which require their own environment variables (prefixed with `GLOBAL_AGENT_`). This allows you to route the CLI’s network traffic through a proxy server, which can be useful in environments with restricted internet access. Additionally, `yarn` needs a proxy too (sometimes), when in environments with restricted internet access. It uses different settings than the other modules. If you decide to use the backstage yarn plugin [mentioned above](#plugin), you will need to set additional proxy values. If you will always need proxy settings in all environments and situations, you can add `httpProxy` and `httpsProxy` values to [the yarnrc.yml file](https://yarnpkg.com/configuration/yarnrc). If some environments need it (say a developer workstation) but other environments do not (perhaps a CI build server running on AWS), then you may not want to update the yarnrc.yml file but just set environment variables `YARN_HTTP_PROXY` and `YARN_HTTPS_PROXY` in the environments/situations where you need to proxy. -**If you plan to use the backstage yarn plugin, you will need these extra yarn proxy settings to both install the plugin and run the `versions:bump` command**. If you do not plan to use the backstage yarn plugin, it seems like the global agent proxy settings alone are sufficient. +**If you plan to use the backstage yarn plugin, you will need these extra yarn proxy settings to both install the plugin and run the `versions:bump` command**. If you do not plan to use the backstage yarn plugin, it seems like the proxy settings alone are sufficient. ### Example Configuration @@ -154,9 +157,10 @@ If you will always need proxy settings in all environments and situations, you c export HTTP_PROXY=http://proxy.company.com:8080 export HTTPS_PROXY=https://secure-proxy.company.com:8080 export NO_PROXY=localhost,internal.company.com -export GLOBAL_AGENT_HTTP_PROXY=${HTTP_PROXY} -export GLOBAL_AGENT_HTTPS_PROXY=${HTTPS_PROXY} -export GLOBAL_AGENT_NO_PROXY=${NO_PROXY} +export NODE_USE_ENV_PROXY=1 # Node.js 22.21.0+ +export GLOBAL_AGENT_HTTP_PROXY=${HTTP_PROXY} # Node.js < 22.21.0 +export GLOBAL_AGENT_HTTPS_PROXY=${HTTPS_PROXY} # Node.js < 22.21.0 +export GLOBAL_AGENT_NO_PROXY=${NO_PROXY} # Node.js < 22.21.0 export YARN_HTTP_PROXY=${HTTP_PROXY} # optional export YARN_HTTPS_PROXY=${HTTPS_PROXY} # optional ``` diff --git a/docs/golden-path/create-app/local-development.md b/docs/golden-path/create-app/local-development.md index 2c81c2c643..ff23a7c652 100644 --- a/docs/golden-path/create-app/local-development.md +++ b/docs/golden-path/create-app/local-development.md @@ -1,6 +1,7 @@ --- id: local-development title: 002 - Local development +description: How to run and develop your Backstage app locally --- Your Backstage app is fully installed and ready to be run! Now that the installation is complete, you can go to the application directory and start the app using the `yarn start` command. The `yarn start` command will run both the frontend and backend as separate processes (named `[0]` and `[1]`) in the same window. diff --git a/docs/golden-path/create-app/npx-create-app.md b/docs/golden-path/create-app/npx-create-app.md index 8ee016f41f..d33c037424 100644 --- a/docs/golden-path/create-app/npx-create-app.md +++ b/docs/golden-path/create-app/npx-create-app.md @@ -1,6 +1,7 @@ --- id: npx-create-app title: '001 - Scaffolding' +description: How to scaffold a new Backstage app using create-app --- Audience: Developers and Admins diff --git a/docs/golden-path/plugins/backend/001-first-steps.md b/docs/golden-path/plugins/backend/001-first-steps.md index 8a0defe183..ed2c8e98ed 100644 --- a/docs/golden-path/plugins/backend/001-first-steps.md +++ b/docs/golden-path/plugins/backend/001-first-steps.md @@ -2,6 +2,7 @@ id: first-steps sidebar_label: 001 - Scaffolding the plugin title: How to scaffold a new plugin? +description: How to scaffold a new Backstage backend plugin using the CLI --- # Scaffolding a new plugin diff --git a/docs/golden-path/plugins/backend/002-poking-around.md b/docs/golden-path/plugins/backend/002-poking-around.md index 596de01b4b..e7636d3749 100644 --- a/docs/golden-path/plugins/backend/002-poking-around.md +++ b/docs/golden-path/plugins/backend/002-poking-around.md @@ -2,6 +2,7 @@ id: poking-around sidebar_label: 002 - Poking around title: 002 - Poking around +description: Exploring the default backend plugin structure and functionality --- ## Default plugin functionality diff --git a/docs/golden-path/plugins/backend/003-persistence.md b/docs/golden-path/plugins/backend/003-persistence.md index ba00b2f417..60d275d7ec 100644 --- a/docs/golden-path/plugins/backend/003-persistence.md +++ b/docs/golden-path/plugins/backend/003-persistence.md @@ -2,6 +2,7 @@ id: persistence sidebar_label: 003 - Persisting your TODOs title: 003 - Persisting your TODOs +description: How to add database persistence to your backend plugin --- ## Saving Plugin State Indefinitely diff --git a/docs/golden-path/plugins/backend/004-source-tracked.md b/docs/golden-path/plugins/backend/004-source-tracked.md index 074cc85cf1..54013ccead 100644 --- a/docs/golden-path/plugins/backend/004-source-tracked.md +++ b/docs/golden-path/plugins/backend/004-source-tracked.md @@ -2,6 +2,7 @@ id: source-tracked sidebar_label: 004 - Integrating with SCMs title: 004 - Git-tracked TODOs +description: How to ingest TODOs from source code repositories into your plugin --- Problem: You have TODOs in your source code that you want to ingest with your plugin. diff --git a/docs/golden-path/plugins/backend/005-testing.md b/docs/golden-path/plugins/backend/005-testing.md index 9643e8a487..075b81f1fc 100644 --- a/docs/golden-path/plugins/backend/005-testing.md +++ b/docs/golden-path/plugins/backend/005-testing.md @@ -2,6 +2,7 @@ id: testing sidebar_label: 005 - Unit testing your plugin title: 005 - Testing +description: How to write unit tests for your Backstage backend plugin --- ## Testing is important diff --git a/docs/golden-path/plugins/frontend/001-first-steps.md b/docs/golden-path/plugins/frontend/001-first-steps.md index d6c21ed053..313a990b62 100644 --- a/docs/golden-path/plugins/frontend/001-first-steps.md +++ b/docs/golden-path/plugins/frontend/001-first-steps.md @@ -2,6 +2,7 @@ id: first-steps sidebar_label: 001 - Scaffolding the plugin title: How to scaffold a new plugin? +description: How to scaffold a new Backstage frontend plugin using the CLI --- Running `yarn new` -> `frontend-plugin`. diff --git a/docs/golden-path/plugins/frontend/002-poking-around.md b/docs/golden-path/plugins/frontend/002-poking-around.md index e85ea235f3..33223019d0 100644 --- a/docs/golden-path/plugins/frontend/002-poking-around.md +++ b/docs/golden-path/plugins/frontend/002-poking-around.md @@ -2,6 +2,7 @@ id: poking-around sidebar_label: 002 - Poking around title: 002 - Poking around +description: Exploring the default frontend plugin structure and components --- Our frontend TODO plugin is a bit more simplistic than the backend one. We need to implement a new UI to replace the example components we have. diff --git a/docs/golden-path/plugins/frontend/003-dynamic-config.md b/docs/golden-path/plugins/frontend/003-dynamic-config.md index 8eecd72c2f..8f3b7ff1ef 100644 --- a/docs/golden-path/plugins/frontend/003-dynamic-config.md +++ b/docs/golden-path/plugins/frontend/003-dynamic-config.md @@ -2,6 +2,7 @@ id: dynamic-config sidebar_label: 003 - Dynamic Config title: 003 - Dynamic Config +description: How to use dynamic configuration to control frontend plugin components --- Your plugin should have been generated by default for the New Frontend System which is config-first. That means you can easily control your frontend components through your `app-config.yaml`. diff --git a/docs/golden-path/plugins/frontend/004-http-client.md b/docs/golden-path/plugins/frontend/004-http-client.md index b6190f0f5f..00678df1d6 100644 --- a/docs/golden-path/plugins/frontend/004-http-client.md +++ b/docs/golden-path/plugins/frontend/004-http-client.md @@ -2,6 +2,7 @@ id: http-client sidebar_label: 004 - HTTP Client title: 004 - HTTP Client +description: How to build an HTTP client for your frontend plugin to fetch backend data --- Now, let's really make our page dynamic. We'll start by writing an HTTP client by hand. diff --git a/docs/golden-path/plugins/frontend/005-testing.md b/docs/golden-path/plugins/frontend/005-testing.md index fe385d7169..6a672998aa 100644 --- a/docs/golden-path/plugins/frontend/005-testing.md +++ b/docs/golden-path/plugins/frontend/005-testing.md @@ -2,6 +2,7 @@ id: testing sidebar_label: 005 - Testing title: 005 - Testing +description: How to write tests for your Backstage frontend plugin components --- Everyone's favorite part! Let's make sure our components continue to work even when we're not able to validate the changes. diff --git a/docs/golden-path/plugins/index.md b/docs/golden-path/plugins/index.md index 616c2c0c36..43ffe612e8 100644 --- a/docs/golden-path/plugins/index.md +++ b/docs/golden-path/plugins/index.md @@ -2,6 +2,7 @@ id: index sidebar_label: Backstage Plugins! title: How to create plugins with Backstage +description: A guided walkthrough for building frontend and backend plugins in Backstage --- ### Prerequisites diff --git a/docs/golden-path/plugins/integrations/001-catalog.md b/docs/golden-path/plugins/integrations/001-catalog.md index f5ed04116e..4825a08ca8 100644 --- a/docs/golden-path/plugins/integrations/001-catalog.md +++ b/docs/golden-path/plugins/integrations/001-catalog.md @@ -2,6 +2,7 @@ id: catalog sidebar_label: 001 - Catalog title: Integrating with Catalog +description: How to integrate your plugin with the Backstage Software Catalog --- ## Software Catalog diff --git a/docs/golden-path/plugins/integrations/002-search.md b/docs/golden-path/plugins/integrations/002-search.md index b0ef762f27..b3d23de4d9 100644 --- a/docs/golden-path/plugins/integrations/002-search.md +++ b/docs/golden-path/plugins/integrations/002-search.md @@ -2,6 +2,7 @@ id: search sidebar_label: 002 - Search title: Integrating with Search +description: How to integrate your plugin with Backstage Search --- ## Search diff --git a/docs/golden-path/plugins/integrations/003-permissions.md b/docs/golden-path/plugins/integrations/003-permissions.md index 167d40d47f..3cbba161fb 100644 --- a/docs/golden-path/plugins/integrations/003-permissions.md +++ b/docs/golden-path/plugins/integrations/003-permissions.md @@ -2,22 +2,309 @@ id: permissions sidebar_label: 003 - Permissions title: Integrating with the Permission framework +description: How to integrate your plugin with the Backstage Permission framework --- ## Permissions ### What is the Permissions framework? - +The [Backstage permissions framework](../../../permissions/overview.md) gives you a structured way to control who can do what inside your plugin. Rather than scattering authorization logic across your route handlers, you define permissions declaratively and let a central policy decide whether to allow or deny each action. + +There are two kinds of permissions: + +_Basic permissions_ apply to actions that don't relate to a specific resource. Creating a todo is a good example: the action either is or isn't allowed, regardless of which todo you're creating. The policy returns a definitive ALLOW or DENY. + +_Resource permissions_ apply to actions on a specific resource. Reading a particular todo is a good example: whether you're allowed might depend on whether you created it. In addition to the basic ALLOW or DENY, the policy can return a CONDITIONAL decision. CONDITIONAL decisions are required to be evaluated against a specific resource and will produce a per-resource ALLOW or DENY. + +The framework sits between your route handlers and your business logic. Your handler asks "is this allowed?", the framework consults the active policy, and your handler either proceeds or throws a `NotAllowedError`. ### Common integration points - +Most plugins integrate at two levels: + +**The backend plugin** is where you define your permissions, register them with the framework, and enforce them inside your route handlers. + +**A common package** (for example, `@internal/plugin-todo-common`) is where you export the permission definitions so they can be referenced from anywhere: your backend, your frontend, and any policy that an adopter writes. + +The split matters because policy authors need to reference your permission objects when writing their own policies. If those definitions live inside your backend package, you're forcing a dependency on backend code where it doesn't belong. ## Creating private TODOs - +The goal here is to ensure users can only read their own todos. This is a resource permission because the decision depends on a property of the resource itself. + +### Define the permission + +In your common package, define a resource permission for reading todos: + +```ts +// plugins/todo-common/src/permissions.ts +import { createPermission } from '@backstage/plugin-permission-common'; + +export const TODO_RESOURCE_TYPE = 'todo-item'; + +export const todoReadPermission = createPermission({ + name: 'todo.read', + attributes: { action: 'read' }, + resourceType: TODO_RESOURCE_TYPE, +}); + +export const todoPermissions = [todoReadPermission]; +``` + +The `resourceType` field ties this permission to a specific kind of resource. Exporting the string as a named constant (`TODO_RESOURCE_TYPE`) means you can import it in your backend rules rather than repeating the raw string, which prevents subtle mismatches. + +### Define a permission rule + +Rules are the conditions that the framework evaluates against a resource. Each rule has two parts: `apply`, which checks an in-memory resource, and `toQuery`, which converts the condition to a filter your database can use. + +```ts +// plugins/todo-backend/src/service/rules.ts +import { + createPermissionResourceRef, + createPermissionRule, +} from '@backstage/plugin-permission-node'; +import { TODO_RESOURCE_TYPE } from '@internal/plugin-todo-common'; +import { z } from 'zod/v3'; +import type { TodoItem } from './services/TodoListService'; + +export const todoResourceRef = createPermissionResourceRef< + TodoItem, + { createdBy: string } +>().with({ + pluginId: 'todo', + resourceType: TODO_RESOURCE_TYPE, +}); + +export const isCreator = createPermissionRule({ + name: 'IS_CREATOR', + description: 'Allow if the todo was created by the current user', + resourceRef: todoResourceRef, + paramsSchema: z.object({ + userRef: z.string().describe('The entity ref of the user'), + }), + apply(todo, { userRef }) { + return todo.createdBy === userRef; + }, + toQuery({ userRef }) { + return { property: 'createdBy', values: [userRef] }; + }, +}); + +export const rules = { isCreator }; +``` + +The `apply` and `toQuery` functions must always have logically identical outcomes. If they diverge, users will see inconsistent results depending on whether the framework checks the database or a loaded resource. + +### Register the resource type + +In your plugin setup, register the resource type alongside its rules: + +```ts +// plugins/todo-backend/src/plugin.ts +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { todoReadPermission } from '@internal/plugin-todo-common'; +import { todoResourceRef, rules } from './service/rules'; +import { todoListServiceRef } from './services/TodoListService'; + +export const todoPlugin = createBackendPlugin({ + pluginId: 'todo', + register(env) { + env.registerInit({ + deps: { + httpRouter: coreServices.httpRouter, + httpAuth: coreServices.httpAuth, + permissions: coreServices.permissions, + permissionsRegistry: coreServices.permissionsRegistry, + todoList: todoListServiceRef, + }, + async init({ + httpRouter, + httpAuth, + permissions, + permissionsRegistry, + todoList, + }) { + permissionsRegistry.addResourceType({ + resourceRef: todoResourceRef, + permissions: [todoReadPermission], + rules: Object.values(rules), + getResources: async resourceRefs => { + return Promise.all( + resourceRefs.map(ref => + todoList.getTodo({ id: ref }).catch(() => undefined), + ), + ); + }, + }); + + const router = await createRouter({ httpAuth, permissions, todoList }); + httpRouter.use(router); + }, + }); + }, +}); +``` + +`getResources` is called by the framework when it needs to load a resource to evaluate a conditional decision. Return `undefined` for any ref that doesn't exist. + +### Enforce the permission in a route handler + +In your route handler, use `authorizeConditional` for resource permissions. Unlike `authorize`, this can return a conditional decision that you apply as a filter rather than a hard stop: + +```ts +// plugins/todo-backend/src/service/router.ts +import { + HttpAuthService, + PermissionsService, +} from '@backstage/backend-plugin-api'; +import { NotAllowedError } from '@backstage/errors'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { todoReadPermission } from '@internal/plugin-todo-common'; +import { todoListServiceRef } from './services/TodoListService'; + +export async function createRouter({ + httpAuth, + permissions, + todoList, +}: { + httpAuth: HttpAuthService; + permissions: PermissionsService; + todoList: typeof todoListServiceRef.T; +}): Promise { + const router = Router(); + router.use(express.json()); + + router.get('/todos', async (req, res) => { + const credentials = await httpAuth.credentials(req, { allow: ['user'] }); + + const decision = ( + await permissions.authorizeConditional( + [{ permission: todoReadPermission }], + { credentials }, + ) + )[0]; + + if (decision.result === AuthorizeResult.DENY) { + throw new NotAllowedError(); + } + + // If CONDITIONAL, pass the conditions to your data layer as a filter. + // If ALLOW, pass no filter (return everything). + const result = await todoList.listTodos( + decision.result === AuthorizeResult.CONDITIONAL + ? decision.conditions + : undefined, + ); + + res.json(result); + }); + + // ... other routes + return router; +} +``` + +The conditional path means users only see the data the policy allows, without the handler needing to know what the policy actually is. The policy is the adopter's concern. + +### Export condition helpers for policy authors + +Adopters who write their own permission policy need to be able to express conditions using your rules. Export helpers from your backend package: + +```ts +// plugins/todo-backend/src/conditionExports.ts +import { createConditionExports } from '@backstage/plugin-permission-node'; +import { todoResourceRef, rules } from './service/rules'; + +const { conditions, createConditionalDecision } = createConditionExports({ + resourceRef: todoResourceRef, + rules, +}); + +export const todoConditions = conditions; +export const createTodoConditionalDecision = createConditionalDecision; +``` + +Re-export these from your package's `src/index.ts`. An adopter can then write a policy like this: + +```ts +import { + todoConditions, + createTodoConditionalDecision, +} from '@internal/plugin-todo-backend'; +import { todoReadPermission } from '@internal/plugin-todo-common'; + +class MyPolicy implements PermissionPolicy { + async handle(request: PolicyQuery, user?: PolicyQueryUser) { + if (isPermission(request.permission, todoReadPermission)) { + return createTodoConditionalDecision( + request.permission, + todoConditions.isCreator({ userRef: user?.info.userEntityRef ?? '' }), + ); + } + return { result: AuthorizeResult.ALLOW }; + } +} +``` + +This gives adopters a typed, discoverable API for customizing your plugin's access control without having to understand the internals of your data layer. ## Restricting who can create TODOs - +Restricting who can create todos is simpler. There is no resource involved yet, so this is a basic permission. The policy returns a definitive ALLOW or DENY. + +### Define the create permission + +Add a create permission to your common package: + +```ts +// plugins/todo-common/src/permissions.ts +export const todoCreatePermission = createPermission({ + name: 'todo.create', + attributes: { action: 'create' }, +}); + +export const todoPermissions = [todoReadPermission, todoCreatePermission]; +``` + +### Register the permission with the framework + +In your plugin setup, register basic permissions with `addPermissions` rather than `addResourceType`: + +```ts +permissionsRegistry.addPermissions([todoCreatePermission]); +``` + +### Enforce the permission in the create handler + +For basic permissions, use `authorize` instead of `authorizeConditional`. The result is always definitive: + +```ts +router.post('/todos', async (req, res) => { + const parsed = todoSchema.safeParse(req.body); + if (!parsed.success) { + throw new InputError(parsed.error.toString()); + } + + const credentials = await httpAuth.credentials(req, { allow: ['user'] }); + + const decision = ( + await permissions.authorize([{ permission: todoCreatePermission }], { + credentials, + }) + )[0]; + + if (decision.result !== AuthorizeResult.ALLOW) { + throw new NotAllowedError('You are not permitted to create todos'); + } + + const result = await todoList.createTodo(parsed.data, { credentials }); + + res.status(201).json(result); +}); +``` + +An adopter's policy can now control this permission however they like: restrict it to a specific group, require a certain annotation on the user entity, or leave it open to everyone. Your plugin does not need to know. diff --git a/docs/golden-path/plugins/integrations/004-notifications.md b/docs/golden-path/plugins/integrations/004-notifications.md index 23c44b4721..d28f08da49 100644 --- a/docs/golden-path/plugins/integrations/004-notifications.md +++ b/docs/golden-path/plugins/integrations/004-notifications.md @@ -2,6 +2,7 @@ id: notifications sidebar_label: 004 - Notifications title: Integrating with Notifications +description: How to integrate your plugin with Backstage Notifications --- ## Notifications diff --git a/docs/golden-path/plugins/integrations/__meta__.md b/docs/golden-path/plugins/integrations/__meta__.md index 2d8df8136e..de9c90befc 100644 --- a/docs/golden-path/plugins/integrations/__meta__.md +++ b/docs/golden-path/plugins/integrations/__meta__.md @@ -1,19 +1,19 @@ -## Integrations +# Integrations Now that our plugin is ready for prime time, let's see how we can really leverage the rest of the Backstage ecosystem. Backstage provides a set of core features out of the box, namely, the Software Catalog, Search, Permissions, and Notifications. -### Catalog +## Catalog We want to show our todos as separate Catalog entities. How can we make this happen? -### Search +## Search We want to make our todos searchable. -### Permissions +## Permissions We only want users to be able to find their own todos. -### Notifications +## Notifications We want to set an alarm time for todos that sends a notification when the time is met. diff --git a/docs/golden-path/plugins/sustainable-plugin-development.md b/docs/golden-path/plugins/sustainable-plugin-development.md index 82d529d6e1..d19d5b7ac8 100644 --- a/docs/golden-path/plugins/sustainable-plugin-development.md +++ b/docs/golden-path/plugins/sustainable-plugin-development.md @@ -2,28 +2,59 @@ id: sustainable-plugin-development sidebar_label: Sustainable plugin development title: Sustainably developing plugins in Backstage +description: Best practices for maintaining and iterating on Backstage plugins long-term --- Plugins are not created in a vacuum, they generally solve a customer ask, be that - a business problem, like showing cloud spend -- a new integration, like showing data from an external vendor such as Pagerduty +- a new integration, like showing data from an external vendor such as PagerDuty - a developer pain point, like organizing information from disjoint or disorganized systems. To ensure that your plugin lives the test of time, you'll need to figure out how to keep it up-to-date, -### Finding your stakeholders +## Finding your stakeholders - +Your internal developer teams are your customers. They are the ones who will use your plugin day-to-day, and they are the best source of truth for whether it's solving the right problems. Before writing a single line of code, it's worth spending time talking to them. -### Iterating on your plugin +Start by identifying which teams are most affected by the problem you're trying to solve. If you're building a cloud spend plugin, talk to the teams who own cloud infrastructure. If you're consolidating on-call information, find the teams that own your incident response process. These are your primary stakeholders. -In many cases, your first version of a plugin will cut a few corners - this is a good sign, you're more focused on delivering a strong use case to continue development than over-indexing on your initial code. It may be temporary after all, if you don't get the response you're looking for! +When you meet with them, listen for: + +- **Pain points**: What manual steps are slowing them down? What information do they have to hunt for across multiple tools? +- **Frequency**: How often do they hit this problem? A daily frustration is worth more investment than a quarterly one. +- **Workarounds**: What are they doing today instead? Existing workarounds often reveal what the minimum viable solution needs to cover. + +Secondary stakeholders like platform teams, engineering managers, or team leads can give you a broader view of organizational needs and help you prioritize across teams. They can also act as champions who drive adoption once your plugin ships. + +Keep these conversations ongoing. A quick check-in after you ship an early version is often more valuable than a long requirements-gathering session upfront. Your stakeholders will give you much clearer feedback once they've seen something working. + +## Iterating on your plugin + +In many cases, your first version of a plugin will cut a few corners. This is a good sign; you're more focused on delivering a strong use case to continue development than over-indexing on your initial code. It may be temporary after all, if you don't get the response you're looking for! So, how do you decide when you should iterate on your plugin? - +The clearest signal is feedback from the teams using it. Go back to the stakeholders you identified earlier. Are they actually using the plugin? Are they hitting friction you didn't anticipate? Direct conversations and usage patterns will tell you far more than assumptions made during initial development. -### Ensuring the success of your plugin +Some common triggers for iteration: - +- **Stakeholder feedback reveals a gap**: A team is using your plugin but still switching to another tool for one specific thing. That gap is your next iteration. +- **Adoption is lower than expected**: If teams aren't using it, find out why before adding features. The problem is often discoverability, missing context, or a workflow mismatch rather than missing functionality. +- **The underlying data or service has changed**: External systems evolve. If your plugin surfaces data from another service, keep a line open with the team that owns it so you're not caught off guard. +- **Analytics surface unexpected patterns**: Backstage has built-in support for analytics events. If you've instrumented your plugin, usage data can reveal which parts of your plugin are heavily used, which are ignored, and where users drop off. A page with high traffic but short visit times might indicate users aren't finding what they need. + +Not every piece of feedback warrants an immediate change. Weigh requests against how broadly they apply; a request from one team may not justify the complexity it adds for everyone else. Your stakeholders are your best guide for prioritization here too. + +## Ensuring the success of your plugin + +A successful plugin is one that continues to be used, trusted, and improved over time. That doesn't happen by accident. It's the result of staying connected to the people who depend on it. + +The foundations are straightforward: + +- **Keep your stakeholder relationships active.** Don't treat the initial conversations as a one-time exercise. Check in regularly, especially after shipping new versions. The teams using your plugin are the fastest way to find out what's working and what isn't. +- **Let feedback drive your priorities.** It can be tempting to iterate on the parts of your plugin you find most interesting technically. Let usage patterns and stakeholder feedback anchor your roadmap instead. +- **Instrument your plugin.** Analytics give you signal between conversations. If a feature is being ignored, or a page has high drop-off, that's worth investigating before investing further in that direction. +- **Treat it like a product, not a project.** A plugin that ships and gets abandoned quickly loses the trust of its users. Even small, regular improvements signal that the plugin is maintained and worth relying on. + +The common thread across all of this is that your developers are your customers. Keeping that relationship healthy is what separates a plugin that becomes a critical part of your developer portal from one that quietly gets bypassed. diff --git a/docs/golden-path/plugins/why-build-plugins.md b/docs/golden-path/plugins/why-build-plugins.md index b0e1be0a98..36a74158c2 100644 --- a/docs/golden-path/plugins/why-build-plugins.md +++ b/docs/golden-path/plugins/why-build-plugins.md @@ -2,6 +2,7 @@ id: why-build-plugins sidebar_label: Why build plugins? title: Introduction to the Value and Impact of Plugins within Backstage +description: Understanding the benefits and impact of building plugins for Backstage --- Backstage plugins are essential components that enable the integration of various tools and services into a unified developer portal. Here’s a detailed look at why building plugins for Backstage can be highly beneficial: diff --git a/docs/integrations/azure-blobStorage/discovery.md b/docs/integrations/azure-blobStorage/discovery.md index f0953815c2..f0019a5c01 100644 --- a/docs/integrations/azure-blobStorage/discovery.md +++ b/docs/integrations/azure-blobStorage/discovery.md @@ -61,7 +61,7 @@ the Azure catalog plugin: yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure ``` -Then updated your backend by adding the following line: +Then update your backend by adding the following line: ```ts title="packages/backend/src/index.ts" backend.add(import('@backstage/plugin-catalog-backend')); diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md index 0eafc938a2..67d70c7f6d 100644 --- a/docs/integrations/azure/discovery.md +++ b/docs/integrations/azure/discovery.md @@ -97,7 +97,7 @@ the Azure catalog plugin: yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure ``` -Then updated your backend by adding the following line: +Then update your backend by adding the following line: ```ts title="packages/backend/src/index.ts" backend.add(import('@backstage/plugin-catalog-backend')); diff --git a/docs/integrations/azure/org.md b/docs/integrations/azure/org.md index 92f3f9c12a..7bd93f38b3 100644 --- a/docs/integrations/azure/org.md +++ b/docs/integrations/azure/org.md @@ -41,7 +41,7 @@ catalog: For large organizations, this plugin can take a long time, so be careful setting low frequency / timeouts and importing a large amount of users / groups for the first try. ::: -Finally, updated your backend by adding the following line: +Finally, update your backend by adding the following line: ```ts title="packages/backend/src/index.ts" backend.add(import('@backstage/plugin-catalog-backend')); diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 8adc81184a..22a843009f 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -40,7 +40,7 @@ catalog: timeout: PT15M ``` -Finally, updated your backend by adding the following line: +Finally, update your backend by adding the following line: ```ts title="packages/backend/src/index.ts" backend.add(import('@backstage/plugin-catalog-backend')); diff --git a/docs/integrations/okta/org.md b/docs/integrations/okta/org.md new file mode 100644 index 0000000000..63769e7c85 --- /dev/null +++ b/docs/integrations/okta/org.md @@ -0,0 +1,23 @@ +--- +id: org +title: Okta Organizational Data +sidebar_label: Org Data +description: Ingesting organizational data from Okta into Backstage +--- + +The Backstage catalog can be set up to ingest organizational data — users and +groups — directly from Okta. The result is a hierarchy of +[`User`](../../features/software-catalog/descriptor-format.md#kind-user) and +[`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind +entities that mirror your Okta organization. + +This integration is provided by the community-maintained +[`@roadiehq/catalog-backend-module-okta`](https://github.com/RoadieHQ/roadie-backstage-plugins/tree/main/plugins/backend/catalog-backend-module-okta) +plugin, owned and maintained by [Roadie](https://roadie.io/). + +## Installation and configuration + +For setup instructions, including authentication options (API token and OAuth +2.0), user/group filtering, custom naming strategies, and entity transformers, +see the +[plugin documentation maintained by Roadie](https://github.com/RoadieHQ/roadie-backstage-plugins/tree/main/plugins/backend/catalog-backend-module-okta). diff --git a/docs/landing-page/doc-landing-page.md b/docs/landing-page/doc-landing-page.md index 98a0ad9fb9..b7cc44c696 100644 --- a/docs/landing-page/doc-landing-page.md +++ b/docs/landing-page/doc-landing-page.md @@ -115,7 +115,7 @@ description: Documentation landing page. diff --git a/docs/notifications/index--old.md b/docs/notifications/index--old.md new file mode 100644 index 0000000000..d99f5144bc --- /dev/null +++ b/docs/notifications/index--old.md @@ -0,0 +1,299 @@ +--- +id: index--old +title: Getting Started (Old Frontend System) +description: How to get started with the notifications and signals +--- + +::::info +This documentation is for Backstage apps that still use the old frontend +system. If your app uses the new frontend system, read the +[current guide](./index.md) instead. +:::: + +The Backstage Notifications System provides a way for plugins and external services to send notifications to Backstage users. +These notifications are displayed in the dedicated page of the Backstage frontend UI or by frontend plugins per specific scenarios. +Additionally, notifications can be sent to external channels (like email) via "processors" implemented within plugins. + +Notifications can be optionally extended with the signals plugin, which provides a push mechanism to ensure users receive notifications immediately. + +### Upgrade to the latest version of Backstage + +To ensure your version of Backstage has all the latest notifications and signals related functionality, it's important to upgrade to the latest version. The [Backstage upgrade helper](https://backstage.github.io/upgrade-helper/) is a great tool to help ensure that you've made all the necessary changes during the upgrade! + +## About notifications + +Notifications are messages sent to either individual users or groups. +They are not intended for inter-process communication of any kind. + +There are two basic types of notifications: + +- **Broadcast**: Messages sent to all users of Backstage. +- **Entity**: Messages delivered to specific listed entities, such as Users or Groups. + +Example of use-cases: + +- System-wide announcements or alerts +- Notifications for component owners, e.g. build failures, successful deployments, new vulnerabilities +- Notifications for individuals, e.g. updates you have subscribed to, new required training courses +- Notifications pertaining to a particular entity in the catalog: A notification might apply to an entity and the owning team. + +## Installation + +:::note + +As of the `1.42.0` release of Backstage, Notifications and Signals are installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installation steps outlined here. The only exception to this is adding the [Notifications tab to User Settings](#user-specific-notification-settings) to allow managing these settings. + +::: + +The following sections will walk you through the installation of the various parts of the Backstage Notification System. + +### Add Notifications Backend + +First we need to add the backend package: + +```bash title="From your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-notifications-backend +``` + +Then we need to add it to our backend: + +```ts title="packages/backend/src/index.ts" +const backend = createBackend(); +// ... +backend.add(import('@backstage/plugin-notifications-backend')); +``` + +### Add Notifications Frontend + +First we need to add the frontend package: + +```bash title="From your Backstage root directory" +yarn --cwd packages/app add @backstage/plugin-notifications +``` + +To add the notifications main menu, add the following: + +```tsx title="packages/app/src/components/Root/Root.tsx" +import { NotificationsSidebarItem } from '@backstage/plugin-notifications'; + + + + + // ... + + + +; +``` + +Also add the route to notifications: + +```tsx title="packages/app/src/App.tsx" +import { NotificationsPage } from '@backstage/plugin-notifications'; + + + // ... + } /> +; +``` + +### Optional: Add Signals + +The use of signals is optional but improves the user experience. + +#### Optional: Add Signals Backend + +Add signals to your backend by first adding the backend package: + +```bash title="From your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-signals-backend +``` + +Then add the signals plugin to your backend: + +```ts title="packages/backend/src/index.ts" +const backend = createBackend(); +// ... +backend.add(import('@backstage/plugin-signals-backend')); +``` + +#### Optional: Signals Frontend + +Start with adding the frontend package: + +```bash title="From your Backstage root directory" +yarn --cwd packages/app add @backstage/plugin-signals +``` + +To install the plugin, add the `SignalsDisplay` to your app root: + +```tsx title="packages/app/src/App.tsx" +import { SignalsDisplay } from '@backstage/plugin-signals'; + +export default app.createRoot( + <> + + + {/* highlight-add-next-line */} + + + + {routes} + + , +); +``` + +If the signals plugin is properly configured, it will be automatically discovered by the notifications plugin and used. + +### User-specific notification settings + +The notifications plugin provides a way for users to manage their notification settings. To enable this, you must +add the `UserNotificationSettingsCard` to your frontend. + +```tsx title="packages/app/src/App.tsx" +}> + + + + +``` + +![Notification Settings](notificationSettings.png) + +You can customize the origin names shown in the UI by passing an object where the keys are the origins and the values are the names you want to show in the UI. + +Each notification processor will receive its own row in the settings page, where the user can enable or disable notifications from that processor. + +### Default notification settings + +You can configure default notification settings for all users in your `app-config.yaml` file. This allows you to set up notification preferences globally, such as disabling specific channels or origins by default, implementing an opt-in strategy instead of opt-out. + +#### Channel-level defaults + +You can set a default enabled state for an entire channel. When set to `false`, the channel uses an opt-in strategy where notifications are disabled by default unless explicitly enabled by the user or for specific origins. + +```yaml +notifications: + defaultSettings: + channels: + - id: 'Web' + enabled: false # Opt-in strategy: channel disabled by default + - id: 'Email' + enabled: true # Opt-out strategy: channel enabled by default (default behavior) +``` + +#### Origin-level defaults + +You can also configure defaults for specific origins within a channel: + +```yaml +notifications: + defaultSettings: + channels: + - id: 'Web' + enabled: true # Channel is enabled by default + origins: + - id: 'plugin:scaffolder' + enabled: false # Disable scaffolder notifications by default + - id: 'plugin:catalog' + enabled: true # Enable catalog notifications by default +``` + +#### Topic-level defaults + +For even more granular control, you can set defaults for specific topics within origins: + +```yaml +notifications: + defaultSettings: + channels: + - id: 'Email' + enabled: false # Email is opt-in by default + origins: + - id: 'plugin:catalog' + enabled: true # But catalog notifications are enabled + topics: + - id: 'entity:validation:error' + enabled: false # Except validation errors +``` + +**Note:** If a channel's `enabled` flag is not set, it defaults to `true` for backwards compatibility. When a channel is set to `enabled: false`, all origins within that channel default to disabled unless explicitly enabled. + +### Automatic notification cleanup + +Notifications are deleted automatically after a certain period of time to prevent the database from growing indefinitely +and to keep the user interface clean. The default retention period is set to 1 year, meaning that notifications older +than that will be deleted automatically. + +The retention period can be configured by setting the `notifications.retention` in the `app-config.yaml` file. + +```yaml +notifications: + retention: 1y +``` + +If the retention is set to false, notifications will not be automatically deleted. + +## Scaffolder Action + +:::note + +As of the `1.42.0` release of Backstage, the Notifications Scaffolder action is installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installations steps outlined here. Feel free to skip to the [Basic Example](#basic-example). + +::: + +There is also a Scaffolder action that you can use to send a notification as part of your Software Template. + +First we need to add the backend package: + +```bash title="From your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-scaffolder-backend-module-notifications +``` + +Then we need to add it to our backend: + +```ts title="packages/backend/src/index.ts" +const backend = createBackend(); +// ... +backend.add( + import('@backstage/plugin-scaffolder-backend-module-notifications'), +); +``` + +### Basic Example + +Here's an example of how you can use it in your Software Template, more details and examples can be found in the "Installed actions" screen in your Backstage instances: + +```yaml title="template.yaml" +steps: + - id: notify + name: Notify + action: notification:send + input: + recipients: entity + entityRefs: + - user:default/guest + title: 'Template executed' + info: 'Your template has been executed' + severity: 'normal' +``` + +The example above would send a notification to the Guest user (`user:default/guest`) + +## Additional info + +An example of a backend plugin sending notifications can be found in the [`@backstage/plugin-scaffolder-backend-module-notifications` package](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend-module-notifications). + +Sources of the notifications and signals plugins: + +- [notifications](https://github.com/backstage/backstage/blob/master/plugins/notifications) +- [notifications-backend](https://github.com/backstage/backstage/blob/master/plugins/notifications-backend) +- [notifications-common](https://github.com/backstage/backstage/blob/master/plugins/notifications-common) +- [notifications-node](https://github.com/backstage/backstage/blob/master/plugins/notifications-node) +- [signals-backend](https://github.com/backstage/backstage/blob/master/plugins/signals-backend) +- [signals](https://github.com/backstage/backstage/blob/master/plugins/signals) +- [signals-node](https://github.com/backstage/backstage/blob/master/plugins/signals-node) +- [signals-react](https://github.com/backstage/backstage/blob/master/plugins/signals-react) diff --git a/docs/notifications/index.md b/docs/notifications/index.md index 3d7dc0eaac..fde24db7cb 100644 --- a/docs/notifications/index.md +++ b/docs/notifications/index.md @@ -4,6 +4,13 @@ title: Getting Started description: How to get started with the notifications and signals --- +::::info +This documentation is written for the new frontend system, which is the default +in new Backstage apps. If your Backstage app still uses the old frontend system, +read the [old frontend system version of this guide](./index--old.md) +instead. +:::: + The Backstage Notifications System provides a way for plugins and external services to send notifications to Backstage users. These notifications are displayed in the dedicated page of the Backstage frontend UI or by frontend plugins per specific scenarios. Additionally, notifications can be sent to external channels (like email) via "processors" implemented within plugins. @@ -12,7 +19,7 @@ Notifications can be optionally extended with the signals plugin, which provides ### Upgrade to the latest version of Backstage -To ensure your version of Backstage has all the latest notifications and signals related functionality, it’s important to upgrade to the latest version. The [Backstage upgrade helper](https://backstage.github.io/upgrade-helper/) is a great tool to help ensure that you’ve made all the necessary changes during the upgrade! +To ensure your version of Backstage has all the latest notifications and signals related functionality, it's important to upgrade to the latest version. The [Backstage upgrade helper](https://backstage.github.io/upgrade-helper/) is a great tool to help ensure that you've made all the necessary changes during the upgrade! ## About notifications @@ -35,7 +42,7 @@ Example of use-cases: :::note -As of the `1.42.0` release of Backstage, Notifications and Signals are installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installations steps outlined here. The only exception to this is adding the [Notifications tab to User Settings](#user-specific-notification-settings) to allow managing these settings. +As of the `1.42.0` release of Backstage, Notifications and Signals are installed as part of the default `@backstage/create-app` instance which means you won't need to follow the installation steps outlined here. The only exception to this is adding the [Notifications sidebar item](#add-notifications-sidebar-item) and optionally [Notifications tab to User Settings](#user-specific-notification-settings). ::: @@ -65,35 +72,29 @@ First we need to add the frontend package: yarn --cwd packages/app add @backstage/plugin-notifications ``` -To add the notifications main menu, add the following: +Once installed, the notifications plugin is automatically available in your app through the default feature discovery. It provides a notifications page at `/notifications` and the notifications API. For more details and alternative installation methods, see [installing plugins](../frontend-system/building-apps/05-installing-plugins.md). -```tsx title="packages/app/src/components/Root/Root.tsx" +### Add Notifications Sidebar Item + +The notifications plugin does not yet include a built-in navigation item, so you need to add the `NotificationsSidebarItem` component to your sidebar manually. If you have a custom sidebar through a `NavContentBlueprint`, add the component there: + +```tsx import { NotificationsSidebarItem } from '@backstage/plugin-notifications'; - - - - // ... - - - -; -``` - -Also add the route to notifications: - -```tsx title="packages/app/src/App.tsx" -import { NotificationsPage } from '@backstage/plugin-notifications'; - - - // ... - } /> -; +// Inside your NavContentBlueprint component: + + }> + {/* ... other items ... */} + + } to="/settings"> + + +; ``` ### Optional: Add Signals -The use of signals is optional but improves the user experience. +The use of signals is optional but improves the user experience by providing real-time push updates. #### Optional: Add Signals Backend @@ -119,42 +120,51 @@ Start with adding the frontend package: yarn --cwd packages/app add @backstage/plugin-signals ``` -To install the plugin, add the `SignalsDisplay` to your app root: - -```tsx title="packages/app/src/App.tsx" -import { SignalsDisplay } from '@backstage/plugin-signals'; - -export default app.createRoot( - <> - - - {/* highlight-add-next-line */} - - - - {routes} - - , -); -``` - -If the signals plugin is properly configured, it will be automatically discovered by the notifications plugin and used. +Once installed, the signals plugin is automatically available in your app through the default feature discovery. No additional configuration is required. If the signals plugin is properly configured, it will be automatically discovered by the notifications plugin and used. ### User-specific notification settings -The notifications plugin provides a way for users to manage their notification settings. To enable this, you must -add the `UserNotificationSettingsCard` to your frontend. +The notifications plugin provides a way for users to manage their notification settings. To enable this, you can create a frontend module that adds a settings tab to the user-settings plugin using the `SubPageBlueprint`: -```tsx title="packages/app/src/App.tsx" -}> - - - - +```tsx title="packages/app/src/modules/NotificationSettingsPage.tsx" +import { Content } from '@backstage/core-components'; +import { UserNotificationSettingsCard } from '@backstage/plugin-notifications'; + +export function NotificationSettingsPage() { + return ( + + + + ); +} ``` +```tsx title="packages/app/src/modules/notificationSettings.tsx" +import { createFrontendModule } from '@backstage/frontend-plugin-api'; +import { SubPageBlueprint } from '@backstage/frontend-plugin-api'; + +export const notificationSettingsModule = createFrontendModule({ + pluginId: 'user-settings', + extensions: [ + SubPageBlueprint.make({ + name: 'notifications', + params: { + path: 'notifications', + title: 'Notifications', + loader: () => + import('./NotificationSettingsPage').then(m => ( + + )), + }, + }), + ], +}); +``` + +Then install the module in your app by adding it to the features array of `createApp`, or through default feature discovery if your app is set up for it. + ![Notification Settings](notificationSettings.png) You can customize the origin names shown in the UI by passing an object where the keys are the origins and the values are the names you want to show in the UI. diff --git a/docs/notifications/usage--old.md b/docs/notifications/usage--old.md new file mode 100644 index 0000000000..8e64e37c4d --- /dev/null +++ b/docs/notifications/usage--old.md @@ -0,0 +1,283 @@ +--- +id: usage--old +title: Usage (Old Frontend System) +description: How to use the notifications and signals +--- + +::::info +This documentation is for Backstage apps that still use the old frontend +system. If your app uses the new frontend system, read the +[current guide](./usage.md) instead. +:::: + +## Notifications Backend + +The notifications backend plugin provides an API to create notifications, list notifications per logged-in user, and search based on parameters. + +The plugin uses a relational [database](https://backstage.io/docs/getting-started/config/database) for persistence; no specifics are introduced in this context. + +No additional configuration in the app-config is needed, except for optional additional modules for `processors`. + +## Notifications Frontend + +The recipients of notifications have to be entities in the catalog, e.g., of the User or Group kind. + +Otherwise, no specific configuration is needed for the front-end notifications plugin. + +All parametrization is done through component properties, such as the `NotificationsSidebarItem`, which can be used as an active left-side menu item in the front-end. + +![Notifications Page](notificationsPage.png) + +In the `packages/app/src/components/Root/Root.tsx`, tweak the [properties](https://backstage.io/api/stable/functions/_backstage_plugin-notifications.index.NotificationsSidebarItem.html) of the `` per specific needs. + +## Usage + +New notifications can be sent either by a backend plugin or by an external service through the REST API. + +## Backend + +Regardless of technical feasibility, a backend plugin should avoid directly accessing the notifications REST API. +Instead, it should integrate with the `@backstage/plugin-notifications-node` to `send` (create) a new notification. + +The reasons for this approach include the propagation of authorization in the API request and improved maintenance and backward compatibility in the future. + +```ts +import { notificationService } from '@backstage/plugin-notifications-node'; + +export const myPlugin = createBackendPlugin({ + pluginId: 'myPlugin', + register(env) { + env.registerInit({ + deps: { + // ... + notificationService: notificationService, + }, + async init({ + // ... + notificationService, + }) { + httpRouter.use( + await createRouter({ + // ... + notificationService, + }), + ); + }, + }); + }, +}); +``` + +To emit a new notification: + +```ts +await notificationService.send({ + recipients /* of the broadcast or entity type */, + payload /* actual message */, +}); +``` + +Consult the [API documentation](https://github.com/backstage/backstage/blob/master/plugins/notifications-node/report.api.md) for further details. + +### External Services + +When the emitter of a notification is a Backstage backend plugin, it is mandatory to use the integration via `@backstage/plugin-notifications-node` as described above. + +If the emitter is a service external to Backstage, an HTTP POST request can be issued directly to the API, assuming that authentication is properly configured. +Refer to the [service-to-service auth documentation](https://backstage.io/docs/auth/service-to-service-auth) for more details, focusing on the Static Tokens section for the simplest setup option. + +An example request for creating a broadcast notification might look like: + +```bash +curl -X POST https://[BACKSTAGE_BACKEND]/api/notifications -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_BASE64_SHARED_KEY_TOKEN" -d '{"recipients":{"type":"broadcast"},"payload": {"title": "Title of broadcast message","link": "http://foo.com/bar","severity": "high","topic": "The topic"}}' +``` + +### Scaffolder Templates + +You can use the `@backstage/plugin-scaffolder-backend-module-notifications` to send notifications when scaffolder templates are run. To install the module, add it to your backend plugin: + +```bash +yarn workspace backend add @backstage/plugin-scaffolder-backend-module-notifications +``` + +Then, add the module to your backend: + +```ts +const backend = createBackend(); +// ... +backend.add( + import('@backstage/plugin-scaffolder-backend-module-notifications'), +); +``` + +In your template you can now use `notification:send` action as part of the steps: + +```yaml +steps: + - id: notify + name: Notify + action: notification:send + input: + recipients: entity + entityRefs: + - component:default/backstage + title: 'Template executed' + info: 'Your template has been executed' + severity: 'info' + link: https://backstage.io +``` + +## Signals + +The use of signals with notifications is optional but generally enhances user experience and performance. + +When a notification is created, a new signal is emitted to a general-purpose message bus to announce it to subscribed listeners. + +The frontend maintains a persistent connection (WebSocket) to receive these announcements from the notifications channel. +The specific details of the updated or created notification should be retrieved via a request to the notifications API, except for new notifications, where the payload is included in the signal for performance reasons. + +In a frontend plugin, to subscribe to notifications' signals: + +```ts +import { useSignal } from '@backstage/plugin-signals-react'; + +const { lastSignal } = useSignal('notifications'); + +React.useEffect(() => { + /* ... */ +}, [lastSignal, notificationsApi]); +``` + +#### Using signals in your own plugin + +It's possible to use signals in your own plugin to deliver data from the backend to the frontend in near real-time. + +To use signals in your own frontend plugin, you need to add the `useSignal` hook from `@backstage/plugin-signals-react` from `@backstage/plugin-notifications-common` with optional generic type of the signal. + +```ts +// To use the same type of signal in the backend, this should be placed in a shared common package +export type MySignalType = { + user: string; + data: string; + // .... +}; + +const { lastSignal } = useSignal('my-plugin'); + +useEffect(() => { + if (lastSignal) { + // Do something with the signal + } +}, [lastSignal]); +``` + +To send signals from the backend plugin, you must add the `signalsServiceRef` to your plugin or module as a dependency. + +```ts +import { signalsServiceRef } from '@backstage/plugin-signals-node'; +export const myPlugin = createBackendPlugin({ + pluginId: 'my', + register(env) { + env.registerInit({ + deps: { + httpRouter: coreServices.httpRouter, + signals: signalsServiceRef, + }, + async init({ httpRouter, signals }) { + httpRouter.use( + await createRouter({ + signals, + }), + ); + }, + }); + }, +}); +``` + +To send the signal using the service, you can use the `publish` method. + +```ts +signals.publish({ user: 'user', data: 'test' }); +``` + +## Consuming Notifications + +In a front-end plugin, the simplest way to query a notification is by its ID: + +```ts +import { useApi } from '@backstage/core-plugin-api'; +import { notificationsApiRef } from '@backstage/plugin-notifications'; + +const notificationsApi = useApi(notificationsApiRef); + +notificationsApi.getNotification(yourId); + +// or with connection to signals: +notificationsApi.getNotification(lastSignal.notification_id); +``` + +## Metadata Field + +The metadata field is a freeform object that is designed to be used by processors. + +### Well-known Notification Metadata Fields + +Below are metadata fields that will be commonly used between processors and have defined schematics. + +#### backstage.io/body.markdown + +```ts +# Example: +const payload = { + title: 'Entities Require Attention', + description: 'Entities: Service A, Service B', + metadata: { + 'backstage.io/body.markdown': ` + # Entities + - Service A + - System B + ` + } +} +``` + +This value of this metadata field should be the notification message in markdown format. This allows additional formatting options for processors that support markdown. + +### Usage + +Below is an example of using the `backstage.io/body.markdown` metadata field in a custom processor. + +When sending a notification: + +```ts +notificationService.send({ + recipients: { type: 'entity', entityRef: 'group/default:team-a' }, + payload: { + title: 'Notification', + description: 'Description' + metadata: { + 'backstage.io/body.markdown': ` + ### Notification + Description + `, + }, + }, +}); +``` + +In the processor, you can then use the metadata field accordingly: + +```ts +async postProcess(notification: Notification): Promise { + // We suggest you parse the metadata field with a schema, i.e. Zod + const parseResult = CustomProcessorMetadataSchema.safeParse(notification.payload.metadata ?? {}); + const metadata = parseResult.success ? parseResult.data : {}; + + customNotificationSender.send({ + to: getUsers(notification.recipients), + subject: notification.payload.title, + markdownText: metadata['backstage.io/body.markdown'] ?? notification.payload.description, + }); +} +``` diff --git a/docs/notifications/usage.md b/docs/notifications/usage.md index 7437ae1cce..279a1953e1 100644 --- a/docs/notifications/usage.md +++ b/docs/notifications/usage.md @@ -4,6 +4,13 @@ title: Usage description: How to use the notifications and signals --- +::::info +This documentation is written for the new frontend system, which is the default +in new Backstage apps. If your Backstage app still uses the old frontend system, +read the [old frontend system version of this guide](./usage--old.md) +instead. +:::: + ## Notifications Backend The notifications backend plugin provides an API to create notifications, list notifications per logged-in user, and search based on parameters. @@ -18,11 +25,11 @@ The recipients of notifications have to be entities in the catalog, e.g., of the Otherwise, no specific configuration is needed for the front-end notifications plugin. -All parametrization is done through component properties, such as the `NotificationsSidebarItem`, which can be used as an active left-side menu item in the front-end. +The `NotificationsSidebarItem` component can be used as an active left-side menu item in the front-end. Since the notifications plugin does not yet include a built-in navigation item, it needs to be added manually to your sidebar through a `NavContentBlueprint` in a custom app module. See the [Getting Started](./index.md#add-notifications-sidebar-item) guide for setup instructions. ![Notifications Page](notificationsPage.png) -In the `packages/app/src/components/Root/Root.tsx`, tweak the [properties](https://backstage.io/api/stable/functions/_backstage_plugin-notifications.index.NotificationsSidebarItem.html) of the `` per specific needs. +You can customize the sidebar item using its [properties](https://backstage.io/api/stable/functions/_backstage_plugin-notifications.index.NotificationsSidebarItem.html) to fit your specific needs. ## Usage @@ -225,7 +232,7 @@ Below are metadata fields that will be commonly used between processors and have # Example: const payload = { title: 'Entities Require Attention', - description: 'Entities: Service A, Service B' + description: 'Entities: Service A, Service B', metadata: { 'backstage.io/body.markdown': ` # Entities diff --git a/docs/overview/threat-model.md b/docs/overview/threat-model.md index 60f22a374c..5c33c5f8e6 100644 --- a/docs/overview/threat-model.md +++ b/docs/overview/threat-model.md @@ -30,7 +30,7 @@ This section assumes that you are using the Backstage is primarily designed to be deployed in a protected environment rather than being exposed to the public internet. From a confidentiality and integrity perspective, Backstage is designed to protect against unauthorized access to data and to ensure that data is not tampered with. However, Backstage does not provide more than rudimentary protection against denial of service attacks, and it is the responsibility of the operator to ensure that the Backstage deployment is protected against such attacks. A common and recommended way to protect a Backstage deployment from unauthorized access is to deploy it behind an authenticating proxy such as AWS’s ALB, GCP’s IAP, or Cloudflare Access. -Users that are signed-in in to Backstage generally have full access to all information and actions. If more fine-grained control is required, the [permissions system](../permissions/overview.md) should be enabled and configured to restrict access as necessary. +Users that are signed in to Backstage generally have full access to all information and actions. If more fine-grained control is required, the [permissions system](../permissions/overview.md) should be enabled and configured to restrict access as necessary. An operator is responsible for protecting the integrity of configuration files as it may otherwise be possible to introduce vulnerable configurations, as well as the confidentiality of configured secrets related to Backstage as these typically include authentication details to third party systems. diff --git a/docs/permissions/custom-rules.md b/docs/permissions/custom-rules.md index 4b188ce7f9..039805bcb4 100644 --- a/docs/permissions/custom-rules.md +++ b/docs/permissions/custom-rules.md @@ -23,7 +23,7 @@ import { createConditionFactory, createPermissionRule, } from '@backstage/plugin-permission-node'; -import { z } from 'zod'; +import { z } from 'zod/v3'; export const isInSystemRule = createPermissionRule({ name: 'IS_IN_SYSTEM', diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md index 1e1a73607b..afdb3b8c62 100644 --- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md +++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md @@ -126,7 +126,7 @@ import { createPermissionRule, } from '@backstage/plugin-permission-node'; import { TODO_LIST_RESOURCE_TYPE } from '@internal/plugin-todo-list-common'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { Todo, TodoFilter } from './todos'; export const todoListPermissionResourceRef = createPermissionResourceRef< diff --git a/docs/plugins/add-to-directory.md b/docs/plugins/add-to-directory.md index 48affef489..a87062e207 100644 --- a/docs/plugins/add-to-directory.md +++ b/docs/plugins/add-to-directory.md @@ -4,6 +4,12 @@ title: Add to Directory description: Documentation on Adding Plugin to Plugin Directory --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The process for adding plugins to the directory described here is still current. + +::: + ## Adding a Plugin to the Directory To add a new plugin to the [plugin directory](https://backstage.io/plugins) create a file with the following pattern `.yaml` where `` is the name of your plugin. This file will go in [`microsite/data/plugins`](https://github.com/backstage/backstage/tree/master/microsite/data/plugins) with your plugin's information. Example: diff --git a/docs/plugins/analytics.md b/docs/plugins/analytics.md index 3e8d5b4111..784895ef49 100644 --- a/docs/plugins/analytics.md +++ b/docs/plugins/analytics.md @@ -4,6 +4,12 @@ title: Plugin Analytics description: Measuring usage of your Backstage instance. --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. For the new frontend system version, see [Plugin Analytics](../frontend-system/building-plugins/08-analytics.md). The concepts and events described here apply to both the old and new frontend systems. + +::: + Setting up, maintaining, and iterating on an instance of Backstage can be a large investment. To help measure return on this investment, Backstage comes with an event-based Analytics API that grants app integrators the flexibility to @@ -36,7 +42,6 @@ choice below. | Analytics Tool | Support Status | | ------------------------------------- | -------------- | -| [Google Analytics][ga] | Yes ✅ | | [Google Analytics 4][ga4] | Yes ✅ | | [New Relic Browser][newrelic-browser] | Community ✅ | | [Matomo][matomo] | Community ✅ | @@ -47,7 +52,6 @@ To suggest an integration, please [open an issue][add-tool] for the analytics tool your organization uses. Or jump to [Writing Integrations][int-howto] to learn how to contribute the integration yourself! -[ga]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga/README.md [ga4]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-ga4/README.md [newrelic-browser]: https://github.com/backstage/community-plugins/blob/main/workspaces/analytics/plugins/analytics-module-newrelic-browser/README.md [qm]: https://github.com/quantummetric/analytics-module-qm/blob/main/README.md diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md index 2872fdcda9..91a3e04839 100644 --- a/docs/plugins/backend-plugin.md +++ b/docs/plugins/backend-plugin.md @@ -4,6 +4,12 @@ title: Backend plugins description: Creating and Developing Backend plugins --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. While this page already describes the new backend system patterns, the canonical documentation for building backend plugins has moved to [Building Backend Plugins and Modules](../backend-system/building-plugins-and-modules/01-index.md). + +::: + This page describes the process of creating and managing backend plugins in your Backstage repository. diff --git a/docs/plugins/call-existing-api.md b/docs/plugins/call-existing-api.md index 35a6d8d599..5b5a91b708 100644 --- a/docs/plugins/call-existing-api.md +++ b/docs/plugins/call-existing-api.md @@ -4,6 +4,12 @@ title: Call Existing API description: Describes the various options that Backstage frontend plugins have, in communicating with service APIs that already exist --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The frontend code examples on this page use the old frontend system APIs (`discoveryApiRef`, `fetchApiRef` from `@backstage/core-plugin-api`). The same APIs are available in the new frontend system via `@backstage/frontend-plugin-api`. The general guidance on when to use direct requests vs. the proxy vs. a backend plugin remains valid for both systems. + +::: + This article describes the various options that Backstage frontend plugins have, in communicating with service APIs that already exist. Each section below describes a possible choice, and the circumstances under which it fits. diff --git a/docs/plugins/composability.md b/docs/plugins/composability.md index d6c9abc98f..35da80a5b2 100644 --- a/docs/plugins/composability.md +++ b/docs/plugins/composability.md @@ -4,6 +4,12 @@ title: Composability System description: Documentation for the Backstage plugin composability APIs. --- +:::caution Legacy Documentation + +This page describes the composability system for the **old frontend system**, including `createRoutableExtension`, `createComponentExtension`, `RouteRef`, `ExternalRouteRef`, and component data. For the new frontend system, see [Extensions](../frontend-system/architecture/20-extensions.md), [Extension Blueprints](../frontend-system/architecture/23-extension-blueprints.md), and [Routes](../frontend-system/architecture/36-routes.md). + +::: + ## Summary This page describes the composability system that helps bring together content diff --git a/docs/plugins/create-a-plugin.md b/docs/plugins/create-a-plugin.md index ea0b088af7..8c97a3d30d 100644 --- a/docs/plugins/create-a-plugin.md +++ b/docs/plugins/create-a-plugin.md @@ -4,6 +4,12 @@ title: Create a Backstage Plugin description: Documentation on How to Create a Backstage Plugin --- +:::caution Legacy Documentation + +This page describes creating plugins for the **old frontend system**. For creating plugins using the new frontend system, see [Building Frontend Plugins](../frontend-system/building-plugins/01-index.md). For creating backend plugins, see [Building Backend Plugins and Modules](../backend-system/building-plugins-and-modules/01-index.md). + +::: + A Backstage Plugin adds functionality to Backstage. ## Create a Plugin diff --git a/docs/plugins/feature-flags.md b/docs/plugins/feature-flags.md index 2d0e34ba4b..25251e3db5 100644 --- a/docs/plugins/feature-flags.md +++ b/docs/plugins/feature-flags.md @@ -4,6 +4,12 @@ title: Feature Flags description: Details the process of defining setting and reading a feature flag. --- +:::caution Legacy Documentation + +This page describes feature flags using the **old frontend system** APIs (`createPlugin` from `@backstage/core-plugin-api` and `createApp` from `@backstage/app-defaults`). For the new frontend system version, see [Feature Flags](../frontend-system/building-plugins/09-feature-flags.md). The `FeatureFlagged` component and `featureFlagsApiRef` work the same way in both systems. + +::: + Backstage offers the ability to define feature flags inside a plugin or during application creation. This allows you to restrict parts of your plugin to those individual users who have toggled the feature flag to on. This page describes the process of defining, setting and reading a feature flag. If you are looking for using feature flags specifically with software templates please see [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#remove-sections-or-fields-based-on-feature-flags). diff --git a/docs/plugins/index.md b/docs/plugins/index.md index ef45152f55..388c3b1177 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -1,9 +1,15 @@ --- id: index -title: Introduction to Plugins -description: Learn about integrating various infrastructure and software development tools into Backstage through plugins. +title: Introduction to Plugins (Legacy) +description: Legacy documentation for integrating various infrastructure and software development tools into Backstage through plugins using the old frontend system. --- +:::caution Legacy Documentation + +This section covers plugin development using the **old frontend system**. For new development, please refer to the [new frontend system](../frontend-system/index.md) and [new backend system](../backend-system/index.md) documentation. The content here is kept for reference and for maintaining existing plugins that have not yet been migrated. + +::: + Backstage orchestrates a cohesive single-page application by seamlessly integrating various plugins. Our vision for the plugin ecosystem champions flexibility, empowering you to incorporate a broad spectrum of infrastructure and software development tools into Backstage as plugins. Adherence to stringent [design guidelines](../dls/design.md) guarantees a consistent and intuitive user experience across the entire plugin landscape. diff --git a/docs/plugins/integrating-plugin-into-software-catalog.md b/docs/plugins/integrating-plugin-into-software-catalog.md index 417b932451..1e3ebb2d2b 100644 --- a/docs/plugins/integrating-plugin-into-software-catalog.md +++ b/docs/plugins/integrating-plugin-into-software-catalog.md @@ -4,6 +4,12 @@ title: Integrate into the Software Catalog description: How to integrate a plugin into software catalog --- +:::caution Legacy Documentation + +This page describes integrating plugins into the Software Catalog using the **old frontend system** patterns (`EntitySwitch`, `EntityLayout`, `EntityLayout.Route`). For the new frontend system, entity page integrations are done using `EntityCardBlueprint` and `EntityContentBlueprint` — see [Common Extension Blueprints](../frontend-system/building-plugins/03-common-extension-blueprints.md). + +::: + > This is an advanced use case and currently is an experimental feature. Expect > API to change over time diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md index 7a7201d9e6..cbd9c89e14 100644 --- a/docs/plugins/integrating-search-into-plugins.md +++ b/docs/plugins/integrating-search-into-plugins.md @@ -4,6 +4,12 @@ title: Integrating Search into a plugin description: How to integrate Search into a Backstage plugin --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The backend search collator patterns described here use the new backend system and are still current. The frontend search experience examples use the old frontend system APIs. + +::: + The Backstage Search Platform was designed to give plugin developers the APIs and interfaces needed to offer search experiences within their plugins, while abstracting away (and instead empowering application integrators to choose) the diff --git a/docs/plugins/internationalization.md b/docs/plugins/internationalization.md index 2770f76799..67a6b962a0 100644 --- a/docs/plugins/internationalization.md +++ b/docs/plugins/internationalization.md @@ -4,6 +4,12 @@ title: Internationalization description: Documentation on adding internationalization to plugins and apps --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. For the new frontend system version, see [Internationalization](../frontend-system/building-plugins/07-internationalization.md). The i18n APIs (`createTranslationRef`, `useTranslationRef`) work the same way in both the old and new frontend systems. + +::: + ## Overview The Backstage core function provides internationalization for plugins and apps. The underlying library is [`i18next`](https://www.i18next.com/) with some additional Backstage typescript magic for type safety with keys. diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index cf983615b5..e7cef270ab 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -4,6 +4,12 @@ title: New Backend System description: Details of the new backend system --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The canonical documentation for the backend system has moved to the [Backend System](../backend-system/index.md) section, which includes more detailed and up-to-date guides for [building plugins and modules](../backend-system/building-plugins-and-modules/01-index.md), [architecture](../backend-system/architecture/01-index.md), and [core services](../backend-system/core-services/01-index.md). + +::: + ## Status The new backend system is released and ready for production use, and many plugins and modules have already been migrated. We recommend all plugins and deployments to migrate to the new system. diff --git a/docs/plugins/observability.md b/docs/plugins/observability.md index 7803d90bd5..eab2ed200c 100644 --- a/docs/plugins/observability.md +++ b/docs/plugins/observability.md @@ -4,6 +4,12 @@ title: Observability description: Adding Observability to Your Plugin --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. For new backend system logging, see the [Logger](../backend-system/core-services/logger.md) and [Root Logger](../backend-system/core-services/root-logger.md) core service documentation. For health checks, see [Root Health](../backend-system/core-services/root-health.md). + +::: + This article briefly describes the observability options that are available to a Backstage integrator. diff --git a/docs/plugins/plugin-development.md b/docs/plugins/plugin-development.md index 5ba1de4a7d..89318e7c5f 100644 --- a/docs/plugins/plugin-development.md +++ b/docs/plugins/plugin-development.md @@ -4,6 +4,12 @@ title: Plugin Development description: Documentation on Plugin Development --- +:::caution Legacy Documentation + +This page covers plugin development patterns for the **old frontend system**, including `createPlugin`, `createRoutableExtension`, and `RouteRef` from `@backstage/core-plugin-api`. For the new frontend system equivalents, see [Building Frontend Plugins](../frontend-system/building-plugins/01-index.md) and [Routes](../frontend-system/architecture/36-routes.md). + +::: + Backstage plugins provide features to a Backstage App. Each plugin is treated as a self-contained web app and can include almost any diff --git a/docs/plugins/plugin-directory-audit.md b/docs/plugins/plugin-directory-audit.md index 9e82cb6de5..b080463c82 100644 --- a/docs/plugins/plugin-directory-audit.md +++ b/docs/plugins/plugin-directory-audit.md @@ -4,6 +4,12 @@ title: Plugin Directory Audit description: Details about the process for auditing plugins in the directory --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The audit process described here is still current. + +::: + ## Audit Process We have a simple process in place to audit the plugins in the Plugin Directory: diff --git a/docs/plugins/proxying.md b/docs/plugins/proxying.md index bd89fc6c36..a764ea64d2 100644 --- a/docs/plugins/proxying.md +++ b/docs/plugins/proxying.md @@ -4,6 +4,12 @@ title: Proxying description: Documentation on Proxying --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The proxy configuration and usage described here applies to both the old and new backend systems. For creating backend plugins and modules, see [Building Backend Plugins and Modules](../backend-system/building-plugins-and-modules/01-index.md). + +::: + This page describes how to configure and use the built-in HTTP proxy functionality in your Backstage backend. ## Overview diff --git a/docs/plugins/publish-private.md b/docs/plugins/publish-private.md deleted file mode 100644 index d04449d465..0000000000 --- a/docs/plugins/publish-private.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: publish-private -title: Publish private -description: Documentation on How to Publish private ---- - -## TODO diff --git a/docs/plugins/structure-of-a-plugin.md b/docs/plugins/structure-of-a-plugin.md index 7cfaca4561..3843359857 100644 --- a/docs/plugins/structure-of-a-plugin.md +++ b/docs/plugins/structure-of-a-plugin.md @@ -4,6 +4,12 @@ title: Structure of a Plugin description: Details about structure of a plugin --- +:::caution Legacy Documentation + +This page describes the structure of a plugin for the **old frontend system**. For the new frontend system, see [Building Frontend Plugins](../frontend-system/building-plugins/01-index.md). The general folder structure is similar, but the plugin wiring in `plugin.ts` differs significantly. + +::: + Nice, you have a new plugin! We'll soon see how we can develop it into doing great things. But first off, let's look at what we get out of the box. diff --git a/docs/plugins/testing.md b/docs/plugins/testing.md index 1297d516f3..94015700fe 100644 --- a/docs/plugins/testing.md +++ b/docs/plugins/testing.md @@ -4,6 +4,12 @@ title: Testing with Jest description: Documentation on How to do unit testing with Jest --- +:::caution Legacy Documentation + +This section is part of the legacy plugins documentation. The general testing principles described here still apply, but for system-specific testing guides, see [Testing Frontend Plugins](../frontend-system/building-plugins/02-testing.md) and [Testing Backend Plugins and Modules](../backend-system/building-plugins-and-modules/02-testing.md). + +::: + :::note Note You may want to consider migrating to Jest 30, to do this, you can follow this guide: [Migrating to Jest 30](../tutorials/jest30-migration.md) diff --git a/docs/releases/v1.49.0-changelog.md b/docs/releases/v1.49.0-changelog.md new file mode 100644 index 0000000000..f3c2bef2e7 --- /dev/null +++ b/docs/releases/v1.49.0-changelog.md @@ -0,0 +1,3330 @@ +# Release v1.49.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.49.0](https://backstage.github.io/upgrade-helper/?to=1.49.0) + +## @backstage/integration@2.0.0 + +### Major Changes + +- 527cf88: **BREAKING** Removed deprecated Azure DevOps, Bitbucket, Gerrit and GitHub code: + + - For Azure DevOps, the long deprecated `token` string and `credential` object have been removed from the `config.d.ts`. Use the `credentials` array object instead. + - For Bitbucket, the long deprecated `bitbucket` object has been removed from the `config.d.ts`. Use the `bitbucketCloud` or `bitbucketServer` objects instead. + - For Gerrit, the `parseGerritGitilesUrl` function has been removed, use `parseGitilesUrlRef` instead. The `buildGerritGitilesArchiveUrl` function has also been removed, use `buildGerritGitilesArchiveUrlFromLocation` instead. + - For GitHub, the `getGitHubRequestOptions` function has been removed. + +### Minor Changes + +- d933f62: Add configurable throttling and retry mechanism for GitLab integration. + +### Patch Changes + +- 1513a0b: Fixed a security vulnerability where path traversal sequences in SCM URLs could be used to access unintended API endpoints using server-side integration credentials. +- 993a598: Fixed Azure integration config schema visibility annotations to use per-field `@visibility secret` instead of `@deepVisibility secret` on parent objects, so that non-secret fields like `clientId`, `tenantId`, `organizations`, and `managedIdentityClientId` are no longer incorrectly marked as secret. + +## @backstage/plugin-catalog@2.0.0 + +### Major Changes + +- 5fc35bb: Migrated `EntityAboutCard`, `EntityLinksCard`, `EntityLabelsCard`, `GroupProfileCard`, and `UserProfileCard` from MUI/InfoCard to use the new BUI card layout and BUI components where possible. + + **BREAKING**: Removed `variant` prop from EntityAboutCard, EntityUserProfileCard, EntityGroupProfileCard, EntityLabelsCard, EntityLinksCard. Removed `gridSizes` prop from `AboutField`. + + **Migration:** + + Simply delete the obsolete `variant` and `gridSizes` props, e.g: + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Minor Changes + +- 4d58894: Added support for group alias IDs and configurable content ordering on the entity page. Groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `defaultContentOrder` option (default `title`) controls how content items within each group are sorted, with support for both a page-level default and per-group overrides. + +- c548a0f: Migrated entity table cards (`HasComponentsCard`, `HasResourcesCard`, `HasSubcomponentsCard`, `HasSubdomainsCard`, `HasSystemsCard`, `DependsOnComponentsCard`, `DependsOnResourcesCard`, `DependencyOfComponentsCard`) to use BUI when no legacy props are passed. The old `variant`, `columns`, and `tableOptions` props are deprecated but still supported — passing any of them triggers the legacy MUI-based rendering. The new `columnConfig` prop accepts `EntityColumnConfig[]` for BUI-based rendering. + + `RelatedEntitiesCard` is deprecated — use `EntityRelationCard` from `@backstage/plugin-catalog-react/alpha` instead. + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 07ba746: Fixed entity page tab groups not respecting the ordering from the `groups` configuration. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-search-react@1.11.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-techdocs-react@1.3.9 + +## @backstage/plugin-scaffolder-common@2.0.0 + +### Major Changes + +- 527cf88: **BREAKING** Removed deprecated `bitbucket` integration from being registered in the `ScaffolderClient`. Use the `bitbucketCloud` or `bitbucketServer` integrations instead. + +### Minor Changes + +- f598909: **BREAKING PRODUCERS**: Made `retry`, `listTasks`, `listTemplatingExtensions`, `dryRun`, and `autocomplete` required methods on the `ScaffolderApi` interface. Implementations of `ScaffolderApi` must now provide these methods. +- e8736ea: Added an optional `secrets` field to `TemplateEntityV1beta3` for configuring secrets validation. The schema for validating secrets is defined under `secrets.schema` as a JSON Schema object. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@2.0.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + +## @backstage/backend-app-api@1.6.0 + +### Minor Changes + +- 545557a: Registration errors should be forwarded as BackendStartupResult + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + +## @backstage/backend-defaults@0.16.0 + +### Minor Changes + +- 42960f1: The actions registry invoke endpoint now accepts direct user credentials in addition to service principals, enabling CLI and other direct user clients to invoke actions. +- 0e7d8f9: The scheduler service now uses the metrics service to create metrics, providing plugin-scoped attribution. +- 527cf88: **BREAKING** Removed deprecated `BitbucketUrlReader`. Use the `BitbucketCloudUrlReader` or the `BitbucketServerUrlReader` instead. + +### Patch Changes + +- cc8348e: Added permissions integration to the actions registry. Actions registered with a `visibilityPermission` field are now checked against the permissions framework when listing and invoking. Denied actions are filtered from list results, and invoking a denied action returns a `404 Not Found` as if the action does not exist. Permissions are automatically registered with the `PermissionsRegistryService` so they appear in the permission policy system. +- dee4283: Added `pluginId` field to `ActionsServiceAction` type, populated from the registering plugin's metadata. +- 015668c: Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available. +- 638e6c7: chore(deps): bump `yauzl` from 3.2.0 to 3.2.1 +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 +- 62f0a53: Fixed error forwarding in the actions registry so that known errors like `InputError` and `NotFoundError` thrown by actions preserve their original status codes and messages instead of being wrapped in `ForwardedError` and coerced to 500. +- d933f62: Add configurable throttling and retry mechanism for GitLab integration. +- b99158a: Fixed `yarn backstage-cli config:check --strict --config app-config.yaml` config validation error by adding + an optional `default` type discriminator to PostgreSQL connection configuration, + allowing `config:check` to properly validate `default` connection configurations. +- 1ee5b28: Adds an alpha `MetricsService` to provide a unified interface for metrics instrumentation across Backstage plugins. +- 5fcbef2: Updated dependency `express-rate-limit` to `^8.0.0`. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/cli-node@0.3.0 + - @backstage/integration@2.0.0 + - @backstage/config-loader@1.10.9 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/backend-app-api@1.6.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/backend-dynamic-feature-service@0.8.0 + +### Minor Changes + +- 0fbcf23: Migrated OpenAPI schemas to 3.1. + +### Patch Changes + +- 4074a22: Fixed `resolvePackagePath` resolution for bundled dynamic plugins. When a plugin bundles its own copy of `@backstage/backend-plugin-api` inside `node_modules`, the `CommonJSModuleLoader` fallback now correctly resolves the plugin's `package.json` by name. Previously the fallback only applied when the resolution originated from the host application; it now also applies when originating from a bundled dependency, which is the case for plugins produced by the `backstage-cli package bundle` command. +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/cli-node@0.3.0 + - @backstage/plugin-catalog-backend@3.5.0 + - @backstage/cli-common@0.2.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/plugin-events-backend@0.6.0 + - @backstage/config-loader@1.10.9 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/backend-openapi-utils@0.6.7 + - @backstage/plugin-app-node@0.1.43 + - @backstage/plugin-events-node@0.4.20 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/backend-plugin-api@1.8.0 + +### Minor Changes + +- cc8348e: Added optional `visibilityPermission` field to `ActionsRegistryActionOptions`, allowing actions to declare a `BasicPermission` that controls visibility and access. + + ```typescript + import { createPermission } from '@backstage/plugin-permission-common'; + + const myPermission = createPermission({ + name: 'myPlugin.myAction.use', + attributes: {}, + }); + + actionsRegistry.register({ + name: 'my-action', + title: 'My Action', + description: 'An action that requires permission', + visibilityPermission: myPermission, + schema: { + input: z => z.object({ name: z.string() }), + output: z => z.object({ ok: z.boolean() }), + }, + action: async ({ input }) => { + return { output: { ok: true } }; + }, + }); + ``` + + Actions without a `visibilityPermission` field continue to work as before. + +- 015668c: Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available. + +### Patch Changes + +- dee4283: Added `pluginId` field to `ActionsServiceAction` type, populated from the registering plugin's metadata. +- 1ee5b28: Adds an alpha `MetricsService` to provide a unified interface for metrics instrumentation across Backstage plugins. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/cli-common@0.2.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/catalog-client@1.14.0 + +### Minor Changes + +- 972f686: Added support for the `query` field in `getEntitiesByRefs` requests, enabling predicate-based filtering with `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. +- 5d95e8e: Add an `onConflict` option to location creation that can refresh an existing location instead of throwing a conflict error. +- 56c908e: Added support for the `query` field in `getEntityFacets` requests, enabling predicate-based filtering with `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. +- 0fbcf23: Migrated OpenAPI schemas to 3.1. +- 51e23eb: Added predicate-based entity filtering via POST /entities/by-query endpoint. + + Supports `$all`, `$any`, `$not`, `$exists`, `$in`, `$hasPrefix`, and (partially) `$contains` operators for expressive entity queries. Integrated into the existing `queryEntities` flow with full cursor-based pagination, permission enforcement, and `totalItems` support. + + The catalog client's `queryEntities()` method automatically routes to the POST endpoint when a `query` predicate is provided. + +### Patch Changes + +- d2494d6: Minor update to catalog client docs +- Updated dependencies + - @backstage/filter-predicates@0.1.1 + - @backstage/catalog-model@1.7.7 + +## @backstage/cli@0.36.0 + +### Minor Changes + +- d0f4cd2: Added new `auth` command group for authenticating the CLI with Backstage instances using OAuth 2.0 with a pre-registered client metadata document. Commands include `login`, `logout`, `list`, `show`, `print-token`, and `select` for managing multiple authenticated instances. + +- d806b0c: The CLI now automatically discovers CLI modules from the project root's `dependencies` and `devDependencies`. Any installed package with the `cli-module` Backstage role will be loaded automatically without needing to be hardcoded in the CLI itself. + + If no CLI modules are found in the project dependencies, the CLI falls back to the built-in set of modules and prints a deprecation warning. This fallback will be removed in a future release. To prepare for this, add `@backstage/cli-defaults` as a `devDependency` in your root `package.json`: + + ```json + { + "devDependencies": { + "@backstage/cli-defaults": "backstage:^" + } + } + ``` + + If you are not using the Backstage Yarn plugin, run the following instead: + + ```sh + yarn workspace root add --dev @backstage/cli-defaults + ``` + + For fine-grained control you can instead install individual CLI modules: + + ```json + { + "devDependencies": { + "@backstage/cli-module-auth": "backstage:^", + "@backstage/cli-module-build": "backstage:^", + "@backstage/cli-module-config": "backstage:^", + "@backstage/cli-module-github": "backstage:^", + "@backstage/cli-module-info": "backstage:^", + "@backstage/cli-module-lint": "backstage:^", + "@backstage/cli-module-maintenance": "backstage:^", + "@backstage/cli-module-migrate": "backstage:^", + "@backstage/cli-module-new": "backstage:^", + "@backstage/cli-module-test-jest": "backstage:^", + "@backstage/cli-module-translations": "backstage:^" + } + } + ``` + +- 08d9770: **BREAKING**: The CLI templates for frontend plugins have been renamed: + + - `new-frontend-plugin` → `frontend-plugin` + - `new-frontend-plugin-module` → `frontend-plugin-module` + - `frontend-plugin` (legacy) → `legacy-frontend-plugin` + + To smooth out this breaking change, the CLI now auto-detects which frontend system your app uses based on the dependencies in `packages/app/package.json`. When using the default templates (no explicit `templates` configuration): + + - Apps using `@backstage/frontend-defaults` will see the new frontend system templates (`frontend-plugin`, `frontend-plugin-module`) + - Apps using `@backstage/app-defaults` will see the legacy template (displayed as `frontend-plugin`) + + This means existing projects that haven't migrated to the new frontend system will continue to create legacy plugins by default, while new projects will get the new frontend system templates. If you have explicit template configuration in your `package.json`, it will be used as-is without any auto-detection. + +- b36a60d: **BREAKING**: The `migrate package-exports` command has been removed. Use `repo fix` instead. + +### Patch Changes + +- edf2b77: Added a new `cli-module` template for creating CLI module packages. + +- 246877a: Updated dependency `bfj` to `^9.0.2`. + +- 0d2d0f2: Internal refactor of CLI modularization, moving individual commands to be implemented with cleye. + +- a4e5902: Internal refactor of the CLI command registration + +- bba2e49: Internal refactor to use new concurrency utilities from `@backstage/cli-node`. + +- 2fcba39: Internal refactor to move shared utilities into their consuming modules, reducing cross-module dependencies. + +- c85ac86: Internal refactor to split `loadCliConfig` into separate implementations for the build and config CLI modules, removing a cross-module dependency. + +- 94a885a: Added support for the new `cli-module` package role in the build system, ESLint configuration, Jest configuration, and maintenance commands. + +- fd50cb3: Added `translations export` and `translations import` commands for managing translation files. + + The `translations export` command discovers all `TranslationRef` definitions across frontend plugin dependencies and exports their default messages as JSON files. The `translations import` command generates `TranslationResource` wiring code from translated JSON files, ready to be plugged into the app. + + Both commands support a `--pattern` option for controlling the message file layout, for example `--pattern '{lang}/{id}.json'` for language-based directory grouping. + +- 0be3eab: Migrated CLI plugin modules to use `createCliModule` from `@backstage/cli-node`. + +- 61cb976: Migrated internal versioning utilities to use `@backstage/cli-node` instead of a local implementation. + +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 + +- ff4a45a: Migrated remaining CLI command handlers from `commander` to `cleye` for argument parsing. Several camelCase CLI flags have been deprecated in favor of their kebab-case equivalents (e.g. `--successCache` → `--success-cache`). The old camelCase forms still work but will now log a deprecation warning. Please update any scripts or CI configurations to use the kebab-case versions. + +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. + +- 825c81d: Internal refactor of CLI command modules. + +- ea90ab0: The built-in `yarn new` templates have been moved to `@backstage/cli-module-new`. Existing references to `@backstage/cli/templates/*` in your root `package.json` will continue to work through a backwards compatibility rewrite in the `new` command. + +- ebeb0d4: Updated the new frontend plugin template to use `@backstage/frontend-dev-utils` in its `dev/` entry point instead of wiring `createApp` manually. Generated plugins now get the same dev app helper setup as the built-in examples. + +- 971cc94: The `new` command now prompts for the plugin package name when creating plugin modules, in order to properly populate the `package.json` file. + +- de62a9d: Upgraded `commander` dependency from `^12.0.0` to `^14.0.3` across all CLI packages. + +- 092b41f: Updated dependency `webpack` to `~5.105.0`. + +- 4a75544: Updated dependency `react-refresh` to `^0.18.0`. + +- a9d23c4: Properly support `package.json` `workspaces` field + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + - @backstage/cli-defaults@0.1.0 + - @backstage/cli-module-build@0.1.0 + - @backstage/eslint-plugin@0.2.2 + - @backstage/cli-module-test-jest@0.1.0 + +## @backstage/cli-common@0.2.0 + +### Minor Changes + +- 56bd494: Added `targetPaths` and `findOwnPaths` as replacements for `findPaths`, with a cleaner separation between target project paths and package-relative paths. + + To migrate existing `findPaths` usage: + + ```ts + // Before + import { findPaths } from '@backstage/cli-common'; + const paths = findPaths(__dirname); + + // After — for target project paths (cwd-based): + import { targetPaths } from '@backstage/cli-common'; + // paths.targetDir → targetPaths.dir + // paths.targetRoot → targetPaths.rootDir + // paths.resolveTarget('src') → targetPaths.resolve('src') + // paths.resolveTargetRoot('yarn.lock') → targetPaths.resolveRoot('yarn.lock') + + // After — for package-relative paths: + import { findOwnPaths } from '@backstage/cli-common'; + const own = findOwnPaths(__dirname); + // paths.ownDir → own.dir + // paths.ownRoot → own.rootDir + // paths.resolveOwn('config/jest.js') → own.resolve('config/jest.js') + // paths.resolveOwnRoot('tsconfig.json') → own.resolveRoot('tsconfig.json') + ``` + +### Patch Changes + +- e44b6a9: The `findOwnRootDir` utility now searches for the monorepo root by traversing up the directory tree looking for a `package.json` with `workspaces`, instead of assuming a fixed `../..` relative path. If no workspaces root is found during this traversal, `findOwnRootDir` now throws to enforce stricter validation of the repository layout. +- 9361965: Fixed `runCheck` to ignore stdio of the spawned process, preventing unwanted output from leaking to the terminal. + +## @backstage/cli-defaults@0.1.0 + +### Minor Changes + +- 7781ae5: Introduced `@backstage/cli-defaults`, a convenience package that bundles all standard Backstage CLI modules. Install this single package as a `devDependency` to get the full default set of CLI commands without listing each module individually. + +### Patch Changes + +- 42960f1: Added `@backstage/cli-module-actions` to the default set of CLI modules. +- Updated dependencies + - @backstage/cli-module-actions@0.0.1 + - @backstage/cli-module-new@0.1.0 + - @backstage/cli-module-maintenance@0.1.0 + - @backstage/cli-module-build@0.1.0 + - @backstage/cli-module-auth@0.1.0 + - @backstage/cli-module-config@0.1.0 + - @backstage/cli-module-github@0.1.0 + - @backstage/cli-module-info@0.1.0 + - @backstage/cli-module-lint@0.1.0 + - @backstage/cli-module-migrate@0.1.0 + - @backstage/cli-module-test-jest@0.1.0 + - @backstage/cli-module-translations@0.1.0 + +## @backstage/cli-module-auth@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/cli-node@0.3.0 + +## @backstage/cli-module-build@0.1.0 + +### Minor Changes + +- 62d0849: Added `package bundle` command to create self-contained plugin bundles for dynamic loading, to be used by the `backend-dynamic-feature-service`. Supports backend and frontend plugins, with optional `--pre-packed-dir` for batch bundling from a pre-built workspace. +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + - @backstage/module-federation-common@0.1.2 + - @backstage/config-loader@1.10.9 + +## @backstage/cli-module-config@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + - @backstage/config-loader@1.10.9 + +## @backstage/cli-module-github@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-info@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-lint@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-maintenance@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- f189d8f: Added auto-fill of `backstage.pluginPackage` metadata for known plugins during `repo fix`. +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-migrate@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-new@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- edf2b77: Added support for the `cli-module` template role for scaffolding new CLI module packages. +- ea90ab0: The built-in `yarn new` templates have been moved to this package from `@backstage/cli`. The default template references have been updated from `@backstage/cli/templates/*` to `@backstage/cli-module-new/templates/*`. Existing references to `@backstage/cli/templates/*` in your root `package.json` will continue to work through a backwards compatibility rewrite. +- ebeb0d4: Updated the new frontend plugin template to use `@backstage/frontend-dev-utils` in its `dev/` entry point instead of wiring `createApp` manually. Generated plugins now get the same dev app helper setup as the built-in examples. +- 971cc94: The `new` command now prompts for the plugin package name when creating plugin modules, in order to properly populate the `package.json` file. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-test-jest@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-module-translations@0.1.0 + +### Minor Changes + +- 329f394: Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + +## @backstage/cli-node@0.3.0 + +### Minor Changes + +- 7d055ef: Added `createCliModule` API and related types for building Backstage CLI plugins. + +### Patch Changes + +- 94a885a: Added a new `cli-module` package role for packages that provide CLI plugin extensions. +- 12fa965: Added `CliAuth` class for managing CLI authentication state. This provides a class-based API with a static `create` method that resolves the currently selected (or explicitly named) auth instance, transparently refreshes expired access tokens, and exposes helpers for other CLI modules to authenticate with a Backstage backend. +- 61cb976: Added `toString()` method to `Lockfile` for serializing lockfiles back to string format. +- 06c2015: Added `runConcurrentTasks` and `runWorkerQueueThreads` utilities, moved from the `@backstage/cli` internal code. +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- 3c811bf: Added `hasBackstageYarnPlugin` and `SuccessCache` exports, moved from `@backstage/cli`. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- a9d23c4: Properly support `package.json` `workspaces` field +- Updated dependencies + - @backstage/cli-common@0.2.0 + +## @backstage/create-app@0.8.0 + +### Minor Changes + +- a6735c3: **BREAKING**: The new frontend system is now the default template when creating a new Backstage app. The previous `--next` flag has been replaced with a `--legacy` flag that can be used to create an app using the old frontend system instead. + +### Patch Changes + +- d806b0c: The create-app templates now include `@backstage/cli-defaults` as a `devDependency`, enabling the CLI's automatic module discovery for newly created projects. + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. + +- ea90ab0: Updated the `next-app` template to reference `@backstage/cli-module-new/templates/*` instead of `@backstage/cli/templates/*` for the built-in `yarn new` templates. + +- de62a9d: Upgraded `commander` dependency from `^12.0.0` to `^14.0.3` across all CLI packages. + +- a9d23c4: Properly support `package.json` `workspaces` field + +- ebd4630: Replace deprecated `workspaces.packages` with `workspaces` in `package.json` + + This change is **not** required, but you can edit your main `package.json`, to fit the more modern & more common pattern: + + ```diff + - "workspaces": { + - "packages": [ + "workspaces": [ + "packages/*", + "plugins/*" + - ] + - }, + ], + ``` + +- Updated dependencies + - @backstage/cli-common@0.2.0 + +## @backstage/frontend-app-api@0.16.0 + +### Minor Changes + +- 92af1ae: **BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createSpecializedApp`. This flag had no effect and was a no-op, so no behavioral changes are expected. + +### Patch Changes + +- d911b72: Frontend apps now respect an explicit `pluginId` on `ApiRef`s when deciding which plugin owns an API factory. +- 0452d02: Add optional `description` field to plugin-level feature flags. +- 5fd78ba: Removed `@backstage/core-plugin-api` leakage from the public API surface. All types such as `ApiHolder` and `ConfigApi` are now imported from `@backstage/frontend-plugin-api`. +- dab6c46: Added the `ExtensionFactoryMiddleware` type as a public export. +- 3f36ce1: Clarified the `IconElement` sizing contract for the new frontend system and aligned legacy system icon rendering with the new icon API. +- 5b160f9: Added `prepareSpecializedApp` for two-phase app wiring so apps can render a bootstrap tree before full app finalization. The bootstrap phase now supports deferred `app/root.elements`, predicate-gated APIs, reusable `sessionState`, and warnings for bootstrap-visible predicates or bootstrap code that accessed APIs that only became available after finalization. Utility APIs that are materialized during bootstrap are also frozen for the lifetime of the app instance, causing deferred overrides of those APIs to be ignored and reported as app errors. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/core-app-api@1.19.6 + - @backstage/frontend-defaults@0.5.0 + - @backstage/filter-predicates@0.1.1 + +## @backstage/frontend-defaults@0.5.0 + +### Minor Changes + +- 92af1ae: **BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createApp`. This flag had no effect and was a no-op, so no behavioral changes are expected. +- 33de79d: **BREAKING**: Removed the deprecated `createPublicSignInApp` function. Use `createApp` from `@backstage/frontend-defaults` with `appModulePublicSignIn` from `@backstage/plugin-app/alpha` instead. + +### Patch Changes + +- 5b160f9: Updated `createApp` to use the phased `prepareSpecializedApp` flow, allowing apps to render a bootstrap tree before the full app is finalized. +- Updated dependencies + - @backstage/frontend-app-api@0.16.0 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-app@0.4.1 + +## @backstage/frontend-dev-utils@0.1.0 + +### Minor Changes + +- c25532a: Added `@backstage/frontend-dev-utils`, a new package that provides a minimal helper for wiring up a development app for frontend plugins using the new frontend system. It exports a `createDevApp` function that handles creating and rendering a development app from a `dev/` entry point. The dev app automatically bypasses the sign-in page and loads the `@backstage/ui` CSS. The options interface accepts `features` together with route bindings through `bindRoutes`. + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-app@0.4.1 + - @backstage/frontend-defaults@0.5.0 + +## @backstage/frontend-plugin-api@0.15.0 + +### Minor Changes + +- 5fd78ba: Renamed `PluginOptions` to `CreateFrontendPluginOptions` and deprecated the old name. Removed `ResolvedExtensionInputs` from the main entry point; it is still available as an inline type in extension factory signatures. + +- 72991a5: Removed the `ResolvedExtensionInput` and `ExtensionDataRefToValue` helper types from the public API surface to reduce top-level API clutter. These types were internal plumbing that are not needed by plugin authors. If you were relying on `ResolvedExtensionInput`, use the `ResolvedExtensionInputs` type instead, which maps a full set of inputs. If you were using `ExtensionDataRefToValue`, replace it with `ExtensionDataValue` combined with inferred types from your `ExtensionDataRef`. + +- 9508514: **BREAKING**: Promoted `PluginWrapperApi`, `pluginWrapperApiRef`, `PluginWrapperBlueprint`, and the new `PluginWrapperDefinition` type from `@alpha` to `@public`. These are now available from the main package entry point rather than only through `/alpha`. + + The `PluginWrapperApi` type now has a required `getRootWrapper()` method that returns a root wrapper component. The `pluginWrapperApiRef` ID changed from `core.plugin-wrapper.alpha` to `core.plugin-wrapper`. + + The `PluginWrapperBlueprint` now accepts `PluginWrapperDefinition` as the loader return type, which supports an optional `useWrapperValue` hook that allows sharing state between wrapper instances. + +- 6573901: **BREAKING**: Removed the deprecated `AnyExtensionDataRef` type. Use `ExtensionDataRef` without type parameters instead. + +- a9440f0: **BREAKING**: Simplified the `ExtensionAttachTo` type to only support a single attachment target. The array form for attaching to multiple extension points has been removed. Also removed the deprecated `ExtensionAttachToSpec` type alias. + +### Patch Changes + +- e26e3de: The `icon` field on `AuthProviderInfo` now accepts `IconElement` in addition to `IconComponent`, letting you pass `` instead of `MyIcon`. + +- eea95b8: Deprecated `AlertApi` in favor of the new `ToastApi`. + + `AlertApi` is now deprecated and will be removed in a future release. Please migrate to `ToastApi` which provides richer notification features. + + **Why migrate?** + + `ToastApi` offers enhanced capabilities over `AlertApi`: + + - **Title and Description**: Display a prominent title with optional description text + - **Action Links**: Include clickable links within notifications + - **Status Variants**: Support for neutral, info, success, warning, and danger statuses + - **Per-toast Timeout**: Control auto-dismiss timing for each notification individually + - **Programmatic Dismiss**: Close notifications via the `close()` handle returned from `post()` + + **Migration Guide** + + | AlertApi | ToastApi | + | -------------------------------------------- | ------------------------------------------ | + | `message: string` | `title: ReactNode` | + | `severity: 'error'` | `status: 'danger'` | + | `severity: 'success' \| 'info' \| 'warning'` | `status: 'success' \| 'info' \| 'warning'` | + | `display: 'transient'` | `timeout: 5000` (or custom ms) | + | `display: 'permanent'` | omit `timeout` | + | `post()` returns `void` | `post()` returns `{ close(): void }` | + + **Example Migration** + + ```typescript + // Before (AlertApi) + import { alertApiRef, useApi } from '@backstage/core-plugin-api'; + + const alertApi = useApi(alertApiRef); + alertApi.post({ + message: 'Entity saved successfully', + severity: 'success', + display: 'transient', + }); + + // After (ToastApi) + import { toastApiRef, useApi } from '@backstage/frontend-plugin-api'; + + const toastApi = useApi(toastApiRef); + const toast = toastApi.post({ + title: 'Entity saved successfully', + status: 'success', + timeout: 5000, + }); + // Later: toast.close() to dismiss programmatically + ``` + + **Note**: During the migration period, both APIs work simultaneously. The `ToastDisplay` component subscribes to both `AlertApi` and `ToastApi`, so existing code continues to work while you migrate incrementally. + +- 8a3a906: Deprecated `NavItemBlueprint`. Nav items are now automatically inferred from `PageBlueprint` extensions based on their `title` and `icon` params. + +- b15a685: Deprecated `withApis`, use the `withApis` export from `@backstage/core-compat-api` instead. + +- 0452d02: Add optional `description` field to plugin-level feature flags. + +- 1bec049: Fixed inconsistent `JSX.Element` type reference in the `DialogApiDialog.update` method signature. + +- 9c81af9: Made the `pluginId` property optional in the `FrontendFeature` type, allowing plugins published against older versions of the framework to be used without type errors. + +- 2c383b5: Deprecated `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory` in favor of the exports from `@backstage/plugin-app-react`. + +- dab6c46: Deprecated the `ExtensionFactoryMiddleware` type, which has been moved to `@backstage/frontend-app-api`. + +- aa29b50: Pages created with `PageBlueprint` now render the plugin header by default in the new frontend system. + +- 3f36ce1: Clarified the `IconElement` sizing contract for the new frontend system and aligned legacy system icon rendering with the new icon API. + +- cc459f7: Added a builder form for `createApiRef` in the new frontend system and deprecated the direct `createApiRef({ ... })` call in favor of `createApiRef().with({ ... })`. The builder form now also preserves literal API ref IDs in the resulting `ApiRef` type. + + The `createApiRef().with({ ... })` form can also use an explicit `pluginId` to declare API ownership without encoding the plugin ID into the API ref ID, while keeping that metadata internal to runtime handling. + +- 5b160f9: Added support for `if` predicates on `createFrontendPlugin` and `createFrontendModule`, applying shared conditions to every extension in the feature. Plugin and extension overrides can now also replace or remove existing `if` predicates. + +- d0206c4: Removed the deprecated `defaultPath` migration helper from `PageBlueprint` params. + +- edb872c: Renamed the `PageTab` type to `PageLayoutTab`. The old `PageTab` name is now a deprecated type alias. + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +- 7e743f4: Introduced a new `ToastApi` for displaying rich toast notifications in the new frontend system. + + The new `ToastApi` provides enhanced notification capabilities compared to the existing `AlertApi`: + + - **Title and Description**: Toasts support both a title and an optional description + - **Custom Timeouts**: Each toast can specify its own timeout duration + - **Links**: Toasts can include action links + - **Status Variants**: Support for neutral, info, success, warning, and danger statuses + - **Programmatic Dismiss**: Toasts can be dismissed programmatically using the `close()` handle returned from `post()` + + **Usage:** + + ```typescript + import { toastApiRef, useApi } from '@backstage/frontend-plugin-api'; + + const toastApi = useApi(toastApiRef); + + // Full-featured toast + toastApi.post({ + title: 'Entity saved', + description: 'Your changes have been saved successfully.', + status: 'success', + timeout: 5000, + links: [{ label: 'View entity', href: '/catalog/entity' }], + }); + + // Programmatic dismiss + const { close } = toastApi.post({ title: 'Uploading...', status: 'info' }); + // Later... + close(); + ``` + + The `ToastDisplay` component subscribes to both `ToastApi` and `AlertApi`, providing a migration path where both systems work side by side until `AlertApi` is fully deprecated. + +- fe848e0: Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context. + +- Updated dependencies + - @backstage/filter-predicates@0.1.1 + +## @backstage/repo-tools@0.17.0 + +### Minor Changes + +- 0fbcf23: Added support for OpenAPI 3.1 to all `schema openapi` commands. The commands now auto-detect the OpenAPI version from the spec file and use the appropriate generator, supporting both OpenAPI 3.0.x and 3.1.x specifications. + +### Patch Changes + +- 426edbe: Fixed `generate-catalog-info` command failing with "too many arguments" when invoked by lint-staged via the pre-commit hook. +- d5779e5: Updated the CLI report parser to support cleye-style help output, and strip ANSI escape codes from captured output. +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 +- 2a51546: Fixed prettier existence checks in OpenAPI commands to use `fs.pathExists` instead of checking the resolved path string, which was always truthy. +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- de62a9d: Upgraded `commander` dependency from `^12.0.0` to `^14.0.3` across all CLI packages. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 18a946c: Updated `@microsoft/api-extractor` to `7.57.3` and added tests for `getTsDocConfig` +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/cli-node@0.3.0 + - @backstage/cli-common@0.2.0 + - @backstage/config-loader@1.10.9 + - @backstage/catalog-model@1.7.7 + +## @backstage/ui@0.13.0 + +### Minor Changes + +- 768f09d: **BREAKING**: Simplified the neutral background prop API for container components. The explicit `neutral-1`, `neutral-2`, `neutral-3`, and `neutral-auto` values have been removed from `ProviderBg`. They are replaced by a single `'neutral'` value that always auto-increments from the parent context, making it impossible to skip or pin to an explicit neutral level. + + **Migration:** + + Replace any explicit `bg="neutral-1"`, `bg="neutral-2"`, `bg="neutral-3"`, or `bg="neutral-auto"` props with `bg="neutral"`. To achieve a specific neutral level in stories or tests, use nested containers — each additional `bg="neutral"` wrapper increments by one level. + + ```tsx + // Before + ... + + // After + + ... + + ``` + + **Affected components:** Box, Flex, Grid, Card, Accordion, Popover, Tooltip, Dialog, Menu + +- b42fcdc: **BREAKING**: Removed `--bui-bg-popover` CSS token. Popover, Tooltip, Menu, and Dialog now use `--bui-bg-app` for their outer shell and `Box bg="neutral-1"` for content areas, providing better theme consistency and eliminating a redundant token. + + **Migration:** + + Replace any usage of `--bui-bg-popover` with `--bui-bg-neutral-1` (for content surfaces) or `--bui-bg-app` (for outer shells): + + ```diff + - background: var(--bui-bg-popover); + + background: var(--bui-bg-neutral-1); + ``` + + **Affected components:** Popover, Tooltip, Menu, Dialog + +- bd3a76e: **BREAKING**: Data attributes rendered by components are now always lowercase. This affects CSS selectors targeting camelCase data attributes. + + **Migration:** + + Update any custom CSS selectors that target camelCase data attributes to use lowercase instead: + + ```diff + - [data-startCollapsed='true'] { ... } + + [data-startcollapsed='true'] { ... } + ``` + + **Affected components:** SearchField + +- 95702ab: **BREAKING**: Removed deprecated types `ComponentDefinition`, `ClassNamesMap`, `DataAttributeValues`, and `DataAttributesMap` from the public API. These were internal styling infrastructure types that have been replaced by the `defineComponent` system. + + **Migration:** + + Remove any direct usage of these types. Component definitions now use `defineComponent()` and their shapes are not part of the public API contract. + + ```diff + - import type { ComponentDefinition, ClassNamesMap } from '@backstage/ui'; + ``` + + If you were reading `definition.dataAttributes`, use `definition.propDefs` instead — props with `dataAttribute: true` in `propDefs` are the equivalent. + +- 42f8c9b: **BREAKING**: Centralized client-side routing in `BUIProvider`. Components like Link, ButtonLink, Tabs, Menu, TagGroup, and Table now require a `BUIProvider` rendered inside a React Router context for client-side navigation to work. + + **Migration:** + + This change requires updating `@backstage/plugin-app` and `@backstage/core-app-api` alongside `@backstage/ui`. If you only upgrade `@backstage/ui`, BUI components will fall back to full-page navigation. + + If you cannot upgrade all packages together, or if you have a custom app shell, add a `BUIProvider` inside your Router: + + ```diff + + import { BUIProvider } from '@backstage/ui'; + + + + + + + + + ``` + + **Affected components:** Link, ButtonLink, Tabs, Menu, TagGroup, Table + +- 17d6398: **BREAKING**: Renamed internal CSS classes to match the `Header` component name. + + **Migration:**: If you are targeting these classes directly in your styles, update the following: + + - `bui-HeaderPage` → `bui-Header` + - `bui-HeaderPageContent` → `bui-HeaderContent` + - `bui-HeaderPageBreadcrumbs` → `bui-HeaderBreadcrumbs` + - `bui-HeaderPageTabsWrapper` → `bui-HeaderTabsWrapper` + - `bui-HeaderPageControls` → `bui-HeaderControls` + + **Affected components:**: Header + +- 9d5f3ba: Removed redundant `selected` and `indeterminate` props from the `Checkbox` component. Use the `isSelected` and `isIndeterminate` props instead, which are the standard React Aria props and already handle both the checkbox behaviour and the corresponding CSS data attributes. + + **Migration:** + Replace any usage of the `selected` and `indeterminate` props on `Checkbox` with the `isSelected` and `isIndeterminate` props. Note that the checked state and related CSS data attributes (such as `data-selected` and `data-indeterminate`) are now driven by React Aria, so any custom logic that previously inspected or set these via the old props should instead rely on the React Aria-managed state and attributes exposed through the new props. + + **Affected components:** Checkbox + +### Patch Changes + +- 04d9d8d: Added `List` and `ListRow` components. These provide a standalone, accessible list of interactive rows built on top of React Aria's `GridList` and `GridListItem` primitives. Rows support icons, descriptions, actions, menus, and single or multiple selection modes. + + **Affected components:** List, ListRow + +- a1f4bee: Made Accordion a `bg` provider so nested components like Button auto-increment their background level. Updated `useDefinition` to resolve `bg` `propDef` defaults for provider components. + +- db92751: Added interactive support to the `Card` component. Pass `onPress` to make the entire card surface pressable, or `href` to make it navigate to a URL. A transparent overlay handles the interaction while nested buttons and links remain independently clickable. + +- 12d8afe: Added analytics capabilities to the component library. Components with navigation behavior (Link, ButtonLink, Tab, MenuItem, Tag, Row) now fire analytics events on click when a `BUIProvider` is present. + + New exports: `BUIProvider`, `useAnalytics`, `getNodeText`, and associated types (`AnalyticsTracker`, `UseAnalyticsFn`, `BUIProviderProps`, `AnalyticsEventAttributes`). + + Components with analytics support now accept a `noTrack` prop to suppress event firing. + + **Affected components:** Link, ButtonLink, Tab, MenuItem, Tag, Row + +- b838cc9: Added a `loading` prop and `data-loading` data attribute to `TableRoot`, allowing consumers to distinguish between stale data and initial loading states. Both `stale` and `loading` set `aria-busy` on the table. + + Affected components: TableRoot + +- 690786f: Improved the `Table` component loading state to show a skeleton UI with visible headers instead of plain "Loading..." text. The table now renders its full structure during loading, with animated skeleton rows in place of data. The loading state includes proper accessibility support with `aria-busy` on the table and screen reader announcements. + + Affected components: Table + +- 58224d3: Fixed neutral-1 hover & pressed state in light mode. + +- 95702ab: Migrated all components from `useStyles` to `useDefinition` hook. Exported `OwnProps` types for each component, enabling better type composition for consumers. + + **Affected components:** Avatar, Checkbox, Container, Dialog, FieldError, FieldLabel, Flex, FullPage, Grid, HeaderPage, Link, Menu, PasswordField, PluginHeader, Popover, RadioGroup, SearchField, Select, Skeleton, Switch, Table, TablePagination, Tabs, TagGroup, Text, TextField, ToggleButton, ToggleButtonGroup, Tooltip, VisuallyHidden + +- 430d5ed: Fixed interactive cards so that CardBody can scroll when the card has a constrained height. Previously, the overlay element blocked scroll events. + + **Affected components:** Card + +- 4c2c350: Removed the `transition` on `Container` padding to prevent an unwanted animation when the viewport is resized. + + Affected components: Container + +- e0b7eb0: Fixed --bui-fg-success token in light mode to be more accessible. + +- ad7c883: Deprecated the `HeaderPage` component name in favor of `Header`. The old `HeaderPage`, `HeaderPageProps`, `HeaderPageOwnProps`, `HeaderPageBreadcrumb`, and `HeaderPageDefinition` exports are still available as deprecated aliases. + +- 0ebde15: Added documentation for the table cell wrapper requirement to TSDoc comments for `Cell`, `CellText`, `CellProfile`, `ColumnConfig`, and `RowRenderFn`. + +- d9d2dd6: Added `SearchAutocomplete` and `SearchAutocompleteItem` components for building accessible search-with-results patterns. Built on React Aria's Autocomplete with keyboard navigation and screen reader support. Designed for async/external search results with a configurable popover width. + + **Affected components:** SearchAutocomplete, SearchAutocompleteItem + +- a6b84e1: Made Checkbox `children` optional and added a dev warning when neither a visible label, `aria-label`, nor `aria-labelledby` is provided. The label wrapper div is no longer rendered when there are no children, removing the unnecessary gap. + + **Affected components:** Checkbox + +- b99f6d5: Fixed `Dialog` content overflowing when no `height` prop is set. The dialog now grows with its content and scrolls when content exceeds the viewport height. + + **Affected components**: Dialog + +- 2f581de: Fixed focus ring styles to use React Aria's `[data-focus-visible]` data attribute instead of the native CSS `:focus-visible` pseudo-class. This ensures keyboard focus rings render reliably when focus is managed programmatically by React Aria (e.g. inside a GridList, Menu, or Select). + + **Affected components:** Accordion, Button, ButtonIcon, ButtonLink, Card, List, Menu, Select, ToggleButtonGroup + +- 17d6398: Fixed incorrect bottom spacing caused by `Container` using `padding-bottom` for its default bottom spacing. Changed to `margin-bottom` and prevented it from applying when `Container` is used as the `Header` root element. + + **Affected components:** Container, Header + +- 2e5c651: Fixed `PluginHeader` to avoid triggering `ResizeObserver loop completed with undelivered notifications` warnings when used in layouts that react to the header height, such as pages that use `FullPage`. + + **Affected components:** PluginHeader + +- d4fa5b4: Fixed tab `matchStrategy` matching to ignore query parameters and hash fragments in tab `href` values. Previously, tabs with query params in their `href` (e.g., `/page?group=foo`) would never show as active since matching compared the full `href` string against `location.pathname` which never includes query params. + + **Affected components:** Tabs, PluginHeader + +- bc42b60: Fixed Table component to use current `--bui-bg-neutral-1` tokens instead of the removed `--bui-bg-tint` tokens, restoring row hover, selected, pressed, and disabled background colors. + +- 9314ff5: Fixed a bug in the `useTable` hook where the loading skeleton was never shown for `complete` mode when using `getData`. The initial data state was an empty array instead of `undefined`, causing the `Table` component to skip the loading state. + +- f42f4cc: Fixed Table column headers overflowing and wrapping when there is not enough space. Headers now truncate with ellipsis instead. + + **Affected components:** Table + +- 1f9682b: Fixed Table row hover, selected, pressed, and disabled background states to use the correct neutral token level based on the container background. + + **Affected components:** Table + +- fbd5c5a: Fixed Table rows showing a pointer cursor when not interactive. Rows now only show `cursor: pointer` when they have an `href`, are selectable, or are pressable. + + **Affected components:** Table + +- 612c217: Fixed `Table` rows with external `href` values to open in a new tab by automatically applying `target="_blank"` and `rel="noopener noreferrer"`. + + **Affected components**: Table + +- 545129a: Updated Table selection checkboxes to use `aria-label` instead of empty fragment children, improving accessibility and removing the unnecessary label gap in the selection cells. + + **Affected components:** Table + +- 36987db: Fixed handling of the `style` prop on `Button`, `ButtonIcon`, and `ButtonLink` so that it is now correctly forwarded to the underlying element instead of being silently dropped. + + **Affected components:** Button, ButtonIcon, ButtonLink + +- 95702ab: Fixed Link variant default from `'body'` to `'body-medium'` to match actual CSS selectors. The previous default did not correspond to a valid variant value. + + **Affected components:** Link + +- 9027b10: Fixed scroll overflow in Menu and Select popover content when constrained by viewport height. + + **Affected components:** Menu, Select + +- 7960d54: Added support for native HTML div attributes on the `Flex`, `Grid`, and `Grid.Item` components. + + **Affected components:** Flex, Grid, Grid.Item + +- 0559408: Added `virtualized` prop to `Table` component for virtualized rendering of large datasets. Accepts `true` for default row height, `{ rowHeight: number }` for fixed height, or `{ estimatedRowHeight: number }` for variable height rows. + +- 8909359: Fixed focus-visible outline styles for Menu and Select components. + + **Affected components:** Menu, Select + +- 12d8afe: Fixed MenuItem `onAction` prop ordering so user-provided `onAction` handlers are chained rather than silently overwritten. + +- aa29b50: Pages created with `PageBlueprint` now render the plugin header by default in the new frontend system. + +- bb66b86: The `Select` trigger now automatically adapts its background colour based on the parent background context. + + **Affected components:** Select + +- 4105a78: Merged the internal `PluginHeaderToolbar` component into `PluginHeader`, removing the separate component and its associated types (`PluginHeaderToolbarOwnProps`, `PluginHeaderToolbarProps`) and definition (`PluginHeaderToolbarDefinition`). This is an internal refactor with no changes to the public API of `PluginHeader`. + + **Affected components:** PluginHeader + +- 9599697: Updated dependency `globals` to `^17.0.0`. + +- 0f462f8: Improved type safety in `useDefinition` by centralizing prop resolution and strengthening the `BgPropsConstraint` to require that `bg` provider components declare `children` as a required prop in their OwnProps type. + +- 8909359: Added proper cursor styles for RadioGroup items. + + **Affected components:** RadioGroup + +- fcaac3b: Fixed `Card` interactive cards not firing the `onPress` handler when clicking the card surface. + + **Affected components**: Card + +- b303857: Fixed `isRequired` prop not being passed to the underlying React Aria field components in TextField, SearchField, and PasswordField. Previously, `isRequired` was consumed locally for the secondary label text but never forwarded, which meant the input elements lacked `aria-required="true"` and React Aria's built-in required validation was not activated. + + **Affected components:** TextField, SearchField, PasswordField + +- 934ac03: `SearchField` and `TextField` now automatically adapt their background color based on the parent bg context, stepping up one neutral level (e.g. neutral-1 → neutral-2) when placed on a neutral background. `TextField` also gains a focus ring using the `--bui-ring` token. + + **Affected components:** SearchField, TextField + +- cd3cb0f: Improved `useBreakpoint` performance by sharing a single set of `matchMedia` listeners across all component instances instead of creating independent listeners per hook call. + +- 36987db: Extended `AlertProps`, `ContainerProps`, `DialogBodyProps`, and `FieldLabelProps` with native div element props to allow passing attributes like `aria-*` and `data-*`. + + **Affected components:** Alert, Container, DialogBody, FieldLabel + +## @backstage/plugin-catalog-backend@3.5.0 + +### Minor Changes + +- a6b2819: Added `query-catalog-entities` action to the catalog backend actions registry. Supports predicate-based filtering with `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. + +- 972f686: Added support for predicate-based filtering on the `/entities/by-refs` endpoint via the `query` field in the request body. Supports `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. + +- 5d95e8e: Add an `onConflict` option to location creation that can refresh an existing location instead of throwing a conflict error. + +- 56c908e: Added support for predicate-based filtering on the `/entity-facets` endpoint via a new `POST` method. Supports `$all`, `$any`, `$not`, `$exists`, `$in`, `$contains`, and `$hasPrefix` operators. + +- 0fbcf23: Migrated OpenAPI schemas to 3.1. + +- bf71677: Added opentelemetry metrics for SCM events: + + - `catalog.events.scm.messages` with attribute `eventType`: Counter for the number of SCM events actually received by the catalog backend. The `eventType` is currently either `location` or `repository`. + +- 51e23eb: Added predicate-based entity filtering via POST /entities/by-query endpoint. + + Supports `$all`, `$any`, `$not`, `$exists`, `$in`, `$hasPrefix`, and (partially) `$contains` operators for expressive entity queries. Integrated into the existing `queryEntities` flow with full cursor-based pagination, permission enforcement, and `totalItems` support. + + The catalog client's `queryEntities()` method automatically routes to the POST endpoint when a `query` predicate is provided. + +### Patch Changes + +- a91bd1b: Improved catalog entity deletion so parent invalidation and deferred relation restitch scheduling are coordinated more safely. + +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 + +- 7416e8b: Moved stitch queue concerns out of `refresh_state` and `final_entities` into a dedicated `stitch_queue` table with `entity_ref` as the primary key. The `stitch_ticket` is used for optimistic concurrency control. When a stitch completes successfully and the ticket hasn't changed, the corresponding row is deleted from the queue. The migration handles existing data and is fully reversible. + +- fbf382f: Minor internal optimisation + +- 1ee5b28: Migrates existing catalog metrics to use the alpha MetricsService. This release is a 1:1 migration with no breaking changes. + +- 72747b4: Deprecated two processors as they have been moved to the Community Plugins repo with their own backend modules: + + - `AnnotateScmSlugEntityProcessor`: Use `@backstage-community/plugin-catalog-backend-module-annotate-scm-slug` instead + - `CodeOwnersProcessor`: Use `@backstage-community/plugin-catalog-backend-module-codeowners` instead + +- 3644b72: Make the `search` foreign key catalog migration non-blocking on large tables by using batch deletes and PostgreSQL `NOT VALID`/`VALIDATE` to reduce lock duration + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +- 3181973: Changed the `search` table foreign key to point to `final_entities` instead of `refresh_state` + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/filter-predicates@0.1.1 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/catalog-model@1.7.7 + - @backstage/backend-openapi-utils@0.6.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-github@0.13.0 + +### Minor Changes + +- b11c2cd: The default user transformer now prefers organization verified domain emails over the user's public GitHub email when populating the user entity profile. It also strips plus-addressed routing tags that GitHub adds to these emails. + + If you want to retain the old behavior, you can do so with a custom user transformer using the `githubOrgEntityProviderTransformsExtensionPoint`: + + ```ts + import { createBackendModule } from '@backstage/backend-plugin-api'; + import { githubOrgEntityProviderTransformsExtensionPoint } from '@backstage/plugin-catalog-backend-module-github-org'; + import { defaultUserTransformer } from '@backstage/plugin-catalog-backend-module-github'; + + export default createBackendModule({ + pluginId: 'catalog', + moduleId: 'github-org-custom-transforms', + register(env) { + env.registerInit({ + deps: { + transforms: githubOrgEntityProviderTransformsExtensionPoint, + }, + async init({ transforms }) { + transforms.setUserTransformer(async (item, ctx) => { + const entity = await defaultUserTransformer(item, ctx); + if (entity && item.email) { + entity.spec.profile!.email = item.email; + } + return entity; + }); + }, + }); + }, + }); + ``` + +### Patch Changes + +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 + +- 106d1b2: Added a `defaultUserTransformer.useVerifiedEmails` config option for the `githubOrg` provider. When set to `true`, the default user transformer prefers organization verified domain emails over the user's public GitHub email. Defaults to `false`, which uses only the public GitHub email. + + This option has no effect when a custom user transformer is set via the `githubOrgEntityProviderTransformsExtensionPoint`. + + ```yaml + catalog: + providers: + githubOrg: + production: + githubUrl: https://github.com + orgs: + - my-org + defaultUserTransformer: + useVerifiedEmails: true + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-graph@0.6.0 + +### Minor Changes + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-node@2.1.0 + +### Minor Changes + +- bf71677: Added the ability for SCM events subscribers to mark the fact that they have taken actions based on events, which produces output metrics: + + - `catalog.events.scm.actions` with attribute `action`: Counter for the number of actions actually taken by catalog internals or other subscribers, based on SCM events. The `action` is currently either `create`, `delete`, `refresh`, or `move`. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-test-utils@1.11.1 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-react@2.1.0 + +### Minor Changes + +- c548a0f: Added `EntityDataTable`, `EntityRelationCard`, `entityDataTableColumns`, `entityColumnPresets`, and related types as alpha exports. These replace `EntityTable` and `RelatedEntitiesCard` (from `@backstage/plugin-catalog`) respectively, providing a unified BUI-based pattern for entity table cards. +- 4d58894: Added `aliases` and `contentOrder` fields to `EntityContentGroupDefinition`, allowing groups to declare alias IDs and control the sort order of their content items. +- d14b6e0: Exported `useEntityRefLink` hook that returns a function for generating entity page URLs from entity references. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- c6080eb: Added `EntityInfoCard` component to `@backstage/plugin-catalog-react` as a BUI-based card wrapper for entity page cards. + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/frontend-test-utils@0.5.1 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/filter-predicates@0.1.1 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + +## @backstage/plugin-devtools-react@0.2.0 + +### Minor Changes + +- f4a1edd: Removed the deprecated `DevToolsContentBlueprint` from `@backstage/plugin-devtools-react`. DevTools pages in the new frontend system now use `SubPageBlueprint` tabs instead, and the catalog unprocessed entities alpha extension now attaches to DevTools as a subpage. + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-events-backend@0.6.0 + +### Minor Changes + +- 0fbcf23: Migrated OpenAPI schemas to 3.1. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-openapi-utils@0.6.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-notifications-backend-module-slack@0.4.0 + +### Minor Changes + +- cd62d78: **BREAKING**: Only send direct messages to user entity recipients. Notifications sent to non-user entities no longer send Slack direct messages to resolved users. +- 749ba60: Add an extension for custom Slack message layouts + +### Patch Changes + +- e7c6c32: The Slack notification processor now uses the `MetricsService` to create metrics, providing plugin-scoped attribution. `{message}` unit has also been added. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-notifications-node@0.2.24 + +## @backstage/plugin-org@0.7.0 + +### Minor Changes + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +- 5fc35bb: Migrated `EntityAboutCard`, `EntityLinksCard`, `EntityLabelsCard`, `GroupProfileCard`, and `UserProfileCard` from MUI/InfoCard to use the new BUI card layout and BUI components where possible. + + **BREAKING**: Removed `variant` prop from EntityAboutCard, EntityUserProfileCard, EntityGroupProfileCard, EntityLabelsCard, EntityLinksCard. Removed `gridSizes` prop from `AboutField`. + + **Migration:** + + Simply delete the obsolete `variant` and `gridSizes` props, e.g: + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-scaffolder@1.36.0 + +### Minor Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. + +### Patch Changes + +- e27bd4e: Removed check for deprecated `bitbucket` integration from `repoPickerValidation` function used by the `RepoUrlPicker`, it now validates the `bitbucketServer` and `bitbucketCloud` integrations instead. +- 538c985: Updated installation documentation to use feature discovery as the default. +- bd5b842: Added a new `ui:autoSelect` option to the EntityPicker field that controls whether an entity is automatically selected when the field loses focus. When set to `false`, the field will remain empty if the user closes it without explicitly selecting an entity, preventing unintentional selections. Defaults to `true` for backward compatibility. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-scaffolder-react@1.20.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-techdocs-react@1.3.9 + +## @backstage/plugin-scaffolder-backend@3.2.0 + +### Minor Changes + +- c9b11eb: Added a new `list-scaffolder-tasks` action that allows querying scaffolder tasks with optional ownership filtering and pagination support +- 1b42218: Adds a new `get-scaffolder-task-logs` action to `@backstage/plugin-scaffolder-backend` that retrieves log events for a given scaffolder task, with optional support for retrieving only new events after a given event ID. +- 0fbcf23: Migrated OpenAPI schemas to 3.1. +- 7695dd2: Added a new `list-scaffolder-actions` action that returns all installed scaffolder actions with their schemas and examples +- e8736ea: Added secrets schema validation for task creation, retry, and dry-run endpoints. When a template defines `spec.secrets.schema`, the API validates provided secrets against the schema and returns a `400` error if validation fails. + +### Patch Changes + +- e27bd4e: Removed `@backstage/plugin-scaffolder-backend-module-bitbucket` from `package.json` as the package itself has been deprecated and the code deleted. +- 4f5ed06: Fixed a security vulnerability where server-configured environment secrets were exposed through the scaffolder dry-run endpoint. +- 30ff981: Fixed a security vulnerability where secrets could bypass log redaction when transformed through Nunjucks filters in scaffolder templates. +- 4e39e63: Removed unused dependencies +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- ccc20cf: create scaffolder MCP action to dry run a provided scaffolder template +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/catalog-model@1.7.7 + - @backstage/backend-openapi-utils@0.6.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-scaffolder-node@0.13.0 + +### Minor Changes + +- e27bd4e: **BREAKING** Removed deprecated `bitbucket` integration from being used in the `parseRepoUrl` function. It will use the `bitbucketCloud` or `bitbucketServer` integrations instead. + +### Patch Changes + +- cd0ecc5: Added `removeFiles` helper function for staging file removals in Git. +- f598909: Added `scaffolderServiceRef` and `ScaffolderService` interface for backend plugins that need to interact with the scaffolder API using `BackstageCredentials` instead of raw tokens. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-test-utils@1.11.1 + - @backstage/integration@2.0.0 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-scaffolder-react@1.20.0 + +### Minor Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- 470f72d: The `LogViewer` component from `@backstage/core-components` now supports downloading logs if a callback is passed to `onDownloadLogs` + +### Patch Changes + +- 004b5c1: Added back `formFieldsApiRef` and `ScaffolderFormFieldsApi` as alpha exports. +- bd31ddd: Updated dependency `flatted` to `3.3.4`. +- f598909: Added `scaffolderApiMock` test utility, exported from `@backstage/plugin-scaffolder-react/testUtils`. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/frontend-test-utils@0.5.1 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-search@1.7.0 + +### Minor Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. + +### Patch Changes + +- d5eb954: Fixes the search component not registering the first search on navigate to the search page. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-search-react@1.11.0 + +## @backstage/plugin-search-backend@2.1.0 + +### Minor Changes + +- 0fbcf23: Migrated OpenAPI schemas to 3.1. + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/backend-openapi-utils@0.6.7 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-react@1.11.0 + +### Minor Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. + +### Patch Changes + +- d5eb954: Fixes the search component not registering the first search on navigate to the search page. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/app-defaults@1.7.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-permission-react@0.4.41 + +## @backstage/backend-openapi-utils@0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + +## @backstage/backend-test-utils@1.11.1 + +### Patch Changes + +- dee4283: Added `pluginId` field to `ActionsServiceAction` type, populated from the registering plugin's metadata. +- 164711a: Added `cancelTask` to `MockSchedulerService` and mock scheduler service factory. +- 62f0a53: Fixed error forwarding in the actions registry so that known errors like `InputError` and `NotFoundError` thrown by actions preserve their original status codes and messages instead of being wrapped in `ForwardedError` and coerced to 500. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 1ee5b28: Adds a new metrics service mock to be leveraged in tests +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/backend-app-api@1.6.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/catalog-model@1.7.7 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +## @backstage/cli-module-actions@0.0.1 + +### Patch Changes + +- 42960f1: Added `actions` CLI module for listing and executing actions from the distributed actions registry. Includes `actions list`, `actions execute`, and `actions sources` commands for managing plugin sources. +- Updated dependencies + - @backstage/cli-node@0.3.0 + +## @backstage/codemods@0.1.55 + +### Patch Changes + +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- de62a9d: Upgraded `commander` dependency from `^12.0.0` to `^14.0.3` across all CLI packages. +- Updated dependencies + - @backstage/cli-common@0.2.0 + +## @backstage/config-loader@1.10.9 + +### Patch Changes + +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- Updated dependencies + - @backstage/cli-common@0.2.0 + +## @backstage/core-app-api@1.19.6 + +### Patch Changes + +- 12d8afe: Added `BUIProvider` from `@backstage/ui` to the app shell provider tree, enabling BUI components to fire analytics events through the Backstage analytics system. +- 59752a2: Deprecated `AlertApiForwarder` in favor of the new `ToastApi`. The `AlertApiForwarder` now emits a console warning on first use, guiding developers to migrate to `ToastApi` from `@backstage/frontend-plugin-api`. +- 0452d02: Add optional `description` field to plugin-level feature flags. +- 42f8c9b: Added `BUIProvider` inside the legacy app router to enable client-side routing for all BUI components. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + +## @backstage/core-compat-api@0.5.9 + +### Patch Changes + +- b15a685: Added `withApis`, which is a Higher-Order Component for providing APIs as props to a component via `useApiHolder`. +- 8e09233: Added a missing dependency on `@backstage/filter-predicates` to `@backstage/core-compat-api`. This fixes package metadata for consumers that use compatibility helpers relying on filter predicate support. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-app-react@0.2.1 + - @backstage/filter-predicates@0.1.1 + +## @backstage/core-components@0.18.8 + +### Patch Changes + +- e26e3de: The login request dialog now handles auth provider icons passed as `IconElement` in addition to `IconComponent`. +- 8e09233: Fixed the shared `Progress` component to provide an accessible name for its loading indicator by default. +- 8b1a847: Fixed Table component layout when both `filters` and `title` props are used together. The filter controls now use a dedicated CSS class (`filterControls`) instead of incorrectly reusing the root container class. +- 3f36ce1: Clarified the `IconElement` sizing contract for the new frontend system and aligned legacy system icon rendering with the new icon API. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 470f72d: The `LogViewer` component from `@backstage/core-components` now supports downloading logs if a callback is passed to `onDownloadLogs` +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + +## @backstage/core-plugin-api@1.12.4 + +### Patch Changes + +- d911b72: Updated `createApiRef` to preserve the direct config call without deprecation warnings while staying compatible with the new frontend API ref typing. +- 59752a2: Deprecated `AlertApi`, `AlertMessage`, and `alertApiRef` in favor of the new `ToastApi` from `@backstage/frontend-plugin-api`. +- 0452d02: Add optional `description` field to plugin-level feature flags. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- fe848e0: Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/dev-utils@1.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/core-app-api@1.19.6 + - @backstage/catalog-model@1.7.7 + - @backstage/app-defaults@1.7.6 + - @backstage/integration-react@1.2.16 + +## @backstage/eslint-plugin@0.2.2 + +### Patch Changes + +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 + +## @backstage/filter-predicates@0.1.1 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +## @backstage/frontend-dynamic-feature-loader@0.1.10 + +### Patch Changes + +- e8ba654: Update the README of the `frontend-dynamic-feature-loader` package to mention the new `backstage-cli package bundle` command. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/module-federation-common@0.1.2 + +## @backstage/frontend-test-utils@0.5.1 + +### Patch Changes + +- b56f573: Deprecated standalone mock API exports in favor of the `mockApis` namespace. This includes the mock classes (`MockAlertApi`, `MockAnalyticsApi`, `MockConfigApi`, `MockErrorApi`, `MockFetchApi`, `MockFeatureFlagsApi`, `MockPermissionApi`, `MockStorageApi`, `MockTranslationApi`), their option types (`MockErrorApiOptions`, `MockFeatureFlagsApiOptions`), and the `ErrorWithContext` type. `MockFetchApiOptions` is kept as a non-deprecated export. Use the `mockApis` namespace instead, for example `mockApis.alert()` or `mockApis.alert.mock()`. +- 479282f: Fixed type inference of `TestApiPair` when using tuple syntax by wrapping `MockWithApiFactory` in `NoInfer`. +- 8e09233: Added a missing dependency on `@backstage/filter-predicates` to `@backstage/frontend-test-utils`. This fixes package metadata for consumers using the frontend test app helpers with predicate-based behavior. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 909c742: Switched `MockTranslationApi` and related test utility imports from `@backstage/core-plugin-api/alpha` to the stable `@backstage/frontend-plugin-api` export. The `TranslationApi` type in the API report is now sourced from a single package. This has no effect on runtime behavior. +- Updated dependencies + - @backstage/frontend-app-api@0.16.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-app@0.4.1 + - @backstage/plugin-app-react@0.2.1 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/filter-predicates@0.1.1 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/test-utils@1.7.16 + +## @backstage/integration-react@1.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/integration@2.0.0 + +## @backstage/module-federation-common@0.1.2 + +### Patch Changes + +- 0cb5646: Fixed the `@mui/material/styles` shared dependency key by removing a trailing slash that caused module resolution failures with MUI package exports. + +## @techdocs/cli@1.10.6 + +### Patch Changes + +- 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`. +- de62a9d: Upgraded `commander` dependency from `^12.0.0` to `^14.0.3` across all CLI packages. +- Updated dependencies + - @backstage/backend-defaults@0.16.0 + - @backstage/cli-common@0.2.0 + - @backstage/plugin-techdocs-node@1.14.4 + - @backstage/catalog-model@1.7.7 + +## @backstage/test-utils@1.7.16 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-permission-common@0.9.7 + +## @backstage/plugin-api-docs@0.13.5 + +### Patch Changes + +- 9c9d425: Fixed invisible text in parameter input fields when using dark mode in OpenAPI definition pages +- 538c985: Updated installation documentation to use feature discovery as the default. +- 30e08df: Added default entity content groups for the API docs entity content tabs. The API definition tab defaults to the `documentation` group and the APIs tab defaults to the `development` group. +- c548a0f: Migrated entity table cards (`ConsumedApisCard`, `ProvidedApisCard`, `HasApisCard`, `ConsumingComponentsCard`, `ProvidingComponentsCard`) to use BUI when no legacy props are passed. The old `variant`, `columns`, and `tableOptions` props are deprecated but still supported — passing any of them triggers the legacy MUI-based rendering. The new `columnConfig` prop accepts `EntityColumnConfig[]` for BUI-based rendering. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- ca277ef: Updated dependency `graphiql` to `3.9.0` to address security vulnerability in `markdown-it` package. + Updated dependency `@graphiql/react` to `0.29.0` to match the version used by `graphiql`. + Moved dependency `graphql-config` to `devDependencies` as it is needed only for types. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-catalog@2.0.0 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-app@0.4.1 + +### Patch Changes + +- 5f3f5d2: `NavContentBlueprint` nav item collections now keep previously collected `rest()` results in sync when additional items are taken later in the same render, making it easier to place items across multiple sidebar sections. + +- aa29b50: Pages created with `PageBlueprint` now render the plugin header by default in the new frontend system. + +- c0ab376: The app nav now falls back to `plugin.icon` for navigation items that don't have an explicit icon set. + +- 12d8afe: Added `BUIProvider` from `@backstage/ui` to the app root, enabling BUI components to fire analytics events through the Backstage analytics system. + +- 5fec07d: Updated the default app root to better support phased app preparation by allowing the app layout to be absent during bootstrap, routing bootstrap failures through the app root boundary, and avoiding installation of a guest identity in protected apps that do not provide a sign-in page. + +- 9508514: Updated the default `PluginWrapperApi` implementation to support the new `useWrapperValue` hook and root wrapper. The root wrapper is now rendered in the app root to manage shared hook state across plugin wrapper instances. + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +- 42f8c9b: Moved `BUIProvider` inside the app router to enable automatic client-side routing for all BUI components. + +- 909c742: Switched translation API imports (`translationApiRef`, `appLanguageApiRef`) from the alpha `@backstage/core-plugin-api/alpha` path to the stable `@backstage/frontend-plugin-api` export. This has no effect on runtime behavior. + +- 7e743f4: Introduced a new `ToastApi` for displaying rich toast notifications in the new frontend system. + + The new `ToastApi` provides enhanced notification capabilities compared to the existing `AlertApi`: + + - **Title and Description**: Toasts support both a title and an optional description + - **Custom Timeouts**: Each toast can specify its own timeout duration + - **Links**: Toasts can include action links + - **Status Variants**: Support for neutral, info, success, warning, and danger statuses + - **Programmatic Dismiss**: Toasts can be dismissed programmatically using the `close()` handle returned from `post()` + + **Usage:** + + ```typescript + import { toastApiRef, useApi } from '@backstage/frontend-plugin-api'; + + const toastApi = useApi(toastApiRef); + + // Full-featured toast + toastApi.post({ + title: 'Entity saved', + description: 'Your changes have been saved successfully.', + status: 'success', + timeout: 5000, + links: [{ label: 'View entity', href: '/catalog/entity' }], + }); + + // Programmatic dismiss + const { close } = toastApi.post({ title: 'Uploading...', status: 'info' }); + // Later... + close(); + ``` + + The `ToastDisplay` component subscribes to both `ToastApi` and `AlertApi`, providing a migration path where both systems work side by side until `AlertApi` is fully deprecated. + +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-app-react@0.2.1 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/filter-predicates@0.1.1 + - @backstage/integration-react@1.2.16 + +## @backstage/plugin-app-backend@0.5.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/config-loader@1.10.9 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/plugin-app-node@0.1.43 + +## @backstage/plugin-app-node@0.1.43 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/config-loader@1.10.9 + +## @backstage/plugin-app-react@0.2.1 + +### Patch Changes + +- 5f3f5d2: `NavContentBlueprint` nav item collections now keep previously collected `rest()` results in sync when additional items are taken later in the same render, making it easier to place items across multiple sidebar sections. +- 2c383b5: Added `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory`, migrated from `@backstage/frontend-plugin-api`. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-app-visualizer@0.2.1 + +### Patch Changes + +- c25532a: Switched dev entry point to use `createDevApp` from `@backstage/frontend-dev-utils`. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-auth@0.1.6 + +### Patch Changes + +- 06294aa: Migrated the ConsentPage UI from Material-UI and `@backstage/core-components` to `@backstage/ui`. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-auth-backend@0.27.2 + +### Patch Changes + +- 1ccad86: Added `who-am-i` action to the auth backend actions registry. Returns the catalog entity and user info for the currently authenticated user. +- d0f4cd2: Added optional client metadata document endpoint at `/.well-known/oauth-client/cli.json` relative to the auth backend base URL for CLI authentication. Enabled when `auth.experimentalClientIdMetadataDocuments.enabled` is set to `true`. +- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1 +- e9b6e97: Fixed a security vulnerability where the CIMD metadata fetch could follow HTTP redirects to internal hosts, bypassing SSRF protections. +- 0f9d673: Improved redirect URI validation in the experimental OIDC provider to match against normalized URLs rather than raw strings. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 634eded: Fixed a foreign key constraint violation when issuing refresh tokens for CIMD clients, and + prevented a failed refresh token issuance from failing the entire token exchange. + Fixed AWS ALB auth provider incorrectly returning HTTP 500 instead of 401 for JWT validation failures, + which caused retry loops and memory pressure under load. +- 619be54: Update migrations to be reversible +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.14 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- 634eded: Fixed a foreign key constraint violation when issuing refresh tokens for CIMD clients, and + prevented a failed refresh token issuance from failing the entire token exchange. + Fixed AWS ALB auth provider incorrectly returning HTTP 500 instead of 401 for JWT validation failures, + which caused retry loops and memory pressure under load. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-backend@0.27.2 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.18 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-github-provider@0.5.1 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.4.1 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.18 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.14 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-backend@0.27.2 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.13 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-openshift-provider@0.1.5 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-auth-node@0.6.14 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-auth-react@0.1.25 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + +## @backstage/plugin-bitbucket-cloud-common@0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@2.0.0 + +## @backstage/plugin-catalog-backend-module-aws@0.4.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-azure@0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/backend-openapi-utils@0.6.7 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-bitbucket-cloud-common@0.3.8 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.20 + +### Patch Changes + +- 106d1b2: Added a `defaultUserTransformer.useVerifiedEmails` config option for the `githubOrg` provider. When set to `true`, the default user transformer prefers organization verified domain emails over the user's public GitHub email. Defaults to `false`, which uses only the public GitHub email. + + This option has no effect when a custom user transformer is set via the `githubOrgEntityProviderTransformsExtensionPoint`. + + ```yaml + catalog: + providers: + githubOrg: + production: + githubUrl: https://github.com + orgs: + - my-org + defaultUserTransformer: + useVerifiedEmails: true + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-backend-module-github@0.13.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-gitlab@0.8.1 + +### Patch Changes + +- d933f62: Add configurable throttling and retry mechanism for GitLab integration. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.8.1 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.10 + +### Patch Changes + +- 5f1e7b8: Migrated metrics from direct `@opentelemetry/api` usage to the alpha `MetricsService`, providing plugin-scoped metric attribution. The `@opentelemetry/api` dependency has been removed. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/plugin-catalog-backend@3.5.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-ldap@0.12.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-logs@0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-backend@3.5.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-catalog-backend-module-msgraph@0.9.1 + +### Patch Changes + +- 97eaecf: Fixed scheduler task remaining stuck in running state after pod termination by propagating AbortSignal into MicrosoftGraphOrgEntityProvider.read() +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-scaffolder-common@2.0.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-catalog-import@0.13.11 + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.27 + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- f4a1edd: Removed the deprecated `DevToolsContentBlueprint` from `@backstage/plugin-devtools-react`. DevTools pages in the new frontend system now use `SubPageBlueprint` tabs instead, and the catalog unprocessed entities alpha extension now attaches to DevTools as a subpage. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-config-schema@0.1.78 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + +## @backstage/plugin-devtools@0.1.37 + +### Patch Changes + +- afabb37: Fixed URL encoding of task IDs for the trigger feature (tasks that contained a "/" in their ID were not triggered) +- f80195e: Added `cancelScheduledTask` to the DevTools API and a cancel button to the scheduled tasks UI. +- 538c985: Updated installation documentation to use feature discovery as the default. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- f4a1edd: Removed the deprecated `DevToolsContentBlueprint` from `@backstage/plugin-devtools-react`. DevTools pages in the new frontend system now use `SubPageBlueprint` tabs instead, and the catalog unprocessed entities alpha extension now attaches to DevTools as a subpage. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-devtools-common@0.1.23 + - @backstage/plugin-permission-react@0.4.41 + +## @backstage/plugin-devtools-backend@0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/cli-common@0.2.0 + - @backstage/plugin-devtools-common@0.1.23 + - @backstage/config-loader@1.10.9 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + +## @backstage/plugin-devtools-common@0.1.23 + +### Patch Changes + +- f80195e: Added `cancelScheduledTask` to the DevTools API and a cancel button to the scheduled tasks UI. +- Updated dependencies + - @backstage/plugin-permission-common@0.9.7 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-azure@0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-gerrit@0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-github@0.4.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-gitlab@0.3.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-google-pubsub@0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/filter-predicates@0.1.1 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-module-kafka@0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-backend-test-utils@0.1.53 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-events-node@0.4.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + +## @backstage/plugin-gateway-backend@1.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + +## @backstage/plugin-home@0.9.3 + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-client@1.14.0 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-home-react@0.1.36 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-home-react@0.1.36 + +### Patch Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/core-compat-api@0.5.9 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-kubernetes@0.12.17 + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-kubernetes-react@0.5.17 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-kubernetes-backend@0.21.2 + +### Patch Changes + +- 6b6b5de: Added `endpointType` config option to the GKE cluster locator, allowing use of DNS-based control plane endpoints instead of public IP endpoints. Set `endpointType: 'dns'` to use GKE DNS endpoints (e.g. `gke-..gke.goog`) which provide proper TLS certificates and IAM-based access control. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-kubernetes-node@0.4.2 + +## @backstage/plugin-kubernetes-cluster@0.0.35 + +### Patch Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-kubernetes-react@0.5.17 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-kubernetes-node@0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-kubernetes-react@0.5.17 + +### Patch Changes + +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-mcp-actions-backend@0.1.10 + +### Patch Changes + +- 62f0a53: Fixed error forwarding in the actions registry so that known errors like `InputError` and `NotFoundError` thrown by actions preserve their original status codes and messages instead of being wrapped in `ForwardedError` and coerced to 500. + +- dee4283: Added `mcpActions.name` and `mcpActions.description` config options to customize the MCP server identity. Namespaced tool names now use dot separator to align with the MCP spec convention. + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +- c74b697: Added support for splitting MCP actions into multiple servers via `mcpActions.servers` configuration. Each server gets its own endpoint at `/api/mcp-actions/v1/{key}` with actions scoped using include/exclude filter rules. Tool names are now namespaced with the plugin ID by default, configurable via `mcpActions.namespacedToolNames`. When `mcpActions.servers` is not configured, the plugin continues to serve a single server at `/api/mcp-actions/v1`. + +- dc81af1: Adds two new metrics to track MCP server operations and sessions. + + - `mcp.server.operation.duration`: The duration taken to process an individual MCP operation + - `mcp.server.session.duration`: The duration of the MCP session from the perspective of the server + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-catalog-node@2.1.0 + +## @backstage/plugin-mui-to-bui@0.2.5 + +### Patch Changes + +- 538c985: Updated installation documentation to use feature discovery as the default. +- ad7c883: Updated the MUI to BUI theme converter page to use the renamed `Header` component from `@backstage/ui`. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/frontend-plugin-api@0.15.0 + +## @backstage/plugin-notifications@0.5.15 + +### Patch Changes + +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-signals-react@0.0.20 + +## @backstage/plugin-notifications-backend@0.6.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-notifications-node@0.2.24 + - @backstage/plugin-signals-node@0.1.29 + +## @backstage/plugin-notifications-backend-module-email@0.3.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-notifications-node@0.2.24 + +## @backstage/plugin-notifications-node@0.2.24 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-signals-node@0.1.29 + +## @backstage/plugin-org-react@0.1.48 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/catalog-client@1.14.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-permission-backend@0.7.10 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-permission-common@0.9.7 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +## @backstage/plugin-permission-node@0.10.11 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-auth-node@0.6.14 + +## @backstage/plugin-permission-react@0.4.41 + +### Patch Changes + +- 5fec07d: Permission checks made in the same tick are now batched into a single call to the permission backend. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/plugin-permission-common@0.9.7 + +## @backstage/plugin-proxy-backend@0.6.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-proxy-node@0.1.13 + +## @backstage/plugin-proxy-node@0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.4 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.8 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-github@0.9.7 + +### Patch Changes + +- a761a48: Added optional `returnWorkflowRunDetails` input to `github:actions:dispatch` action. When true, exposes `workflowRunId`, `workflowRunUrl`, and `workflowRunHtmlUrl` as outputs using the GitHub API `return_run_details` parameter. +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- b2591f6: Fixed environment `waitTime` description incorrectly asking for milliseconds instead of minutes. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.11.4 + +### Patch Changes + +- 5730c8e: Added `maskedAndHidden` option to `gitlab:projectVariable:create` and `publish:gitlab` action to support creating GitLab project variables that are both masked and hidden. Updated gitbeaker to version 43.8.0 for proper type support. + +- 0c1726a: Added new `gitlab:group:access` scaffolder action to add or remove users and groups as members of GitLab groups. The action supports specifying members via `userIds` and/or `groupIds` array parameters, configurable access levels (Guest, Reporter, Developer, Maintainer, Owner), and defaults to the 'add' action when not specified. + +- 4b8fcf0: Added two optional inputs to the `publish:gitlab` action: + + - `settings.name`: set a custom human-readable project title that differs from the repository slug. + - `ownerUsername`: add a specific GitLab user as project owner (access level 50) of the newly created repository. Requires a privileged token in the integration configuration. + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/plugin-notifications-node@0.2.24 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.19 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/integration@2.0.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-scaffolder-node@0.13.0 + - @backstage/plugin-scaffolder-node-test-utils@0.3.9 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-test-utils@1.11.1 + - @backstage/plugin-scaffolder-node@0.13.0 + +## @backstage/plugin-search-backend-module-catalog@0.3.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-module-elasticsearch@1.8.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-module-explore@0.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-module-pg@0.5.53 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-module-techdocs@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-techdocs-node@1.14.4 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-search-backend-node@1.4.2 + +## @backstage/plugin-search-backend-node@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-permission-common@0.9.7 + +## @backstage/plugin-signals@0.0.29 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-signals-react@0.0.20 + +## @backstage/plugin-signals-backend@0.3.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-events-node@0.4.20 + - @backstage/plugin-signals-node@0.1.29 + +## @backstage/plugin-signals-node@0.1.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/plugin-events-node@0.4.20 + +## @backstage/plugin-signals-react@0.0.20 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + +## @backstage/plugin-techdocs@1.17.1 + +### Patch Changes + +- 9795d30: chore(deps): bump `dompurify` from 3.3.1 to 3.3.2 +- 30e08df: Added `documentation` as the default entity content group for the TechDocs entity content tab. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-search-react@1.11.0 + - @backstage/catalog-client@1.14.0 + - @backstage/integration@2.0.0 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-auth-react@0.1.25 + - @backstage/plugin-techdocs-react@1.3.9 + +## @backstage/plugin-techdocs-addons-test-utils@2.0.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/plugin-search-react@1.11.0 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-techdocs@1.17.1 + - @backstage/plugin-catalog@2.0.0 + - @backstage/integration-react@1.2.16 + - @backstage/test-utils@1.7.16 + - @backstage/plugin-techdocs-react@1.3.9 + +## @backstage/plugin-techdocs-backend@2.1.6 + +### Patch Changes + +- cb7c6b1: Added `techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys` configuration option to explicitly bypass MkDocs configuration key restrictions. This enables support for additional MkDocs configuration keys beyond the default safe allow list, such as the `hooks` key which some MkDocs plugins require. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/catalog-client@1.14.0 + - @backstage/plugin-techdocs-node@1.14.4 + - @backstage/integration@2.0.0 + - @backstage/plugin-catalog-node@2.1.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.34 + +### Patch Changes + +- 895563a: Avoid enabling the TechDocs LightBox addon for images wrapped in links, so image links keep working. +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/integration@2.0.0 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-techdocs-react@1.3.9 + +## @backstage/plugin-techdocs-node@1.14.4 + +### Patch Changes + +- cb7c6b1: Added `techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys` configuration option to explicitly bypass MkDocs configuration key restrictions. This enables support for additional MkDocs configuration keys beyond the default safe allow list, such as the `hooks` key which some MkDocs plugins require. +- e96f6d9: Removed `INHERIT` from the `ALLOWED_MKDOCS_KEYS` set to address a security concern with MkDocs configuration inheritance. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/integration@2.0.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-techdocs-react@1.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/catalog-model@1.7.7 + +## @backstage/plugin-user-settings@0.9.1 + +### Patch Changes + +- e26e3de: The `ProviderSettingsItem` `icon` prop now accepts `IconElement` in addition to `IconComponent`. +- 538c985: Updated installation documentation to use feature discovery as the default. +- aa29b50: New frontend system pages now use the default plugin header together with `HeaderPage` instead of the legacy core page header pattern. +- 3f36ce1: Updated alpha plugin icons to follow the new frontend icon sizing rules when rendered in plugin and navigation surfaces. +- 0be2541: Promoted the plugin's translation ref to the stable package entry point. It was previously only available through the alpha entry point. +- Updated dependencies + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/core-app-api@1.19.6 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-signals-react@0.0.20 + +## @backstage/plugin-user-settings-backend@0.4.1 + +### Patch Changes + +- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/plugin-signals-node@0.1.29 + +## example-app@0.0.33 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.36.0 + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/core-compat-api@0.5.9 + - @backstage/frontend-app-api@0.16.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/plugin-app-visualizer@0.2.1 + - @backstage/plugin-auth@0.1.6 + - @backstage/core-components@0.18.8 + - @backstage/plugin-user-settings@0.9.1 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-search-react@1.11.0 + - @backstage/plugin-search@1.7.0 + - @backstage/plugin-api-docs@0.13.5 + - @backstage/plugin-devtools@0.1.37 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-scaffolder@1.36.0 + - @backstage/plugin-techdocs@1.17.1 + - @backstage/plugin-catalog@2.0.0 + - @backstage/plugin-catalog-graph@0.6.0 + - @backstage/plugin-catalog-import@0.13.11 + - @backstage/plugin-catalog-unprocessed-entities@0.2.27 + - @backstage/plugin-home@0.9.3 + - @backstage/plugin-kubernetes@0.12.17 + - @backstage/plugin-org@0.7.0 + - @backstage/plugin-scaffolder-react@1.20.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.34 + - @backstage/plugin-app@0.4.1 + - @backstage/plugin-app-react@0.2.1 + - @backstage/plugin-notifications@0.5.15 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/frontend-defaults@0.5.0 + - @backstage/plugin-home-react@0.1.36 + - @backstage/plugin-kubernetes-cluster@0.0.35 + - @backstage/catalog-model@1.7.7 + - @backstage/app-defaults@1.7.6 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-auth-react@0.1.25 + - @backstage/plugin-signals@0.0.29 + - @backstage/plugin-techdocs-react@1.3.9 + +## app-example-plugin@0.0.33 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + +## example-app-legacy@0.2.119 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.36.0 + - @backstage/plugin-catalog-react@2.1.0 + - @backstage/ui@0.13.0 + - @backstage/frontend-app-api@0.16.0 + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + - @backstage/plugin-user-settings@0.9.1 + - @backstage/plugin-search-react@1.11.0 + - @backstage/plugin-search@1.7.0 + - @backstage/plugin-api-docs@0.13.5 + - @backstage/plugin-devtools@0.1.37 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-scaffolder@1.36.0 + - @backstage/plugin-techdocs@1.17.1 + - @backstage/plugin-catalog@2.0.0 + - @backstage/plugin-catalog-graph@0.6.0 + - @backstage/plugin-catalog-import@0.13.11 + - @backstage/plugin-catalog-unprocessed-entities@0.2.27 + - @backstage/plugin-home@0.9.3 + - @backstage/plugin-kubernetes@0.12.17 + - @backstage/plugin-mui-to-bui@0.2.5 + - @backstage/plugin-org@0.7.0 + - @backstage/plugin-scaffolder-react@1.20.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.34 + - @backstage/plugin-notifications@0.5.15 + - @backstage/plugin-permission-react@0.4.41 + - @backstage/plugin-home-react@0.1.36 + - @backstage/plugin-kubernetes-cluster@0.0.35 + - @backstage/catalog-model@1.7.7 + - @backstage/app-defaults@1.7.6 + - @backstage/integration-react@1.2.16 + - @backstage/plugin-auth-react@0.1.25 + - @backstage/plugin-signals@0.0.29 + - @backstage/plugin-techdocs-react@1.3.9 + +## example-backend@0.0.48 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 + - @backstage/backend-defaults@0.16.0 + - @backstage/plugin-catalog-backend@3.5.0 + - @backstage/plugin-auth-backend@0.27.2 + - @backstage/plugin-techdocs-backend@2.1.6 + - @backstage/plugin-scaffolder-backend-module-github@0.9.7 + - @backstage/plugin-scaffolder-backend@3.2.0 + - @backstage/plugin-mcp-actions-backend@0.1.10 + - @backstage/plugin-kubernetes-backend@0.21.2 + - @backstage/plugin-events-backend@0.6.0 + - @backstage/plugin-search-backend@2.1.0 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.5 + - @backstage/plugin-auth-backend-module-github-provider@0.5.1 + - @backstage/plugin-permission-backend@0.7.10 + - @backstage/plugin-permission-common@0.9.7 + - @backstage/plugin-permission-node@0.10.11 + - @backstage/catalog-model@1.7.7 + - @backstage/plugin-auth-node@0.6.14 + - @backstage/plugin-app-backend@0.5.12 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.17 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.12 + - @backstage/plugin-catalog-backend-module-openapi@0.2.20 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.18 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.9 + - @backstage/plugin-devtools-backend@0.5.15 + - @backstage/plugin-events-backend-module-google-pubsub@0.2.1 + - @backstage/plugin-notifications-backend@0.6.3 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.17 + - @backstage/plugin-proxy-backend@0.6.11 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.20 + - @backstage/plugin-search-backend-module-catalog@0.3.13 + - @backstage/plugin-search-backend-module-elasticsearch@1.8.1 + - @backstage/plugin-search-backend-module-explore@0.3.12 + - @backstage/plugin-search-backend-module-techdocs@0.4.12 + - @backstage/plugin-search-backend-node@1.4.2 + - @backstage/plugin-signals-backend@0.3.13 + +## @internal/cli@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.3.0 + +## e2e-test@0.2.38 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.2.0 + - @backstage/create-app@0.8.0 + +## @internal/frontend@0.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/filter-predicates@0.1.1 + +## @internal/scaffolder@0.0.19 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/plugin-scaffolder-react@1.20.0 + +## techdocs-cli-embedded-app@0.2.118 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.36.0 + - @backstage/ui@0.13.0 + - @backstage/core-components@0.18.8 + - @backstage/frontend-plugin-api@0.15.0 + - @backstage/core-app-api@1.19.6 + - @backstage/plugin-techdocs@1.17.1 + - @backstage/plugin-catalog@2.0.0 + - @backstage/plugin-app-react@0.2.1 + - @backstage/frontend-defaults@0.5.0 + - @backstage/catalog-model@1.7.7 + - @backstage/integration-react@1.2.16 + - @backstage/test-utils@1.7.16 + - @backstage/plugin-techdocs-react@1.3.9 + +## yarn-plugin-backstage@0.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.2.0 + +## @internal/plugin-todo-list@1.0.49 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.12.4 + - @backstage/core-components@0.18.8 + +## @internal/plugin-todo-list-backend@1.0.48 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0 diff --git a/docs/releases/v1.49.0-next.2-changelog.md b/docs/releases/v1.49.0-next.2-changelog.md new file mode 100644 index 0000000000..b6442fa4b0 --- /dev/null +++ b/docs/releases/v1.49.0-next.2-changelog.md @@ -0,0 +1,1826 @@ +# Release v1.49.0-next.2 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.49.0-next.2](https://backstage.github.io/upgrade-helper/?to=1.49.0-next.2) + +## @backstage/plugin-catalog@2.0.0-next.2 + +### Major Changes + +- 5fc35bb: Migrated `EntityAboutCard`, `EntityLinksCard`, `EntityLabelsCard`, `GroupProfileCard`, and `UserProfileCard` from MUI/InfoCard to use the new BUI card layout and BUI components where possible. + + **BREAKING**: Removed `variant` prop from EntityAboutCard, EntityUserProfileCard, EntityGroupProfileCard, EntityLabelsCard, EntityLinksCard. Removed `gridSizes` prop from `AboutField`. + + **Migration:** + + Simply delete the obsolete `variant` and `gridSizes` props, e.g: + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + - @backstage/plugin-search-react@1.10.5-next.1 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @backstage/backend-app-api@1.6.0-next.1 + +### Minor Changes + +- 545557a: Registration errors should be forwarded as BackendStartupResult + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/backend-plugin-api@1.8.0-next.1 + +### Minor Changes + +- 015668c: Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.2.0-next.2 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/catalog-client@1.14.0-next.2 + +### Minor Changes + +- 5d95e8e: Add an `onConflict` option to location creation that can refresh an existing location instead of throwing a conflict error. + +## @backstage/cli@0.36.0-next.2 + +### Minor Changes + +- d0f4cd2: Added new `auth` command group for authenticating the CLI with Backstage instances using OAuth 2.0 with a pre-registered client metadata document. Commands include `login`, `logout`, `list`, `show`, `print-token`, and `select` for managing multiple authenticated instances. + +### Patch Changes + +- a4e5902: Internal refactor of the CLI command registration +- ff4a45a: Migrated remaining CLI command handlers from `commander` to `cleye` for argument parsing. Several camelCase CLI flags have been deprecated in favor of their kebab-case equivalents (e.g. `--successCache` → `--success-cache`). The old camelCase forms still work but will now log a deprecation warning. Please update any scripts or CI configurations to use the kebab-case versions. +- 4a75544: Updated dependency `react-refresh` to `^0.18.0`. +- Updated dependencies + - @backstage/cli-common@0.2.0-next.2 + - @backstage/integration@2.0.0-next.2 + +## @backstage/frontend-app-api@0.16.0-next.1 + +### Minor Changes + +- 92af1ae: **BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createSpecializedApp`. This flag had no effect and was a no-op, so no behavioral changes are expected. + +### Patch Changes + +- 0452d02: Add optional `description` field to plugin-level feature flags. +- dab6c46: Added the `ExtensionFactoryMiddleware` type as a public export. +- Updated dependencies + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/frontend-defaults@0.5.0-next.1 + +## @backstage/frontend-defaults@0.5.0-next.1 + +### Minor Changes + +- 92af1ae: **BREAKING**: Removed the `allowUnknownExtensionConfig` option from `createApp`. This flag had no effect and was a no-op, so no behavioral changes are expected. +- 33de79d: **BREAKING**: Removed the deprecated `createPublicSignInApp` function. Use `createApp` from `@backstage/frontend-defaults` with `appModulePublicSignIn` from `@backstage/plugin-app/alpha` instead. + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/frontend-app-api@0.16.0-next.1 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-app@0.4.1-next.2 + +## @backstage/frontend-plugin-api@0.15.0-next.1 + +### Minor Changes + +- 6573901: **BREAKING**: Removed the deprecated `AnyExtensionDataRef` type. Use `ExtensionDataRef` without type parameters instead. +- a9440f0: **BREAKING**: Simplified the `ExtensionAttachTo` type to only support a single attachment target. The array form for attaching to multiple extension points has been removed. Also removed the deprecated `ExtensionAttachToSpec` type alias. + +### Patch Changes + +- 8a3a906: Deprecated `NavItemBlueprint`. Nav items are now automatically inferred from `PageBlueprint` extensions based on their `title` and `icon` params. +- b15a685: Deprecated `withApis`, use the `withApis` export from `@backstage/core-compat-api` instead. +- 0452d02: Add optional `description` field to plugin-level feature flags. +- 1bec049: Fixed inconsistent `JSX.Element` type reference in the `DialogApiDialog.update` method signature. +- 2c383b5: Deprecated `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory` in favor of the exports from `@backstage/plugin-app-react`. +- dab6c46: Deprecated the `ExtensionFactoryMiddleware` type, which has been moved to `@backstage/frontend-app-api`. +- d0206c4: Removed the deprecated `defaultPath` migration helper from `PageBlueprint` params. +- edb872c: Renamed the `PageTab` type to `PageLayoutTab`. The old `PageTab` name is now a deprecated type alias. +- fe848e0: Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context. + +## @backstage/plugin-catalog-backend@3.5.0-next.2 + +### Minor Changes + +- 5d95e8e: Add an `onConflict` option to location creation that can refresh an existing location instead of throwing a conflict error. + +### Patch Changes + +- 7416e8b: Moved stitch queue concerns out of `refresh_state` and `final_entities` into a dedicated `stitch_queue` table with `entity_ref` as the primary key. The `stitch_ticket` is used for optimistic concurrency control. When a stitch completes successfully and the ticket hasn't changed, the corresponding row is deleted from the queue. The migration handles existing data and is fully reversible. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-catalog-graph@0.6.0-next.2 + +### Minor Changes + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-catalog-react@2.1.0-next.2 + +### Minor Changes + +- d14b6e0: Exported `useEntityRefLink` hook that returns a function for generating entity page URLs from entity references. +- c6080eb: Added `EntityInfoCard` component to `@backstage/plugin-catalog-react` as a BUI-based card wrapper for entity page cards. + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-test-utils@0.5.1-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-notifications-backend-module-slack@0.4.0-next.1 + +### Minor Changes + +- cd62d78: **BREAKING**: Only send direct messages to user entity recipients. Notifications sent to non-user entities no longer send Slack direct messages to resolved users. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-notifications-node@0.2.24-next.2 + +## @backstage/plugin-org@0.7.0-next.2 + +### Minor Changes + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +- 5fc35bb: Migrated `EntityAboutCard`, `EntityLinksCard`, `EntityLabelsCard`, `GroupProfileCard`, and `UserProfileCard` from MUI/InfoCard to use the new BUI card layout and BUI components where possible. + + **BREAKING**: Removed `variant` prop from EntityAboutCard, EntityUserProfileCard, EntityGroupProfileCard, EntityLabelsCard, EntityLinksCard. Removed `gridSizes` prop from `AboutField`. + + **Migration:** + + Simply delete the obsolete `variant` and `gridSizes` props, e.g: + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-scaffolder-backend@3.2.0-next.2 + +### Minor Changes + +- e8736ea: Added secrets schema validation for task creation, retry, and dry-run endpoints. When a template defines `spec.secrets.schema`, the API validates provided secrets against the schema and returns a `400` error if validation fails. + +### Patch Changes + +- 30ff981: Fixed a security vulnerability where secrets could bypass log redaction when transformed through Nunjucks filters in scaffolder templates. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-common@2.0.0-next.2 + +### Minor Changes + +- e8736ea: Added an optional `secrets` field to `TemplateEntityV1beta3` for configuring secrets validation. The schema for validating secrets is defined under `secrets.schema` as a JSON Schema object. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@2.0.0-next.2 + +## @backstage/plugin-scaffolder-react@1.20.0-next.2 + +### Minor Changes + +- 470f72d: The `LogViewer` component from `@backstage/core-components` now supports downloading logs if a callback is passed to `onDownloadLogs` + +### Patch Changes + +- bd31ddd: Updated dependency `flatted` to `3.3.4`. +- Updated dependencies + - @backstage/frontend-test-utils@0.5.1-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + +## @backstage/backend-defaults@0.16.0-next.2 + +### Patch Changes + +- 015668c: Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available. +- 5fcbef2: Updated dependency `express-rate-limit` to `^8.0.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/backend-app-api@1.6.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/backend-dynamic-feature-service@0.8.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/cli-common@0.2.0-next.2 + - @backstage/plugin-catalog-backend@3.5.0-next.2 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-app-node@0.1.43-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-events-backend@0.6.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/backend-openapi-utils@0.6.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/backend-test-utils@1.11.1-next.2 + +### Patch Changes + +- 164711a: Added `cancelTask` to `MockSchedulerService` and mock scheduler service factory. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/backend-app-api@1.6.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/cli-common@0.2.0-next.2 + +### Patch Changes + +- 9361965: Fixed `runCheck` to ignore stdio of the spawned process, preventing unwanted output from leaking to the terminal. + +## @backstage/core-app-api@1.19.6-next.1 + +### Patch Changes + +- 12d8afe: Added `BUIProvider` from `@backstage/ui` to the app shell provider tree, enabling BUI components to fire analytics events through the Backstage analytics system. +- 0452d02: Add optional `description` field to plugin-level feature flags. +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/core-plugin-api@1.12.4-next.1 + +## @backstage/core-compat-api@0.5.9-next.2 + +### Patch Changes + +- b15a685: Added `withApis`, which is a Higher-Order Component for providing APIs as props to a component via `useApiHolder`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/plugin-app-react@0.2.1-next.1 + +## @backstage/core-components@0.18.8-next.1 + +### Patch Changes + +- 8b1a847: Fixed Table component layout when both `filters` and `title` props are used together. The filter controls now use a dedicated CSS class (`filterControls`) instead of incorrectly reusing the root container class. +- 470f72d: The `LogViewer` component from `@backstage/core-components` now supports downloading logs if a callback is passed to `onDownloadLogs` +- Updated dependencies + - @backstage/core-plugin-api@1.12.4-next.1 + +## @backstage/core-plugin-api@1.12.4-next.1 + +### Patch Changes + +- 0452d02: Add optional `description` field to plugin-level feature flags. +- fe848e0: Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + +## @backstage/create-app@0.7.10-next.2 + +### Patch Changes + +- d14b6e0: **BREAKING**: Migrated `MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` to use BUI card primitives via `EntityInfoCard`. + + - `OwnershipCard`: Removed `variant` and `maxScrollHeight` props. Card height and scrolling are now controlled by the parent container — the card fills its container and the body scrolls automatically when content overflows. + - `CatalogGraphCard`: Removed `variant` prop. + - `MembersListCard`: Translation keys `subtitle`, `paginationLabel`, `aggregateMembersToggle.directMembers`, `aggregateMembersToggle.aggregatedMembers`, and `aggregateMembersToggle.ariaLabel` have been removed. The `title` key now includes `{{groupName}}`. New keys added: `cardLabel`, `noSearchResult`, `aggregateMembersToggle.label`. + - `OwnershipCard`: Translation keys `aggregateRelationsToggle.directRelations`, `aggregateRelationsToggle.aggregatedRelations`, and `aggregateRelationsToggle.ariaLabel` have been removed. New key added: `aggregateRelationsToggle.label`. + - Removed `MemberComponentClassKey` export, and `root` and `cardContent` from `MembersListCardClassKey`, `card` from `OwnershipCardClassKey`, and `card` from `CatalogGraphCardClassKey`. + + **Migration:** + + ```diff + - + + + ``` + + ```diff + - + + + ``` + +- Updated dependencies + - @backstage/cli-common@0.2.0-next.2 + +## @backstage/frontend-dynamic-feature-loader@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + +## @backstage/frontend-test-utils@0.5.1-next.2 + +### Patch Changes + +- b56f573: Deprecated standalone mock API exports in favor of the `mockApis` namespace. This includes the mock classes (`MockAlertApi`, `MockAnalyticsApi`, `MockConfigApi`, `MockErrorApi`, `MockFetchApi`, `MockFeatureFlagsApi`, `MockPermissionApi`, `MockStorageApi`, `MockTranslationApi`), their option types (`MockErrorApiOptions`, `MockFeatureFlagsApiOptions`), and the `ErrorWithContext` type. `MockFetchApiOptions` is kept as a non-deprecated export. Use the `mockApis` namespace instead, for example `mockApis.alert()` or `mockApis.alert.mock()`. +- Updated dependencies + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/frontend-app-api@0.16.0-next.1 + - @backstage/plugin-app-react@0.2.1-next.1 + - @backstage/plugin-app@0.4.1-next.2 + +## @backstage/integration@2.0.0-next.2 + +### Patch Changes + +- 1513a0b: Fixed a security vulnerability where path traversal sequences in SCM URLs could be used to access unintended API endpoints using server-side integration credentials. + +## @backstage/repo-tools@0.17.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/cli-common@0.2.0-next.2 + +## @backstage/ui@0.13.0-next.2 + +### Patch Changes + +- db92751: Added interactive support to the `Card` component. Pass `onPress` to make the entire card surface pressable, or `href` to make it navigate to a URL. A transparent overlay handles the interaction while nested buttons and links remain independently clickable. + +- 12d8afe: Added analytics capabilities to the component library. Components with navigation behavior (Link, ButtonLink, Tab, MenuItem, Tag, Row) now fire analytics events on click when a `BUIProvider` is present. + + New exports: `BUIProvider`, `useAnalytics`, `getNodeText`, and associated types (`AnalyticsTracker`, `UseAnalyticsFn`, `BUIProviderProps`, `AnalyticsEventAttributes`). + + Components with analytics support now accept a `noTrack` prop to suppress event firing. + + **Affected components:** Link, ButtonLink, Tab, MenuItem, Tag, Row + +- 430d5ed: Fixed interactive cards so that CardBody can scroll when the card has a constrained height. Previously, the overlay element blocked scroll events. + + **Affected components:** Card + +- ad7c883: Deprecated the `HeaderPage` component name in favor of `Header`. The old `HeaderPage`, `HeaderPageProps`, `HeaderPageOwnProps`, `HeaderPageBreadcrumb`, and `HeaderPageDefinition` exports are still available as deprecated aliases. + +- f42f4cc: Fixed Table column headers overflowing and wrapping when there is not enough space. Headers now truncate with ellipsis instead. + + **Affected components:** Table + +- fbd5c5a: Fixed Table rows showing a pointer cursor when not interactive. Rows now only show `cursor: pointer` when they have an `href`, are selectable, or are pressable. + + **Affected components:** Table + +- 7960d54: Added support for native HTML div attributes on the `Flex`, `Grid`, and `Grid.Item` components. + + **Affected components:** Flex, Grid, Grid.Item + +- 12d8afe: Fixed MenuItem `onAction` prop ordering so user-provided `onAction` handlers are chained rather than silently overwritten. + +- bb66b86: The `Select` trigger now automatically adapts its background colour based on the parent background context. + + **Affected components:** Select + +- 934ac03: `SearchField` and `TextField` now automatically adapt their background color based on the parent bg context, stepping up one neutral level (e.g. neutral-1 → neutral-2) when placed on a neutral background. `TextField` also gains a focus ring using the `--bui-ring` token. + + **Affected components:** SearchField, TextField + +## @backstage/plugin-api-docs@0.13.5-next.2 + +### Patch Changes + +- ca277ef: Updated dependency `graphiql` to `3.9.0` to address security vulnerability in `markdown-it` package. + Updated dependency `@graphiql/react` to `0.29.0` to match the version used by `graphiql`. + Moved dependency `graphql-config` to `devDependencies` as it is needed only for types. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-catalog@2.0.0-next.2 + +## @backstage/plugin-app@0.4.1-next.2 + +### Patch Changes + +- 12d8afe: Added `BUIProvider` from `@backstage/ui` to the app root, enabling BUI components to fire analytics events through the Backstage analytics system. +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-app-react@0.2.1-next.1 + +## @backstage/plugin-app-backend@0.5.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-app-node@0.1.43-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-app-node@0.1.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-app-react@0.2.1-next.1 + +### Patch Changes + +- 2c383b5: Added `AnalyticsImplementationBlueprint` and `AnalyticsImplementationFactory`, migrated from `@backstage/frontend-plugin-api`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + +## @backstage/plugin-app-visualizer@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-auth@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-auth-backend@0.27.1-next.2 + +### Patch Changes + +- d0f4cd2: Added optional client metadata document endpoint at `/.well-known/oauth-client/cli.json` relative to the auth backend base URL for CLI authentication. Enabled when `auth.experimentalClientIdMetadataDocuments.enabled` is set to `true`. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-backend@0.27.1-next.2 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-github-provider@0.5.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-backend@0.27.1-next.2 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-openshift-provider@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-auth-node@0.6.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + +## @backstage/plugin-catalog-backend-module-aws@0.4.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-azure@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-github@0.13.0-next.2 + +### Patch Changes + +- 106d1b2: Added a `defaultUserTransformer.useVerifiedEmails` config option for the `githubOrg` provider. When set to `true`, the default user transformer prefers organization verified domain emails over the user's public GitHub email. Defaults to `false`, which uses only the public GitHub email. + + This option has no effect when a custom user transformer is set via the `githubOrgEntityProviderTransformsExtensionPoint`. + + ```yaml + catalog: + providers: + githubOrg: + production: + githubUrl: https://github.com + orgs: + - my-org + defaultUserTransformer: + useVerifiedEmails: true + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.20-next.2 + +### Patch Changes + +- 106d1b2: Added a `defaultUserTransformer.useVerifiedEmails` config option for the `githubOrg` provider. When set to `true`, the default user transformer prefers organization verified domain emails over the user's public GitHub email. Defaults to `false`, which uses only the public GitHub email. + + This option has no effect when a custom user transformer is set via the `githubOrgEntityProviderTransformsExtensionPoint`. + + ```yaml + catalog: + providers: + githubOrg: + production: + githubUrl: https://github.com + orgs: + - my-org + defaultUserTransformer: + useVerifiedEmails: true + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-backend-module-github@0.13.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.8.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-backend-module-gitlab@0.8.1-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/plugin-catalog-backend@3.5.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.12.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-logs@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-backend@3.5.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.9.1-next.1 + +### Patch Changes + +- 97eaecf: Fixed scheduler task remaining stuck in running state after pod termination by propagating AbortSignal into MicrosoftGraphOrgEntityProvider.read() +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-catalog-import@0.13.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-catalog-node@2.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.11.1-next.2 + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-devtools-react@0.1.2-next.1 + +## @backstage/plugin-devtools@0.1.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-devtools-react@0.1.2-next.1 + +## @backstage/plugin-devtools-backend@0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/cli-common@0.2.0-next.2 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-devtools-react@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + +## @backstage/plugin-events-backend@0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-azure@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-github@0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-gitlab@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-google-pubsub@0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-backend-module-kafka@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-events-node@0.4.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-gateway-backend@1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-home@0.9.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-home-react@0.1.36-next.1 + +## @backstage/plugin-home-react@0.1.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-kubernetes@0.12.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-kubernetes-backend@0.21.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-kubernetes-node@0.4.2-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-kubernetes-node@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-mcp-actions-backend@0.1.10-next.2 + +### Patch Changes + +- c74b697: Added support for splitting MCP actions into multiple servers via `mcpActions.servers` configuration. Each server gets its own endpoint at `/api/mcp-actions/v1/{key}` with actions scoped using include/exclude filter rules. Tool names are now namespaced with the plugin ID by default, configurable via `mcpActions.namespacedToolNames`. When `mcpActions.servers` is not configured, the plugin continues to serve a single server at `/api/mcp-actions/v1`. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-mui-to-bui@0.2.5-next.2 + +### Patch Changes + +- ad7c883: Updated the MUI to BUI theme converter page to use the renamed `Header` component from `@backstage/ui`. +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + +## @backstage/plugin-notifications@0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-notifications-backend@0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-notifications-node@0.2.24-next.2 + - @backstage/plugin-signals-node@0.1.29-next.1 + +## @backstage/plugin-notifications-backend-module-email@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-notifications-node@0.2.24-next.2 + +## @backstage/plugin-notifications-node@0.2.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-signals-node@0.1.29-next.1 + +## @backstage/plugin-permission-backend@0.7.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-permission-node@0.10.11-next.1 + +## @backstage/plugin-permission-node@0.10.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + +## @backstage/plugin-proxy-backend@0.6.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-proxy-node@0.1.13-next.1 + +## @backstage/plugin-proxy-node@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-scaffolder@1.35.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-scaffolder-react@1.20.0-next.2 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-github@0.9.7-next.2 + +### Patch Changes + +- b2591f6: Fixed environment `waitTime` description incorrectly asking for milliseconds instead of minutes. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.11.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-notifications-node@0.2.24-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + - @backstage/plugin-scaffolder-node-test-utils@0.3.9-next.2 + +## @backstage/plugin-scaffolder-node@0.13.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.11.1-next.2 + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-scaffolder-common@2.0.0-next.2 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@1.11.1-next.2 + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-scaffolder-node@0.13.0-next.2 + +## @backstage/plugin-search@1.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-search-react@1.10.5-next.1 + +## @backstage/plugin-search-backend@2.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-openapi-utils@0.6.7-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-catalog@0.3.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.8.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-explore@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-pg@0.5.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-module-techdocs@0.4.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-techdocs-node@1.14.4-next.2 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + +## @backstage/plugin-search-backend-node@1.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + +## @backstage/plugin-search-react@1.10.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-signals@0.0.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-signals-backend@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-events-node@0.4.20-next.1 + - @backstage/plugin-signals-node@0.1.29-next.1 + +## @backstage/plugin-signals-node@0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-events-node@0.4.20-next.1 + +## @backstage/plugin-techdocs@1.17.1-next.2 + +### Patch Changes + +- 9795d30: chore(deps): bump `dompurify` from 3.3.1 to 3.3.2 +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-search-react@1.10.5-next.1 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@2.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/plugin-techdocs@1.17.1-next.2 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/plugin-catalog@2.0.0-next.2 + - @backstage/plugin-search-react@1.10.5-next.1 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @backstage/plugin-techdocs-backend@2.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-techdocs-node@1.14.4-next.2 + - @backstage/catalog-client@1.14.0-next.2 + - @backstage/integration@2.0.0-next.2 + - @backstage/plugin-catalog-node@2.1.0-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/integration@2.0.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @backstage/plugin-techdocs-node@1.14.4-next.2 + +### Patch Changes + +- e96f6d9: Removed `INHERIT` from the `ALLOWED_MKDOCS_KEYS` set to address a security concern with MkDocs configuration inheritance. +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/integration@2.0.0-next.2 + +## @backstage/plugin-techdocs-react@1.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-user-settings@0.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + +## @backstage/plugin-user-settings-backend@0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-signals-node@0.1.29-next.1 + +## example-app@0.0.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.5.9-next.2 + - @backstage/ui@0.13.0-next.2 + - @backstage/cli@0.36.0-next.2 + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/plugin-techdocs@1.17.1-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/frontend-app-api@0.16.0-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-org@0.7.0-next.2 + - @backstage/plugin-catalog-graph@0.6.0-next.2 + - @backstage/plugin-app-react@0.2.1-next.1 + - @backstage/plugin-app@0.4.1-next.2 + - @backstage/frontend-defaults@0.5.0-next.1 + - @backstage/plugin-scaffolder-react@1.20.0-next.2 + - @backstage/plugin-api-docs@0.13.5-next.2 + - @backstage/plugin-catalog@2.0.0-next.2 + - @backstage/plugin-app-visualizer@0.2.1-next.2 + - @backstage/plugin-auth@0.1.6-next.1 + - @backstage/plugin-catalog-import@0.13.11-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.27-next.1 + - @backstage/plugin-devtools@0.1.37-next.2 + - @backstage/plugin-home@0.9.3-next.2 + - @backstage/plugin-home-react@0.1.36-next.1 + - @backstage/plugin-kubernetes@0.12.17-next.2 + - @backstage/plugin-notifications@0.5.15-next.1 + - @backstage/plugin-scaffolder@1.35.5-next.2 + - @backstage/plugin-search@1.6.2-next.2 + - @backstage/plugin-search-react@1.10.5-next.1 + - @backstage/plugin-signals@0.0.29-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.34-next.2 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + - @backstage/plugin-user-settings@0.9.1-next.2 + +## app-example-plugin@0.0.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-components@0.18.8-next.1 + +## example-app-legacy@0.2.119-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/cli@0.36.0-next.2 + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/plugin-techdocs@1.17.1-next.2 + - @backstage/core-plugin-api@1.12.4-next.1 + - @backstage/frontend-app-api@0.16.0-next.1 + - @backstage/plugin-catalog-react@2.1.0-next.2 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-org@0.7.0-next.2 + - @backstage/plugin-catalog-graph@0.6.0-next.2 + - @backstage/plugin-mui-to-bui@0.2.5-next.2 + - @backstage/plugin-scaffolder-react@1.20.0-next.2 + - @backstage/plugin-api-docs@0.13.5-next.2 + - @backstage/plugin-catalog@2.0.0-next.2 + - @backstage/plugin-catalog-import@0.13.11-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.27-next.1 + - @backstage/plugin-devtools@0.1.37-next.2 + - @backstage/plugin-home@0.9.3-next.2 + - @backstage/plugin-home-react@0.1.36-next.1 + - @backstage/plugin-kubernetes@0.12.17-next.2 + - @backstage/plugin-notifications@0.5.15-next.1 + - @backstage/plugin-scaffolder@1.35.5-next.2 + - @backstage/plugin-search@1.6.2-next.2 + - @backstage/plugin-search-react@1.10.5-next.1 + - @backstage/plugin-signals@0.0.29-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.34-next.2 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + - @backstage/plugin-user-settings@0.9.1-next.2 + +## example-backend@0.0.48-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 + - @backstage/backend-defaults@0.16.0-next.2 + - @backstage/plugin-auth-backend@0.27.1-next.2 + - @backstage/plugin-catalog-backend@3.5.0-next.2 + - @backstage/plugin-scaffolder-backend@3.2.0-next.2 + - @backstage/plugin-mcp-actions-backend@0.1.10-next.2 + - @backstage/plugin-scaffolder-backend-module-github@0.9.7-next.2 + - @backstage/plugin-app-backend@0.5.12-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.5.1-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.17-next.1 + - @backstage/plugin-auth-backend-module-openshift-provider@0.1.5-next.1 + - @backstage/plugin-auth-node@0.6.14-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.12-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.20-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.18-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.9-next.1 + - @backstage/plugin-devtools-backend@0.5.15-next.1 + - @backstage/plugin-events-backend@0.6.0-next.2 + - @backstage/plugin-events-backend-module-google-pubsub@0.2.1-next.1 + - @backstage/plugin-kubernetes-backend@0.21.2-next.2 + - @backstage/plugin-notifications-backend@0.6.3-next.1 + - @backstage/plugin-permission-backend@0.7.10-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.17-next.1 + - @backstage/plugin-permission-node@0.10.11-next.1 + - @backstage/plugin-proxy-backend@0.6.11-next.1 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.20-next.2 + - @backstage/plugin-search-backend@2.1.0-next.2 + - @backstage/plugin-search-backend-module-catalog@0.3.13-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.8.1-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.12-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.12-next.2 + - @backstage/plugin-search-backend-node@1.4.2-next.1 + - @backstage/plugin-signals-backend@0.3.13-next.1 + - @backstage/plugin-techdocs-backend@2.1.6-next.2 + +## @internal/frontend@0.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + +## @internal/scaffolder@0.0.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/plugin-scaffolder-react@1.20.0-next.2 + +## techdocs-cli-embedded-app@0.2.118-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.13.0-next.2 + - @backstage/cli@0.36.0-next.2 + - @backstage/core-app-api@1.19.6-next.1 + - @backstage/plugin-techdocs@1.17.1-next.2 + - @backstage/frontend-plugin-api@0.15.0-next.1 + - @backstage/core-components@0.18.8-next.1 + - @backstage/plugin-app-react@0.2.1-next.1 + - @backstage/frontend-defaults@0.5.0-next.1 + - @backstage/plugin-catalog@2.0.0-next.2 + - @backstage/plugin-techdocs-react@1.3.9-next.1 + +## @internal/plugin-todo-list-backend@1.0.48-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.8.0-next.1 diff --git a/docs/releases/v1.49.0.md b/docs/releases/v1.49.0.md new file mode 100644 index 0000000000..83c2e69f3d --- /dev/null +++ b/docs/releases/v1.49.0.md @@ -0,0 +1,233 @@ +--- +id: v1.49.0 +title: v1.49.0 +description: Backstage Release v1.49.0 +--- + +These are the release notes for the v1.49.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +### New Frontend System: 1.0 Release Candidate + +This release marks the release candidate for version 1.0 of the New Frontend System. Newly created Backstage apps now use the New Frontend System by default, the `--next` flag for `create-app` has been replaced with a `--legacy` flag for apps that still want to use the old system. The `yarn new` templates have been updated accordingly, with auto-detection that presents the correct plugin templates based on which frontend system your app uses. + +On the framework side, this release includes significant stabilization of the API surface. Several deprecated types and options have been removed, `PluginWrapperApi` has graduated from alpha to stable, and a new builder pattern for `createApiRef` has been introduced. A full list of API changes can be found in the [`@backstage/frontend-plugin-api` changelog](https://github.com/backstage/backstage/blob/master/packages/frontend-plugin-api/CHANGELOG.md). + +Plugin pages across the supported plugins have been migrated to the Backstage UI `Header` component, aligning the plugin header and page-level navigation patterns across the New Frontend System. A new `@backstage/frontend-dev-utils` package with a `createDevApp` helper simplifies the setup of plugin development apps. + +Documentation has been overhauled across the board to cover and prioritize the New Frontend System, aligning installation guidance across plugin READMEs, closing gaps with the existing "Plugins" section that is now marked as legacy, and many other changes. + +### **BREAKING**: Backstage UI updates + +There are several new additions in Backstage UI, for example new `SearchAutocomplete` and `SearchAutocompleteItem` components for building accessible search-with-results patterns. New `List` and `ListRow` components built on React Aria's GridList for interactive lists with icons, descriptions, and selection. A `virtualized` prop added to the `Table` for rendering large datasets. And much more. + +There are also several breaking changes to note: + +- **Checkbox**: Removed the redundant `selected` and `indeterminate` props. Use `isSelected` and `isIndeterminate` instead, which are the standard React Aria props. +- **Header CSS classes**: Renamed internal CSS classes to match the `Header` component name (e.g. `bui-HeaderPage` → `bui-Header`). +- **BUIProvider routing**: Centralized client-side routing in `BUIProvider`. Components like Link, ButtonLink, Tabs, Menu, and Table now require a `BUIProvider` inside a React Router context for client-side navigation to work. +- **Data attributes**: Data attributes rendered by components are now always lowercase, affecting CSS selectors targeting camelCase attributes. +- **Removed deprecated types**: `ComponentDefinition`, `ClassNamesMap`, `DataAttributeValues`, and `DataAttributesMap` have been removed from the public API. +- **Popover token**: Removed `--bui-bg-popover` CSS token. Use `--bui-bg-neutral-1` or `--bui-bg-app` instead. +- **Neutral background**: Simplified the neutral background prop API. Explicit `neutral-1`, `neutral-2`, `neutral-3`, and `neutral-auto` values have been replaced by a single `neutral` value that auto-increments from the parent context. + +Check the [BUI Changelog](https://ui.backstage.io/changelog) for more details. + +### **BREAKING**: Entity cards migrated to Backstage UI + +The `@backstage/plugin-catalog` package has received a major version bump as `EntityAboutCard`, `EntityLinksCard`, `EntityLabelsCard`, `GroupProfileCard`, and `UserProfileCard` have been migrated from MUI to BUI. The `variant` prop has been removed from these cards, and the `gridSizes` prop has been removed from `AboutField`. + +Additionally, entity table cards like `HasComponentsCard`, `HasResourcesCard`, `HasSubcomponentsCard`, and others now render with BUI when no legacy props are passed. The old `variant`, `columns`, and `tableOptions` props are deprecated but still supported — passing them triggers the legacy MUI rendering. `RelatedEntitiesCard` is deprecated in favor of the new `EntityRelationCard` from `@backstage/plugin-catalog-react/alpha`. + +`MembersListCard`, `OwnershipCard`, and `CatalogGraphCard` from `@backstage/plugin-org` and `@backstage/plugin-catalog-graph` have also been migrated to BUI card primitives via `EntityInfoCard`. The `variant` prop has been removed from these cards. + +```diff +- ++ +``` + +### **BREAKING**: Deprecated Bitbucket and legacy integrations removed + +Several long-deprecated integrations have been cleaned up across the project. + +In `@backstage/integration`, the deprecated `bitbucket` config object, Azure DevOps `token`/`credential` fields, `parseGerritGitilesUrl`, `buildGerritGitilesArchiveUrl`, and `getGitHubRequestOptions` have all been removed. Use `bitbucketCloud`/`bitbucketServer`, the `credentials` array, `parseGitilesUrlRef`/`buildGerritGitilesArchiveUrlFromLocation`, respectively. + +In `@backstage/backend-defaults`, the deprecated `BitbucketUrlReader` has been removed. Use `BitbucketCloudUrlReader` or `BitbucketServerUrlReader` instead. + +In `@backstage/plugin-scaffolder-node`, the deprecated `bitbucket` integration has been removed from `parseRepoUrl`. It now uses `bitbucketCloud` or `bitbucketServer`. + +In `@backstage/plugin-scaffolder-common`, the deprecated `bitbucket` integration has been removed from `ScaffolderClient`. + +### **BREAKING PRODUCERS**: `ScaffolderApi` methods now required + +The `retry`, `listTasks`, `listTemplatingExtensions`, `dryRun`, and `autocomplete` methods are now required on the `ScaffolderApi` interface. Implementations must provide all of these methods. + +### **BREAKING**: Slack notifications direct messages + +The `@backstage/plugin-notifications-backend-module-slack` module now only sends direct messages to user entity recipients. Notifications sent to non-user entities no longer trigger Slack direct messages. + +Contributed by [@kaidubauskas-dd](https://github.com/kaidubauskas-dd) in [#32619](https://github.com/backstage/backstage/pull/32619). + +### AI and MCP improvements + +This release significantly expands the set of built-in actions available for AI agents and MCP consumers. New actions include `who-am-i` for identifying the authenticated user, `query-catalog-entities` for predicate-based catalog queries, `list-scaffolder-actions` for discovering available scaffolder actions with their schemas, `list-scaffolder-tasks` for querying scaffolder tasks with ownership filtering, and `get-scaffolder-task-logs` for retrieving log events from running tasks. + +The MCP actions backend now supports splitting actions into multiple servers via `mcpActions.servers` configuration, with include/exclude filter rules per server. Added `mcpActions.name` and `mcpActions.description` config options for customizing server identity, and tool names now use dot separators to align with the MCP spec convention. Error forwarding has also been improved so that known errors preserve their original status codes. + +A new `actions` CLI module provides `actions list`, `actions execute`, and `actions sources` commands for interacting with the actions registry directly from the terminal. + +See the [AI documentation](https://backstage.io/docs/ai/generated-index) for more information on using Backstage with AI agents. + +### CLI Module System + +The Backstage CLI has been refactored into an extensible module system. CLI commands are now provided by individual `cli-module` packages that are discovered automatically from your project's dependencies. This release includes the initial set of CLI modules: + +- `@backstage/cli-module-auth` +- `@backstage/cli-module-actions` +- `@backstage/cli-module-build` +- `@backstage/cli-module-config` +- `@backstage/cli-module-github` +- `@backstage/cli-module-info` +- `@backstage/cli-module-lint` +- `@backstage/cli-module-maintenance` +- `@backstage/cli-module-migrate` +- `@backstage/cli-module-new` +- `@backstage/cli-module-test-jest` +- `@backstage/cli-module-translations` + +If no CLI modules are found in project dependencies, the CLI falls back to the built-in set with a deprecation warning. To prepare for the removal of this fallback, add `@backstage/cli-defaults` as a `devDependency`: + +```json +{ + "devDependencies": { + "@backstage/cli-defaults": "backstage:^" + } +} +``` + +A new `createCliModule` API in `@backstage/cli-node` enables third-party CLI modules, and a `cli-module` template is available via `yarn new`. + +### CLI Auth Commands + +A new `auth` command group has been added for authenticating the CLI with Backstage instances using OAuth 2.0. Commands include `login`, `logout`, `list`, `show`, `print-token`, and `select` for managing multiple authenticated instances. An API for interacting with the selected and specific instance and the authentication sessions towards them has been added to `@backstage/cli-node` grouped under the `CliAuth` export. + +### `package bundle` Command + +A new `package bundle` command has been added to `@backstage/cli-module-build` for creating self-contained plugin bundles for dynamic loading, to be used by the `backend-dynamic-feature-service`. + +Contributed by [@davidfestal](https://github.com/davidfestal) in [#33125](https://github.com/backstage/backstage/pull/33125). + +### Predicate-based catalog entity filtering + +A powerful new predicate-based filtering system has been added to the catalog. The catalog client's `queryEntities()`, `getEntitiesByRefs()`, and `getEntityFacets()` methods now support a `query` field with operators like `$all`, `$any`, `$not`, `$exists`, `$in`, `$hasPrefix`, and `$contains` for expressive entity queries. + +These are exposed through new POST endpoints with full pagination and permission enforcement support. A new `query-catalog-entities` action has been added for predicate-based catalog queries via the actions system. + +### Actions: Permissions and user invocation + +Backend actions now support permission-based visibility. An optional `visibilityPermission` field has been added to `ActionsRegistryActionOptions`, allowing actions to declare a permission that controls access. + +The actions registry invoke endpoint now also accepts direct user credentials in addition to service principals, enabling CLI and other direct user clients to invoke actions. + +### New `ToastApi` for rich notifications + +A new `ToastApi` has been introduced in the New Frontend System for displaying rich toast notifications. Toasts support titles, descriptions, custom timeouts, action links, and status variants (neutral, info, success, warning, danger). They can also be dismissed programmatically. + +```typescript +const toastApi = useApi(toastApiRef); + +toastApi.post({ + title: 'Entity saved', + description: 'Your changes have been saved successfully.', + status: 'success', + timeout: 5000, + links: [{ label: 'View entity', href: '/catalog/entity' }], +}); +``` + +The `ToastDisplay` component subscribes to both `ToastApi` and the existing `AlertApi`, providing a migration path. The `AlertApi`, `AlertMessage`, `alertApiRef`, and `AlertApiForwarder` have been deprecated in favor of `ToastApi`. + +### Template secrets schema validation + +Templates can now define a `secrets.schema` field in `TemplateEntityV1beta3` for validating secrets provided during task creation. The scaffolder backend validates secrets against the schema and returns a `400` error if validation fails. + +### Scheduler `cancelTask` + +A new `cancelTask` method has been added to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. A corresponding cancel button has been added to the DevTools scheduled tasks UI. + +### Entity page group aliases and content ordering + +Entity page groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `defaultContentOrder` option controls how content items within each group are sorted, with support for both page-level and per-group overrides. + +### `LogViewer` download support + +The `LogViewer` component now supports downloading logs via an `onDownloadLogs` callback. + +Contributed by [@0xts](https://github.com/0xts) in [#31989](https://github.com/backstage/backstage/pull/31989). + +### Translation refs promoted to stable + +Translation refs across 18 packages have been promoted from alpha-only exports to the stable entry points. If you are importing translation refs from `/alpha` entry points, for example `import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'`, you can now import them directly from the main package entry point instead. The alpha re-exports are still available but deprecated. + +### Permission batching + +Permission checks made in the same tick are now batched into a single call to the permission backend, improving performance for pages with many permission-gated elements. + +### GitHub org verified email preference + +The default user transformer for `githubOrg` now prefers organization verified domain emails over the user's public GitHub email. A new `defaultUserTransformer.useVerifiedEmails` config option controls this behavior for the config-based provider. + +### GitLab integration improvements + +Added configurable throttling and retry mechanism for GitLab integration. + +Contributed by [@JohannesWill](https://github.com/JohannesWill) in [#30804](https://github.com/backstage/backstage/pull/30804). + +Added a new `gitlab:group:access` scaffolder action for managing GitLab group memberships. + +Contributed by [@Jellyfrog](https://github.com/Jellyfrog) in [#32528](https://github.com/backstage/backstage/pull/32528). + +Added `maskedAndHidden` option to `gitlab:projectVariable:create` and `publish:gitlab`. + +Contributed by [@hyfc](https://github.com/hyfc) in [#32818](https://github.com/backstage/backstage/pull/32818). + +### Custom Slack message layouts + +Added an extension for custom Slack message layouts in the notifications backend Slack module. + +Contributed by [@kaidubauskas-dd](https://github.com/kaidubauskas-dd) in [#32733](https://github.com/backstage/backstage/pull/32733). + +### OpenAPI 3.1 support + +OpenAPI schemas across several packages have been migrated to version 3.1. The `schema openapi` commands in `@backstage/repo-tools` now auto-detect the OpenAPI version and support both 3.0.x and 3.1.x specifications. + +### Deprecated Catalog Processors & New Community Plugin Backend Modules + +Two Catalog processors have been deprecated as they have been moved to the Community Plugins repo with their own backend modules: + +- `AnnotateScmSlugEntityProcessor`: Use `@backstage-community/plugin-catalog-backend-module-annotate-scm-slug` instead +- `CodeOwnersProcessor`: Use `@backstage-community/plugin-catalog-backend-module-codeowners` instead + +## Security Fixes + +This release does not contain any security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.49.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://spoti.fi/backstagenewsletter) if you want to be informed about what is happening in the world of Backstage. diff --git a/docs/releases/v1.50.0-next.0-changelog.md b/docs/releases/v1.50.0-next.0-changelog.md new file mode 100644 index 0000000000..b99b6bb195 --- /dev/null +++ b/docs/releases/v1.50.0-next.0-changelog.md @@ -0,0 +1,2439 @@ +# Release v1.50.0-next.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.50.0-next.0](https://backstage.github.io/upgrade-helper/?to=1.50.0-next.0) + +## @backstage/ui@0.14.0-next.0 + +### Minor Changes + +- 8659f33: **BREAKING**: The `Header` component's `tabs` prop now uses `HeaderNavTabItem[]` instead of `HeaderTab[]`. Tabs render as a `