diff --git a/.changeset/afraid-poets-thank.md b/.changeset/afraid-poets-thank.md
new file mode 100644
index 0000000000..b234e2e2c1
--- /dev/null
+++ b/.changeset/afraid-poets-thank.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Fix card scrolling behaviour
diff --git a/.changeset/angry-sites-fold.md b/.changeset/angry-sites-fold.md
deleted file mode 100644
index 8124ddaf47..0000000000
--- a/.changeset/angry-sites-fold.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-Added the configuration flag `auth.omitIdentityTokenOwnershipClaim` that causes issued user tokens to no longer contain the `ent` claim that represents the ownership references of the user.
-
-The benefit of this new flag is that issued user tokens will be much smaller in
-size, but they will no longer be self-contained. This means that any consumers
-of the token that require access to the ownership claims now need to call the
-`/api/auth/v1/userinfo` endpoint instead. Within the Backstage ecosystem this is
-done automatically, as clients will still receive the full set of claims during
-authentication, while plugin backends will need to use the `UserInfoService`
-which already calls the user info endpoint if necessary.
-
-When enabling this flag, it is important that any custom sign-in resolvers directly return the result of the sign-in method. For example, the following would not work:
-
-```ts
-const { token } = await ctx.issueToken({
- claims: { sub: entityRef, ent: [entityRef] },
-});
-return { token }; // WARNING: This will not work with the flag enabled
-```
-
-Instead, the sign-in resolver should directly return the result:
-
-```ts
-return ctx.issueToken({
- claims: { sub: entityRef, ent: [entityRef] },
-});
-```
diff --git a/.changeset/beige-kiwis-flow.md b/.changeset/beige-kiwis-flow.md
deleted file mode 100644
index 500095b44b..0000000000
--- a/.changeset/beige-kiwis-flow.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes-node': minor
----
-
-**BREAKING**: The `PinnipedHelper` class now expects a regular `LoggerService` instance from the new backend system, instead of a Winston logger.
diff --git a/.changeset/blue-apples-pump.md b/.changeset/blue-apples-pump.md
new file mode 100644
index 0000000000..c7bbdbbafc
--- /dev/null
+++ b/.changeset/blue-apples-pump.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-org': patch
+---
+
+Added OwnershipCard, ComponentsGrid and UserProfileCard components to the `overridableComponents`.
diff --git a/.changeset/brave-donuts-sink.md b/.changeset/brave-donuts-sink.md
deleted file mode 100644
index 47827345a5..0000000000
--- a/.changeset/brave-donuts-sink.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/test-utils': patch
----
-
-Added support for interpolating JSX elements with the `MockTranslationApi`.
diff --git a/.changeset/brave-eggs-mate.md b/.changeset/brave-eggs-mate.md
deleted file mode 100644
index 73eb8e363a..0000000000
--- a/.changeset/brave-eggs-mate.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/theme': patch
----
-
-Show arrow when MuiTableSortLabel receives focus
diff --git a/.changeset/brave-pumas-attack.md b/.changeset/brave-pumas-attack.md
new file mode 100644
index 0000000000..b08e3e5ff3
--- /dev/null
+++ b/.changeset/brave-pumas-attack.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-openapi-utils': patch
+---
+
+Update `express-openapi-validator` to 5.5.8 to fix security vulnerability in transitive dependency `multer`
diff --git a/.changeset/brave-toes-switch.md b/.changeset/brave-toes-switch.md
deleted file mode 100644
index 27b39cccd3..0000000000
--- a/.changeset/brave-toes-switch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-msgraph': minor
----
-
-Add new `userGroupMember.path`, `user.path` and, `group.path` option to each query type to allow more complex msgraph queries
diff --git a/.changeset/breezy-fans-exist.md b/.changeset/breezy-fans-exist.md
new file mode 100644
index 0000000000..bf70b58cea
--- /dev/null
+++ b/.changeset/breezy-fans-exist.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Added missing space for alert display component
diff --git a/.changeset/breezy-hotels-deny.md b/.changeset/breezy-hotels-deny.md
deleted file mode 100644
index 13c8b47a7f..0000000000
--- a/.changeset/breezy-hotels-deny.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/integration': patch
----
-
-Added missing `organizations` property to `azure` section in `config.d.ts` file
diff --git a/.changeset/bright-elephants-sparkle.md b/.changeset/bright-elephants-sparkle.md
new file mode 100644
index 0000000000..05dc6150c6
--- /dev/null
+++ b/.changeset/bright-elephants-sparkle.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Created a flag for scaffolding apps using the new frontend system.
diff --git a/.changeset/bright-moles-sort.md b/.changeset/bright-moles-sort.md
deleted file mode 100644
index 9796729d1a..0000000000
--- a/.changeset/bright-moles-sort.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-dynamic-feature-service': minor
----
-
-**BREAKING** Removed support for the legacy backend, please migrate to the new backend system
diff --git a/.changeset/bumpy-showers-design.md b/.changeset/bumpy-showers-design.md
deleted file mode 100644
index 2db5006944..0000000000
--- a/.changeset/bumpy-showers-design.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-gitlab': patch
----
-
-If the commit action is not `create` log a more appropriate error message to the end user advising that the files they're trying to modify might not exist
diff --git a/.changeset/busy-badgers-hang.md b/.changeset/busy-badgers-hang.md
deleted file mode 100644
index fc4b0e907e..0000000000
--- a/.changeset/busy-badgers-hang.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/create-app': patch
----
-
-Removed `lerna-debug.log*` pattern from `.gitignore` as Lerna was removed from the package in version `@backstage/create-app@0.5.19`.
diff --git a/.changeset/calm-geese-serve.md b/.changeset/calm-geese-serve.md
new file mode 100644
index 0000000000..ff52f59b56
--- /dev/null
+++ b/.changeset/calm-geese-serve.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes-backend': patch
+---
+
+Remove usage of the deprecated `loggerToWinstonLogger` from `@backstage/backend-common`.
diff --git a/.changeset/calm-toys-occur.md b/.changeset/calm-toys-occur.md
deleted file mode 100644
index ea03aaf4f8..0000000000
--- a/.changeset/calm-toys-occur.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-'@backstage/plugin-bitbucket-cloud-common': minor
----
-
-Update Bitbucket Cloud schema and models.
-
-The latest schema was fetched from Bitbucket Cloud and stored locally.
-Based on the updated schema, the models got regenerated.
-
-**BREAKING:**
-
-Due to the schema changes, the model update includes one breaking change:
-
-- `Account.username` was removed.
-
-Additionally, there were a couple of compatible changes including the addition of
-`BaseCommit.committer` and others.
diff --git a/.changeset/chatty-coats-sin.md b/.changeset/chatty-coats-sin.md
new file mode 100644
index 0000000000..97f74bee80
--- /dev/null
+++ b/.changeset/chatty-coats-sin.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': patch
+---
+
+Deprecated `createPublicSignInApp`, which has been replaced by the new `appModulePublicSignIn` from `@backstage/plugin-app/alpha` instead.
diff --git a/.changeset/chatty-dodos-design.md b/.changeset/chatty-dodos-design.md
new file mode 100644
index 0000000000..d998f09250
--- /dev/null
+++ b/.changeset/chatty-dodos-design.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+'@backstage/backend-defaults': patch
+---
+
+Fixed WinstonLogger throwing when redactions were null or undefined
diff --git a/.changeset/chatty-schools-post.md b/.changeset/chatty-schools-post.md
new file mode 100644
index 0000000000..0500a8a838
--- /dev/null
+++ b/.changeset/chatty-schools-post.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Remove deprecated `source` property from the `AppNodeSpec` type, use `AppNodeSpec.plugin` instead.
diff --git a/.changeset/chatty-showers-cheat.md b/.changeset/chatty-showers-cheat.md
deleted file mode 100644
index 24c2720fb6..0000000000
--- a/.changeset/chatty-showers-cheat.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-**BREAKING ALPHA**: You can no longer import the catalog plugin from the `/alpha` export; please use the regular root default export instead.
diff --git a/.changeset/chilly-trams-cheer.md b/.changeset/chilly-trams-cheer.md
deleted file mode 100644
index 0e14423ef8..0000000000
--- a/.changeset/chilly-trams-cheer.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes-react': patch
----
-
-Add headlamp formatter
diff --git a/.changeset/chubby-cougars-run.md b/.changeset/chubby-cougars-run.md
deleted file mode 100644
index deb954ef6b..0000000000
--- a/.changeset/chubby-cougars-run.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-catalog-backend': patch
----
-
-This patch addresses an issue identified in Backstage when configured with a MySQL database. If an entity of type location
-(e..all.yaml) has more than 70 referenced entities, clicking "Refresh" does not update the referenced entities as expected. This occurs because the TEXT type in MySQL has a limit of 65,535 bytes, which is insufficient to store all the referenced entities, causing the refresh operation to fail.
diff --git a/.changeset/chubby-needles-vanish.md b/.changeset/chubby-needles-vanish.md
deleted file mode 100644
index 2cd664dcdd..0000000000
--- a/.changeset/chubby-needles-vanish.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-Fix Canon missing dependencies
diff --git a/.changeset/clean-chairs-sit-2.md b/.changeset/clean-chairs-sit-2.md
new file mode 100644
index 0000000000..6fb7d6c844
--- /dev/null
+++ b/.changeset/clean-chairs-sit-2.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-scaffolder-react': minor
+---
+
+**DEPRECATION**: The following types have been deprecated from this package and moved into `@backstage/plugin-scaffolder-common` and should be imported from there instead.
+
+`Action`, `ListActionsResponse`, `LogEvent`, `ScaffolderApi`, `ScaffolderDryRunOptions`, `ScaffolderDryRunResponse`, `ScaffolderGetIntegrationsListOptions`, `ScaffolderGetIntegrationsListResponse`,
+`ScaffolderOutputLink`, `ScaffolderOutputText`, `ScaffolderScaffoldOptions`, `ScaffolderScaffoldResponse`, `ScaffolderStreamLogsOptions`, `ScaffolderTask`, `ScaffolderTaskOutput`, `ScaffolderTaskStatus`,
+`ScaffolderUsageExample`, `TemplateFilter`, `TemplateGlobalFunction`, `TemplateGlobalValue`, `TemplateParameterSchema`.
diff --git a/.changeset/clean-chairs-sit.md b/.changeset/clean-chairs-sit.md
new file mode 100644
index 0000000000..9e76e56887
--- /dev/null
+++ b/.changeset/clean-chairs-sit.md
@@ -0,0 +1,10 @@
+---
+'@backstage/backend-openapi-utils': minor
+'@backstage/plugin-scaffolder-backend': minor
+'@backstage/plugin-scaffolder-common': minor
+'@backstage/plugin-scaffolder-react': minor
+'@backstage/plugin-scaffolder-node': minor
+'@backstage/plugin-scaffolder': minor
+---
+
+Move Scaffolder API to OpenAPI
diff --git a/.changeset/clever-plants-warn.md b/.changeset/clever-plants-warn.md
new file mode 100644
index 0000000000..7018aa31ee
--- /dev/null
+++ b/.changeset/clever-plants-warn.md
@@ -0,0 +1,24 @@
+---
+'@backstage/frontend-plugin-api': patch
+'@backstage/frontend-app-api': patch
+---
+
+Add support for a new `aliasFor` option for `createRouteRef`. This allows for the creation of a new route ref that acts as an alias for an existing route ref that is installed in the app. This is particularly useful when creating modules that override existing plugin pages, without referring to the existing plugin. For example:
+
+```tsx
+export default createFrontendModule({
+ pluginId: 'catalog',
+ extensions: [
+ PageBlueprint.make({
+ params: {
+ defaultPath: '/catalog',
+ routeRef: createRouteRef({ aliasFor: 'catalog.catalogIndex' }),
+ loader: () =>
+ import('./CustomCatalogIndexPage').then(m => (
+
+ )),
+ },
+ }),
+ ],
+});
+```
diff --git a/.changeset/cold-heads-arrive.md b/.changeset/cold-heads-arrive.md
new file mode 100644
index 0000000000..1e1f5ff6e2
--- /dev/null
+++ b/.changeset/cold-heads-arrive.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `defaultPath` param of `PageBlueprint` has been renamed to `path`. This change does not affect the compatibility of extensions created with older versions of this blueprint.
diff --git a/.changeset/cold-humans-check.md b/.changeset/cold-humans-check.md
deleted file mode 100644
index 5bcb6caa4b..0000000000
--- a/.changeset/cold-humans-check.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-user-settings': patch
----
-
-plugin-user-settingsgs support i18n
diff --git a/.changeset/cold-lemons-design.md b/.changeset/cold-lemons-design.md
new file mode 100644
index 0000000000..9bdadac9c7
--- /dev/null
+++ b/.changeset/cold-lemons-design.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': patch
+---
+
+Log a warning when `SwappableComponent` extensions are installed outside of using the `app` plugin
diff --git a/.changeset/common-goats-raise.md b/.changeset/common-goats-raise.md
deleted file mode 100644
index c2d797b719..0000000000
--- a/.changeset/common-goats-raise.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-github': patch
----
-
-Use action context logger in Octokit client
diff --git a/.changeset/common-heads-build.md b/.changeset/common-heads-build.md
new file mode 100644
index 0000000000..2874ea7594
--- /dev/null
+++ b/.changeset/common-heads-build.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Fixes some styles on the Select component in BUI.
diff --git a/.changeset/component-refs-app.md b/.changeset/component-refs-app.md
new file mode 100644
index 0000000000..52bfa85c58
--- /dev/null
+++ b/.changeset/component-refs-app.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-app': patch
+---
+
+Default implementations of core components are now provided by this package.
+
+A backwards compatible `componentsApi` implementation is also provided from this package which uses the `SwappableComponentsApi` as the implementation. This backwards compatible wrapper will be removed in the future.
diff --git a/.changeset/component-refs-breaking-app.md b/.changeset/component-refs-breaking-app.md
new file mode 100644
index 0000000000..9ba6307f60
--- /dev/null
+++ b/.changeset/component-refs-breaking-app.md
@@ -0,0 +1,15 @@
+---
+'@backstage/plugin-app': minor
+---
+
+**BREAKING**: The `componentsApi` implementation has been removed from the plugin and replaced with the new `SwappableComponentsApi` instead.
+
+If you were overriding the `componentsApi` implementation, you can now use the new `SwappableComponentsApi` instead.
+
+```ts
+// old
+appPlugin.getExtension('api:app/components').override(...)
+
+// new
+appPlugin.getExtension('api:app/swappable-components').override(...)
+```
diff --git a/.changeset/component-refs-breaking-frontend-plugin-api.md b/.changeset/component-refs-breaking-frontend-plugin-api.md
new file mode 100644
index 0000000000..47c40865d3
--- /dev/null
+++ b/.changeset/component-refs-breaking-frontend-plugin-api.md
@@ -0,0 +1,96 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The component system has been overhauled to use `SwappableComponent` instead of `ComponentRef`. Several APIs have been removed and replaced:
+
+- Removed: `createComponentRef`, `createComponentExtension`, `ComponentRef`, `ComponentsApi`, `componentsApiRef`, `useComponentRef`, `coreComponentRefs`
+- Added: `createSwappableComponent`, `SwappableComponentBlueprint`, `SwappableComponentRef`, `SwappableComponentsApi`, `swappableComponentsApiRef`
+
+**BREAKING**: The default `componentRefs` and exported `Core*Props` have been removed and have replacement `SwappableComponents` and revised type names instead.
+
+- The `errorBoundaryFallback` component and `CoreErrorBoundaryFallbackProps` type have been replaced with `ErrorDisplay` swappable component and `CoreErrorDisplayProps` respectively.
+- The `progress` component and `CoreProgressProps` type have been replaced with `Progress` swappable component and `ProgressProps` respectively.
+- The `notFoundErrorPage` component and `CoreNotFoundErrorPageProps` type have been replaced with `NotFoundErrorPage` swappable component and `NotFoundErrorPageProps` respectively.
+
+**Migration for creating swappable components:**
+
+```tsx
+// OLD: Using createComponentRef and createComponentExtension
+import {
+ createComponentRef,
+ createComponentExtension,
+} from '@backstage/frontend-plugin-api';
+
+const myComponentRef = createComponentRef<{ title: string }>({
+ id: 'my-plugin.my-component',
+});
+
+const myComponentExtension = createComponentExtension({
+ ref: myComponentRef,
+ loader: {
+ lazy: () => import('./MyComponent').then(m => m.MyComponent),
+ },
+});
+
+// NEW: Using createSwappableComponent and SwappableComponentBlueprint
+import {
+ createSwappableComponent,
+ SwappableComponentBlueprint,
+} from '@backstage/frontend-plugin-api';
+
+const MySwappableComponent = createSwappableComponent({
+ id: 'my-plugin.my-component',
+ loader: () => import('./MyComponent').then(m => m.MyComponent),
+});
+
+const myComponentExtension = SwappableComponentBlueprint.make({
+ name: 'my-component',
+ params: {
+ component: MySwappableComponent,
+ loader: () => import('./MyComponent').then(m => m.MyComponent),
+ },
+});
+```
+
+**Migration for using components:**
+
+```tsx
+// OLD: Using ComponentsApi and useComponentRef
+import {
+ useComponentRef,
+ componentsApiRef,
+ useApi,
+ coreComponentRefs,
+} from '@backstage/frontend-plugin-api';
+
+const MyComponent = useComponentRef(myComponentRef);
+const ProgressComponent = useComponentRef(coreComponentRefs.progress);
+
+
+// NEW: Direct component usage
+import { Progress } from '@backstage/frontend-plugin-api';
+
+// Use directly as React Component
+
+
+```
+
+**Migration for core component references:**
+
+```tsx
+// OLD: Core component refs
+import { coreComponentRefs } from '@backstage/frontend-plugin-api';
+
+coreComponentRefs.progress
+coreComponentRefs.notFoundErrorPage
+coreComponentRefs.errorBoundaryFallback
+
+// NEW: Direct swappable component imports
+import { Progress, NotFoundErrorPage, ErrorDisplay } from '@backstage/frontend-plugin-api';
+
+// Use directly as React components
+
+
+
+```
diff --git a/.changeset/cool-bikes-push.md b/.changeset/cool-bikes-push.md
deleted file mode 100644
index 00825c1ad0..0000000000
--- a/.changeset/cool-bikes-push.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-app-api': patch
----
-
-Updated `I18nextTranslationApi` to support interpolation of JSX elements.
diff --git a/.changeset/cool-cities-grab.md b/.changeset/cool-cities-grab.md
deleted file mode 100644
index 372ca9887f..0000000000
--- a/.changeset/cool-cities-grab.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-`LogViewer` now supports a `textWrap` prop that wraps log lines to the next line for overflowing content instead of using horizontal scroll
diff --git a/.changeset/cool-colts-float.md b/.changeset/cool-colts-float.md
deleted file mode 100644
index c001f81ade..0000000000
--- a/.changeset/cool-colts-float.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/repo-tools': patch
----
-
-Support passing additional properties to OpenAPI server generator
diff --git a/.changeset/cool-knives-design.md b/.changeset/cool-knives-design.md
deleted file mode 100644
index 63197edd16..0000000000
--- a/.changeset/cool-knives-design.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/frontend-plugin-api': patch
----
-
-The `id` option of `createFrontendPlugin` has been renamed to `pluginId` in order to better align with similar APIs in the frontend and backend systems.
-
-The old `id` option is deprecated and will be removed in a future release.
diff --git a/.changeset/crazy-chefs-sin.md b/.changeset/crazy-chefs-sin.md
deleted file mode 100644
index 8d33add929..0000000000
--- a/.changeset/crazy-chefs-sin.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-notifications-backend-module-slack': patch
----
-
-Fix slack notification processor to handle a notification with an empty description
diff --git a/.changeset/crazy-pants-exist.md b/.changeset/crazy-pants-exist.md
new file mode 100644
index 0000000000..5eca381523
--- /dev/null
+++ b/.changeset/crazy-pants-exist.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': minor
+---
+
+Added plugin and module templates for the new frontend system. These templates are not included by default, but can be included by adding `@backstage/cli/templates/new-frontend-plugin` and `@backstage/cli/templates/new-frontend-plugin-module` as [custom templates](https://backstage.io/docs/tooling/cli/templates#installing-custom-templates).
diff --git a/.changeset/create-app-1745325336.md b/.changeset/create-app-1753196727.md
similarity index 100%
rename from .changeset/create-app-1745325336.md
rename to .changeset/create-app-1753196727.md
diff --git a/.changeset/create-app-1745936753.md b/.changeset/create-app-1754401469.md
similarity index 100%
rename from .changeset/create-app-1745936753.md
rename to .changeset/create-app-1754401469.md
diff --git a/.changeset/cruel-bars-buy.md b/.changeset/cruel-bars-buy.md
new file mode 100644
index 0000000000..d172551428
--- /dev/null
+++ b/.changeset/cruel-bars-buy.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-test-utils': patch
+---
+
+Updated import of the `FrontendFeature` type.
diff --git a/.changeset/cruel-lights-sip.md b/.changeset/cruel-lights-sip.md
deleted file mode 100644
index b38ab052a9..0000000000
--- a/.changeset/cruel-lights-sip.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend-module-github-provider': patch
----
-
-Added missing types package
diff --git a/.changeset/fruity-bags-flow.md b/.changeset/cruel-zoos-argue.md
similarity index 73%
rename from .changeset/fruity-bags-flow.md
rename to .changeset/cruel-zoos-argue.md
index bc6034a489..eb59d2d85b 100644
--- a/.changeset/fruity-bags-flow.md
+++ b/.changeset/cruel-zoos-argue.md
@@ -1,23 +1,21 @@
---
'@backstage/plugin-catalog-unprocessed-entities': patch
-'@backstage/frontend-test-utils': patch
+'@backstage/frontend-defaults': patch
'@backstage/core-compat-api': patch
'@backstage/plugin-app-visualizer': patch
'@backstage/plugin-catalog-import': patch
'@backstage/plugin-catalog-graph': patch
'@backstage/plugin-notifications': patch
'@backstage/plugin-user-settings': patch
+'@backstage/plugin-search-react': patch
'@backstage/plugin-kubernetes': patch
'@backstage/plugin-scaffolder': patch
'@backstage/plugin-api-docs': patch
'@backstage/plugin-devtools': patch
'@backstage/plugin-techdocs': patch
'@backstage/plugin-catalog': patch
-'@backstage/plugin-signals': patch
'@backstage/plugin-search': patch
'@backstage/plugin-home': patch
-'@backstage/plugin-app': patch
-'@backstage/plugin-org': patch
---
-Internal update to use the new `pluginId` option of `createFrontendPlugin`.
+Internal update to align with new blueprint parameter naming in the new frontend system.
diff --git a/.changeset/cyan-pots-appear.md b/.changeset/cyan-pots-appear.md
deleted file mode 100644
index f82f4548c3..0000000000
--- a/.changeset/cyan-pots-appear.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-unprocessed': minor
----
-
-**BREAKING** Removed support for the legacy backend and removed references to `@backstage/backend-common`, please [migrate to the new backend system](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating)
diff --git a/.changeset/deep-apples-attack.md b/.changeset/deep-apples-attack.md
new file mode 100644
index 0000000000..abf34ad863
--- /dev/null
+++ b/.changeset/deep-apples-attack.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend-module-gitlab': patch
+---
+
+Show additional information about the cause in error messages from GitLab
diff --git a/.changeset/deep-mangos-dig.md b/.changeset/deep-mangos-dig.md
new file mode 100644
index 0000000000..237f625e27
--- /dev/null
+++ b/.changeset/deep-mangos-dig.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Attempt to circumvent event listener memory leak in compression middleware
diff --git a/.changeset/deep-ties-move.md b/.changeset/deep-ties-move.md
deleted file mode 100644
index 57f6c7772c..0000000000
--- a/.changeset/deep-ties-move.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-ldap': patch
----
-
-Improves error reporting for missing metadata.name in LDAP catalog provider.
diff --git a/.changeset/dirty-grapes-vanish.md b/.changeset/dirty-grapes-vanish.md
deleted file mode 100644
index b78660d21e..0000000000
--- a/.changeset/dirty-grapes-vanish.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/backend-defaults': minor
----
-
-**BREAKING**: The `DefaultSchedulerService` constructor options now requires `RootLifecycleService`, `HttpRouterService`, and `PluginMetadataService` fields.
-
-The scheduler will register a REST API for listing and triggering tasks. Please see [the scheduler documentation](https://backstage.io/docs/backend-system/core-services/scheduler) for more details about this API.
diff --git a/.changeset/dry-carpets-hope.md b/.changeset/dry-carpets-hope.md
deleted file mode 100644
index 569e089a66..0000000000
--- a/.changeset/dry-carpets-hope.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-backstage-openapi': patch
----
-
-Do not swallow errors; instead allow them to bubble up to the task scheduler for better tracking and logging.
diff --git a/.changeset/dull-doodles-trade.md b/.changeset/dull-doodles-trade.md
deleted file mode 100644
index eb9399fcc7..0000000000
--- a/.changeset/dull-doodles-trade.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-kubernetes-backend': patch
----
-
-Changed logging of cluster details to debug to minimise log clutter.
diff --git a/.changeset/early-colts-accept.md b/.changeset/early-colts-accept.md
deleted file mode 100644
index ff583144f0..0000000000
--- a/.changeset/early-colts-accept.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/backend-dynamic-feature-service': patch
----
-
-Fixed various typos.
-`FrontendRemoteResolver`'s misspelled `getAdditionaRemoteInfo` has been deprecated. Use the correct spelling `getAdditionalRemoteInfo` instead.
diff --git a/.changeset/early-dryers-teach.md b/.changeset/early-dryers-teach.md
deleted file mode 100644
index d747fbc730..0000000000
--- a/.changeset/early-dryers-teach.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-node': minor
----
-
-Added `parseEntityYaml` from `@backstage/plugin-catalog-backend`, to make it more easily usable by custom plugins and modules
diff --git a/.changeset/eight-sloths-walk.md b/.changeset/eight-sloths-walk.md
new file mode 100644
index 0000000000..666069ce8b
--- /dev/null
+++ b/.changeset/eight-sloths-walk.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Removed the deprecated `createFrontendPlugin` variant where the plugin ID is passed via an `id` option. To update existing code, switch to using the `pluginId` option instead.
diff --git a/.changeset/eight-toys-feel.md b/.changeset/eight-toys-feel.md
deleted file mode 100644
index c0f5a12c40..0000000000
--- a/.changeset/eight-toys-feel.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-'@backstage/backend-app-api': patch
----
-
-Added a configuration to permit backend plugin module failures on startup:
-
-```yaml
-backend:
- ...
- startup:
- plugins:
- plugin-x:
- modules:
- module-y:
- onPluginModuleBootFailure: continue
-```
-
-This configuration permits `plugin-x` with `module-y` to fail on startup. Omitting the
-`onPluginModuleBootFailure` configuration matches the previous behavior, wherein any
-individual plugin module failure is forwarded to the plugin and aborts backend startup.
-
-The default can also be changed, so that continuing on failure is the default
-unless otherwise specified:
-
-```yaml
-backend:
- startup:
- default:
- onPluginModuleBootFailure: continue
- plugins:
- catalog:
- modules:
- github:
- onPluginModuleBootFailure: abort
-```
diff --git a/.changeset/eleven-ghosts-strive.md b/.changeset/eleven-ghosts-strive.md
deleted file mode 100644
index ac48c19524..0000000000
--- a/.changeset/eleven-ghosts-strive.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder': patch
----
-
-Full support in EntityPicker (and derivatives) for default EntityPresentationApi
diff --git a/.changeset/eleven-tigers-drop.md b/.changeset/eleven-tigers-drop.md
new file mode 100644
index 0000000000..ea2702cfb5
--- /dev/null
+++ b/.changeset/eleven-tigers-drop.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-home': patch
+---
+
+Add the missing Visits API to the alpha plugin, fixing a crash due to the API not being installed.
diff --git a/.changeset/empty-years-grow.md b/.changeset/empty-years-grow.md
new file mode 100644
index 0000000000..17a5ef0e36
--- /dev/null
+++ b/.changeset/empty-years-grow.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': minor
+---
+
+We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood.
diff --git a/.changeset/every-schools-find.md b/.changeset/every-schools-find.md
new file mode 100644
index 0000000000..b4cb15bf52
--- /dev/null
+++ b/.changeset/every-schools-find.md
@@ -0,0 +1,20 @@
+---
+'@backstage/plugin-catalog-unprocessed-entities': patch
+'@backstage/frontend-app-api': patch
+'@backstage/core-compat-api': patch
+'@backstage/plugin-scaffolder-react': patch
+'@backstage/plugin-catalog-import': patch
+'@backstage/plugin-notifications': patch
+'@backstage/plugin-kubernetes': patch
+'@backstage/plugin-scaffolder': patch
+'@backstage/plugin-api-docs': patch
+'@backstage/plugin-devtools': patch
+'@backstage/plugin-techdocs': patch
+'@backstage/plugin-catalog': patch
+'@backstage/plugin-signals': patch
+'@backstage/plugin-search': patch
+'@backstage/plugin-home': patch
+'@backstage/plugin-app': patch
+---
+
+Internal update to use the new variant of `ApiBlueprint`.
diff --git a/.changeset/evil-forks-hang.md b/.changeset/evil-forks-hang.md
new file mode 100644
index 0000000000..f261c48c2b
--- /dev/null
+++ b/.changeset/evil-forks-hang.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': minor
+---
+
+Added the `analyzeLocation` method to `catalogApiMock`
diff --git a/.changeset/evil-phones-unite.md b/.changeset/evil-phones-unite.md
new file mode 100644
index 0000000000..9a3e4ff151
--- /dev/null
+++ b/.changeset/evil-phones-unite.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Support `filter` parameter on the `EntityHeaderBlueprint`
diff --git a/.changeset/famous-cities-stand.md b/.changeset/famous-cities-stand.md
deleted file mode 100644
index 86ba727997..0000000000
--- a/.changeset/famous-cities-stand.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-auth-node': patch
----
-
-Added the `identity` property to `BackstageSignInResult`.
-
-The `prepareBackstageIdentityResponse` function will now also forward the `identity` to the response if present in the provided sign-in result.
diff --git a/.changeset/fancy-ducks-help.md b/.changeset/fancy-ducks-help.md
new file mode 100644
index 0000000000..06cfc23309
--- /dev/null
+++ b/.changeset/fancy-ducks-help.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Removed the `routable` property from `ExtensionBoundary`. This property was never needed in practice and is instead inferred from whether or not the extension outputs a route reference. It can be safely removed.
diff --git a/.changeset/fancy-frogs-like.md b/.changeset/fancy-frogs-like.md
deleted file mode 100644
index ed3a9fbf81..0000000000
--- a/.changeset/fancy-frogs-like.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Internal code cleanup
diff --git a/.changeset/fast-jars-push.md b/.changeset/fast-jars-push.md
new file mode 100644
index 0000000000..2073e008eb
--- /dev/null
+++ b/.changeset/fast-jars-push.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `ResolveInputValueOverrides` type is no longer exported.
diff --git a/.changeset/fifty-ads-dance.md b/.changeset/fifty-ads-dance.md
new file mode 100644
index 0000000000..79801caafd
--- /dev/null
+++ b/.changeset/fifty-ads-dance.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Fixes a couple of small bugs in BUI including setting H1 and H2 correctly on the Header and HeaderPage.
diff --git a/.changeset/five-ducks-hide.md b/.changeset/five-ducks-hide.md
new file mode 100644
index 0000000000..6ce1fec8f7
--- /dev/null
+++ b/.changeset/five-ducks-hide.md
@@ -0,0 +1,31 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `NavLogoBlueprint` has been removed and replaced by `NavContentBlueprint`, which instead replaces the entire navbar. The default navbar has also been switched to a more minimal implementation.
+
+To use `NavContentBlueprint` to install new logos, you can use it as follows:
+
+```tsx
+NavContentBlueprint.make({
+ params: {
+ component: ({ items }) => {
+ return compatWrapper(
+
+
+
+ {/* Other sidebar content */}
+
+
+ {items.map((item, index) => (
+
+ ))}
+
+
+ {/* Other sidebar content */}
+ ,
+ );
+ },
+ },
+});
+```
diff --git a/.changeset/floppy-days-tell.md b/.changeset/floppy-days-tell.md
deleted file mode 100644
index 2eb184f6fe..0000000000
--- a/.changeset/floppy-days-tell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-For improved a11y, clicking a Select component label now focuses the Select trigger element, and the TextField component's label is now styled to indicate it's interactive.
diff --git a/.changeset/floppy-groups-hug.md b/.changeset/floppy-groups-hug.md
new file mode 100644
index 0000000000..6e47ecaaf0
--- /dev/null
+++ b/.changeset/floppy-groups-hug.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: Removed the ability to define a default extension `name` in blueprints. This option had no practical purpose as blueprints already use the `kind` to identity the source of the extension.
diff --git a/.changeset/fluffy-otters-cry.md b/.changeset/fluffy-otters-cry.md
new file mode 100644
index 0000000000..fd24a0bb47
--- /dev/null
+++ b/.changeset/fluffy-otters-cry.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': minor
+---
+
+Use an app plugin for built-in extension app node specs.
diff --git a/.changeset/four-peaches-talk.md b/.changeset/four-peaches-talk.md
deleted file mode 100644
index 4b0d2e8a47..0000000000
--- a/.changeset/four-peaches-talk.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Internal refactor of opaque type handling.
diff --git a/.changeset/four-spiders-jump.md b/.changeset/four-spiders-jump.md
new file mode 100644
index 0000000000..d5a92b8745
--- /dev/null
+++ b/.changeset/four-spiders-jump.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': patch
+---
+
+Added a new module for implementing public sign-in apps, exported as `appModulePublicSignIn` via the `/alpha` sub-path export. This replaces the `createPublicSignInApp` export from `@backstage/frontend-defaults`, which is now deprecated.
diff --git a/.changeset/free-months-share.md b/.changeset/free-months-share.md
new file mode 100644
index 0000000000..42e47a973d
--- /dev/null
+++ b/.changeset/free-months-share.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': minor
+---
+
+**BREAKING**: Removed the deprecated `FrontendFeature` type, import it from `@backstage/frontend-plugin-api` instead.
diff --git a/.changeset/fruity-rockets-rhyme.md b/.changeset/fruity-rockets-rhyme.md
new file mode 100644
index 0000000000..13e957c5f1
--- /dev/null
+++ b/.changeset/fruity-rockets-rhyme.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': minor
+---
+
+**BREAKING**: Removed the deprecated `CreateAppFeatureLoader` and support for it in other APIs. Switch existing usage to use the newer `createFrontendFeatureLoader` from `@backstage/frontend-plugin-api` instead.
diff --git a/.changeset/full-streets-take.md b/.changeset/full-streets-take.md
new file mode 100644
index 0000000000..f04cd92c57
--- /dev/null
+++ b/.changeset/full-streets-take.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': minor
+---
+
+Updated the `app/nav` extension to use the new `NavContentBlueprint`, and removed support for extensions created with the now removed `NavLogoBlueprint`.
diff --git a/.changeset/funny-brooms-trade.md b/.changeset/funny-brooms-trade.md
new file mode 100644
index 0000000000..2a0b94bb13
--- /dev/null
+++ b/.changeset/funny-brooms-trade.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The separate `RouteResolutionApiResolveOptions` type has been removed.
diff --git a/.changeset/funny-dancers-start.md b/.changeset/funny-dancers-start.md
new file mode 100644
index 0000000000..267585f8b2
--- /dev/null
+++ b/.changeset/funny-dancers-start.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Update styling of Tooltip element
diff --git a/.changeset/fuzzy-ducks-jump.md b/.changeset/fuzzy-ducks-jump.md
new file mode 100644
index 0000000000..1a4064dc91
--- /dev/null
+++ b/.changeset/fuzzy-ducks-jump.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-compat-api': patch
+---
+
+The `compatWrapper` has been switched to use the new `SwappableComponentsApi` instead of the old `ComponentsApi` in its bridging to the old frontend system.
diff --git a/.changeset/fuzzy-ducks-speak.md b/.changeset/fuzzy-ducks-speak.md
new file mode 100644
index 0000000000..30e23c7ca5
--- /dev/null
+++ b/.changeset/fuzzy-ducks-speak.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend-module-gitlab': patch
+---
+
+The `description` property in `publish:gitlab:merge-request` has been made optional again to comply with the GitLab API.
diff --git a/.changeset/gentle-cars-arrive.md b/.changeset/gentle-cars-arrive.md
new file mode 100644
index 0000000000..d6fd765302
--- /dev/null
+++ b/.changeset/gentle-cars-arrive.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-kubernetes-backend': minor
+---
+
+**BREAKING CHANGE**: Removed support for the legacy backend system. This means that the deprecated `createRouter` and `KubernetesBuilder` and related types have been removed. Please refer to the [relevant documentation](https://backstage.io/docs/features/kubernetes/installation/#adding-kubernetes-backend-plugin) to configure the Kubernetes plugin.
+
+**BREAKING CHANGE**: The deprecated types `AuthenticationStrategy`, `AuthMetadata`, `ClusterDetails`, `CustomResource`, `CustomResourcesByEntity`, `FetchResponseWrapper`, `KubernetesBuilder`, `KubernetesBuilderReturn`, `KubernetesClustersSupplier`, `KubernetesCredential`, `KubernetesEnvironment`, `KubernetesFetcher`, `KubernetesObjectsProvider`, `KubernetesObjectTypes`, `KubernetesServiceLocator`,`ObjectFetchParams`, `ObjectToFetch`,`RouterOptions` and `ServiceLocatorRequestContext` should all now be imported from `@backstage/plugin-kubernetes-node`.
diff --git a/.changeset/good-islands-drive.md b/.changeset/good-islands-drive.md
deleted file mode 100644
index 5b909dc84f..0000000000
--- a/.changeset/good-islands-drive.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Added `info` object to the context of the alpha CLI.
diff --git a/.changeset/great-hounds-fix.md b/.changeset/great-hounds-fix.md
new file mode 100644
index 0000000000..a7cc488ecb
--- /dev/null
+++ b/.changeset/great-hounds-fix.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': minor
+---
+
+Fixed fs:readdir action example
diff --git a/.changeset/great-snakes-dress.md b/.changeset/great-snakes-dress.md
new file mode 100644
index 0000000000..404bdab03c
--- /dev/null
+++ b/.changeset/great-snakes-dress.md
@@ -0,0 +1,5 @@
+---
+'@backstage/theme': patch
+---
+
+We are introducing two new data attributes on the `body` to support Backstage UI (BUI) new theming system.
diff --git a/.changeset/green-lies-invite copy.md b/.changeset/green-lies-invite copy.md
new file mode 100644
index 0000000000..469ed2fbac
--- /dev/null
+++ b/.changeset/green-lies-invite copy.md
@@ -0,0 +1,39 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: In an attempt to align some of the API's around providing components to `Blueprints`, we've renamed the parameters for both the `RouterBlueprint` and `AppRootWrapperBlueprint` from `Component` to `component`.
+
+```tsx
+// old
+RouterBlueprint.make({
+ params: {
+ Component: ({ children }) =>
{children}
,
+ },
+});
+
+// new
+RouterBlueprint.make({
+ params: {
+ component: ({ children }) =>
{children}
,
+ },
+});
+```
+
+```tsx
+// old
+AppRootWrapperBlueprint.make({
+ params: {
+ Component: ({ children }) =>
{children}
,
+ },
+});
+
+// new
+AppRootWrapperBlueprint.make({
+ params: {
+ component: ({ children }) =>
{children}
,
+ },
+});
+```
+
+As part of this change, the type for `component` has also changed from `ComponentType>` to `(props: { children: ReactNode }) => JSX.Element | null` which is not breaking, just a little more reflective of the actual expected component.
diff --git a/.changeset/green-lies-invite.md b/.changeset/green-lies-invite.md
new file mode 100644
index 0000000000..92ccc2324d
--- /dev/null
+++ b/.changeset/green-lies-invite.md
@@ -0,0 +1,7 @@
+---
+'@backstage/frontend-test-utils': patch
+'@backstage/core-compat-api': patch
+'@backstage/plugin-app': patch
+---
+
+Updated the usage of the `RouterBlueprint` and `AppRootWrapperBlueprint` to use the lowercase `component` parameter
diff --git a/.changeset/green-trainers-float.md b/.changeset/green-trainers-float.md
deleted file mode 100644
index 537fe01736..0000000000
--- a/.changeset/green-trainers-float.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder': patch
----
-
-Fix EntityPicker field to render description as markdown, matching other form components in the system.
diff --git a/.changeset/heavy-baths-rule.md b/.changeset/heavy-baths-rule.md
deleted file mode 100644
index 09f26e8b57..0000000000
--- a/.changeset/heavy-baths-rule.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-github': minor
----
-
-**BREAKING** The `GithubLocationAnalyzer` now requires the `AuthService` and the `CatalogService` when being constructed and the `TokenManger` has been removed.
diff --git a/.changeset/heavy-onions-swim.md b/.changeset/heavy-onions-swim.md
deleted file mode 100644
index 42ba056c1e..0000000000
--- a/.changeset/heavy-onions-swim.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': minor
----
-
-Added `workspace:template` and `workspace:template:file` actions to complement respective `fetch:*` actions
diff --git a/.changeset/honest-moons-rest.md b/.changeset/honest-moons-rest.md
new file mode 100644
index 0000000000..d7540ea3e0
--- /dev/null
+++ b/.changeset/honest-moons-rest.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+**Breaking change** Move breadcrumb to fit in the `HeaderPage` instead of the `Header` in Backstage UI.
diff --git a/.changeset/honest-seas-repeat.md b/.changeset/honest-seas-repeat.md
new file mode 100644
index 0000000000..99f1ceaeb2
--- /dev/null
+++ b/.changeset/honest-seas-repeat.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': minor
+---
+
+**BREAKING**: The `app-root-element` extension now only accepts `JSX.Element` in its `element` param, meaning overrides need to be updated.
diff --git a/.changeset/honest-snakes-draw.md b/.changeset/honest-snakes-draw.md
new file mode 100644
index 0000000000..f7a5ffe830
--- /dev/null
+++ b/.changeset/honest-snakes-draw.md
@@ -0,0 +1,23 @@
+---
+'@backstage/cli': minor
+---
+
+**BREAKING**: The new app build based on [Rspack](https://rspack.dev/) is now the default, and the `EXPERIMENTAL_RSPACK` flag has been removed. To revert to the old behavior, set the `LEGACY_WEBPACK_BUILD` environment flag and install the following optional dependencies:
+
+```json
+{
+ "dependencies": {
+ "@module-federation/enhanced": "^0.9.0",
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
+ "esbuild-loader": "^4.0.0",
+ "eslint-webpack-plugin": "^4.2.0",
+ "fork-ts-checker-webpack-plugin": "^9.0.0",
+ "mini-css-extract-plugin": "^2.4.2",
+ "terser-webpack-plugin": "^5.1.3",
+ "webpack": "^5.96.0",
+ "webpack-dev-server": "^5.0.0"
+ }
+}
+```
+
+If you do encounter a blocking issue that forces you to use the old WebPack build, please [open an issue](https://github.com/backstage/backstage/issues) explaining the problem. The WebPack build will be removed in a future release.
diff --git a/.changeset/hot-clowns-behave.md b/.changeset/hot-clowns-behave.md
new file mode 100644
index 0000000000..3c7e9dec12
--- /dev/null
+++ b/.changeset/hot-clowns-behave.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Adding `type` as an override to the `convertLegacyEntityCardExtension`
diff --git a/.changeset/huge-heads-occur.md b/.changeset/huge-heads-occur.md
new file mode 100644
index 0000000000..1972037cf0
--- /dev/null
+++ b/.changeset/huge-heads-occur.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-azure': patch
+---
+
+`host` should be optional in `config` schema
diff --git a/.changeset/huge-olives-do.md b/.changeset/huge-olives-do.md
deleted file mode 100644
index 61eb37559f..0000000000
--- a/.changeset/huge-olives-do.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-events-backend-module-gitlab': patch
----
-
-Adds support for `object_kind` field with priority over `event_name` on Gitlab webhook event types
diff --git a/.changeset/huge-paws-design.md b/.changeset/huge-paws-design.md
new file mode 100644
index 0000000000..8d90435480
--- /dev/null
+++ b/.changeset/huge-paws-design.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+We are motion away from `motion` to use `gsap` instead to make Backstage UI backward compatible with React 17.
diff --git a/.changeset/icy-mugs-glow.md b/.changeset/icy-mugs-glow.md
deleted file mode 100644
index 553daff24a..0000000000
--- a/.changeset/icy-mugs-glow.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-bitbucket-cloud-common': patch
----
-
-Add support for `repo:updated` events as `Events.RepoUpdatedEvent`.
diff --git a/.changeset/itchy-doodles-boil.md b/.changeset/itchy-doodles-boil.md
new file mode 100644
index 0000000000..727a0ed01b
--- /dev/null
+++ b/.changeset/itchy-doodles-boil.md
@@ -0,0 +1,12 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `AnyRoutes` and `AnyExternalRoutes` types have been removed and their usage has been inlined instead.
+
+Existing usage can be replaced according to their previous definitions:
+
+```ts
+type AnyRoutes = { [name in string]: RouteRef | SubRouteRef };
+type AnyExternalRoutes = { [name in string]: ExternalRouteRef };
+```
diff --git a/.changeset/khaki-grapes-sink.md b/.changeset/khaki-grapes-sink.md
deleted file mode 100644
index d96521e029..0000000000
--- a/.changeset/khaki-grapes-sink.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-Added new icon and onClear props to the TextField to make it easier to accessorize inputs.
diff --git a/.changeset/large-experts-sort.md b/.changeset/large-experts-sort.md
deleted file mode 100644
index 6d58836db7..0000000000
--- a/.changeset/large-experts-sort.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-events-backend-module-github': minor
----
-
-**BREAKING**: Removed the `createGithubSignatureValidator` export.
-
-Added support webhook validation based on `integrations.github.[].apps.[].webhookSecret`.
diff --git a/.changeset/large-lemons-clap.md b/.changeset/large-lemons-clap.md
deleted file mode 100644
index cf1a3eed5d..0000000000
--- a/.changeset/large-lemons-clap.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/backend-plugin-api': patch
-'@backstage/backend-defaults': patch
-'@backstage/integration': patch
----
-
-update documentation
diff --git a/.changeset/late-squids-feel.md b/.changeset/late-squids-feel.md
new file mode 100644
index 0000000000..f527152c8b
--- /dev/null
+++ b/.changeset/late-squids-feel.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-proxy-backend': patch
+---
+
+correct rewrite rule to avoid extra subpath in proxy path
diff --git a/.changeset/lazy-tires-show.md b/.changeset/lazy-tires-show.md
deleted file mode 100644
index 3ccf5f155e..0000000000
--- a/.changeset/lazy-tires-show.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-permission-backend': minor
-'@backstage/plugin-permission-common': minor
-'@backstage/plugin-permission-node': minor
----
-
-Fixed an issue causing the `PermissionClient` to exhaust the request body size limit too quickly when making many requests.
diff --git a/.changeset/lemon-ways-lay.md b/.changeset/lemon-ways-lay.md
new file mode 100644
index 0000000000..725e57c141
--- /dev/null
+++ b/.changeset/lemon-ways-lay.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': patch
+---
+
+Renaming the `getNodesByRoutePath` parameter from `sourcePath` to `routePath`
diff --git a/.changeset/little-bugs-care.md b/.changeset/little-bugs-care.md
new file mode 100644
index 0000000000..930cbd0e21
--- /dev/null
+++ b/.changeset/little-bugs-care.md
@@ -0,0 +1,5 @@
+---
+'@backstage/catalog-client': minor
+---
+
+Added the analyze-location endpoint to the CatalogClient
diff --git a/.changeset/long-grapes-glow.md b/.changeset/long-grapes-glow.md
new file mode 100644
index 0000000000..e0e805ed87
--- /dev/null
+++ b/.changeset/long-grapes-glow.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-node': minor
+---
+
+Added the analyze-location endpoint to the CatalogService
diff --git a/.changeset/lovely-cats-take.md b/.changeset/lovely-cats-take.md
deleted file mode 100644
index ab1ee1c249..0000000000
--- a/.changeset/lovely-cats-take.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
----
-
-Support Bitbucket Cloud's `repo:updated` events at `BitbucketCloudEntityProvider`.
-
-To make use of the new event type, you have to configure your webhook or add a new ones
-that delivers this event type to Backstage similar to `repo:push` before.
-
-Only `repo:updated` events that modify a repository's URL (e.g., due to a name change)
-will cause changes (removing the "old", adding the "new" repository).
diff --git a/.changeset/lovely-fans-write.md b/.changeset/lovely-fans-write.md
new file mode 100644
index 0000000000..71b02f2bde
--- /dev/null
+++ b/.changeset/lovely-fans-write.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+differentiate between entirely and partially composite schemas in schema rendering
diff --git a/.changeset/major-comics-stay.md b/.changeset/major-comics-stay.md
new file mode 100644
index 0000000000..b8000bd0c5
--- /dev/null
+++ b/.changeset/major-comics-stay.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-compat-api': minor
+---
+
+**BREAKING**: The `defaultPath` override of `convertLegacyPageExtension` has been renamed to `path`, in order to align with the same update that was made to the `PageBlueprint`.
diff --git a/.changeset/mean-parents-build.md b/.changeset/mean-parents-build.md
deleted file mode 100644
index d3bba29019..0000000000
--- a/.changeset/mean-parents-build.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-Pin version of @base-ui-components/react.
diff --git a/.changeset/mighty-carrots-decide.md b/.changeset/mighty-carrots-decide.md
deleted file mode 100644
index 68f210da48..0000000000
--- a/.changeset/mighty-carrots-decide.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-react': minor
----
-
-Allow search filters to provide labels and values separately, and not only values
diff --git a/.changeset/mighty-cycles-stay.md b/.changeset/mighty-cycles-stay.md
new file mode 100644
index 0000000000..cb1bb3646e
--- /dev/null
+++ b/.changeset/mighty-cycles-stay.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-scaffolder': patch
+'@backstage/plugin-scaffolder-react': patch
+---
+
+Export `FormField` type from `/alpha` in `-react` package, and internal refactor.
diff --git a/.changeset/mira-looking-ostrich.md b/.changeset/mira-looking-ostrich.md
new file mode 100644
index 0000000000..fb85b10d0d
--- /dev/null
+++ b/.changeset/mira-looking-ostrich.md
@@ -0,0 +1,18 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Plugins should now use the new `AnalyticsImplementationBlueprint` to define and provide concrete analytics implementations. For example:
+
+```ts
+import { AnalyticsImplementationBlueprint } from '@backstage/frontend-plugin-api';
+
+const AcmeAnalytics = AnalyticsImplementationBlueprint.make({
+ name: 'acme-analytics',
+ params: define =>
+ define({
+ deps: { config: configApiRef },
+ factory: ({ config }) => AcmeAnalyticsImpl.fromConfig(config),
+ }),
+});
+```
diff --git a/.changeset/moody-clowns-hear.md b/.changeset/moody-clowns-hear.md
new file mode 100644
index 0000000000..d2f45e2d91
--- /dev/null
+++ b/.changeset/moody-clowns-hear.md
@@ -0,0 +1,13 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Make the processing hash calculation not care about the order of the processors.
+
+This change does not affect the behavior of the catalog, but it will make the processing
+hash calculation more robust against changes in the order of processors. This should lead to
+more stable processing hashes, which in turn should lead to fewer unnecessary reprocessing
+of entities.
+
+After deploying this fix, you may see a period of increased processing and stitching, but
+this should stabilize over time as the processing hashes become more consistent.
diff --git a/.changeset/neat-glasses-occur.md b/.changeset/neat-glasses-occur.md
deleted file mode 100644
index 5fea5b1886..0000000000
--- a/.changeset/neat-glasses-occur.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-import': patch
----
-
-Add i18n support for `catalog-import` plugin.
diff --git a/.changeset/neat-glasses-occured.md b/.changeset/neat-glasses-occured.md
deleted file mode 100644
index 289e03e243..0000000000
--- a/.changeset/neat-glasses-occured.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-import': minor
----
-
-**BREAKING**: `generateStepper` and `defaultGenerateStepper` now require a translation argument to be passed through for supporting translations.
diff --git a/.changeset/neat-tigers-clap.md b/.changeset/neat-tigers-clap.md
new file mode 100644
index 0000000000..93d114bb29
--- /dev/null
+++ b/.changeset/neat-tigers-clap.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Fixes CSS to adjust based on whether or not the global Backstage sidebar is on the page.
diff --git a/.changeset/nej-inte-ostrich.md b/.changeset/nej-inte-ostrich.md
new file mode 100644
index 0000000000..434708e2e4
--- /dev/null
+++ b/.changeset/nej-inte-ostrich.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app': patch
+---
+
+The default implementation of the Analytics API now collects and instantiates analytics implementations exposed via `AnalyticsImplementationBlueprint` extensions. If no such extensions are discovered, the API continues to do nothing with analytics events fired within Backstage. If multiple such extensions are discovered, every discovered implementation automatically receives analytics events.
diff --git a/.changeset/new-hands-scream.md b/.changeset/new-hands-scream.md
deleted file mode 100644
index 03291648db..0000000000
--- a/.changeset/new-hands-scream.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-auth-backend': minor
----
-
-**BREAKING**: Removed support for the old backend system, and removed all deprecated exports.
-
-If you were using one of the deprecated imports from this package, you will have to follow the instructions in their respective deprecation notices before upgrading. Most of the general utilities are available from `@backstage/plugin-auth-node`, and the specific auth providers are available from dedicated packages such as for example `@backstage/plugin-auth-backend-module-github-provider`. See [the auth docs](https://backstage.io/docs/auth/) for specific instructions.
diff --git a/.changeset/nice-actors-cheer.md b/.changeset/nice-actors-cheer.md
new file mode 100644
index 0000000000..918148ffb8
--- /dev/null
+++ b/.changeset/nice-actors-cheer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Adding a more sensible default order to the default filters
diff --git a/.changeset/nice-buttons-return.md b/.changeset/nice-buttons-return.md
new file mode 100644
index 0000000000..a47a3aa1a7
--- /dev/null
+++ b/.changeset/nice-buttons-return.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': minor
+---
+
+Adds `additionalAllowedURIProtocols` to sanitizer config
diff --git a/.changeset/nice-crabs-clean.md b/.changeset/nice-crabs-clean.md
new file mode 100644
index 0000000000..45690e98aa
--- /dev/null
+++ b/.changeset/nice-crabs-clean.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Support multiple headers in new frontend system, and don't render a header until the entity has finished loading
diff --git a/.changeset/nice-vans-vanish.md b/.changeset/nice-vans-vanish.md
deleted file mode 100644
index c52fc42488..0000000000
--- a/.changeset/nice-vans-vanish.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': minor
----
-
-**Breaking Change** Icons on Button and IconButton now need to be imported and placed like this: } />
diff --git a/.changeset/odd-beans-sell.md b/.changeset/odd-beans-sell.md
new file mode 100644
index 0000000000..13f33e52d3
--- /dev/null
+++ b/.changeset/odd-beans-sell.md
@@ -0,0 +1,40 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `ApiBlueprint` has been updated to use the new advanced type parameters through the new `defineParams` blueprint option. This is an immediate breaking change that requires all existing usages of `ApiBlueprint` to switch to the new callback format. Existing extensions created with the old format are still compatible with the latest version of the plugin API however, meaning that this does not break existing plugins.
+
+To update existing usages of `ApiBlueprint`, you remove the outer level of the `params` object and replace `createApiFactory(...)` with `defineParams => defineParams(...)`.
+
+For example, the following old usage:
+
+```ts
+ApiBlueprint.make({
+ name: 'error',
+ params: {
+ factory: createApiFactory({
+ api: errorApiRef,
+ deps: { alertApi: alertApiRef },
+ factory: ({ alertApi }) => {
+ return ...;
+ },
+ })
+ },
+})
+```
+
+is migrated to the following:
+
+```ts
+ApiBlueprint.make({
+ name: 'error',
+ params: defineParams =>
+ defineParams({
+ api: errorApiRef,
+ deps: { alertApi: alertApiRef },
+ factory: ({ alertApi }) => {
+ return ...;
+ },
+ }),
+})
+```
diff --git a/.changeset/old-crews-serve.md b/.changeset/old-crews-serve.md
deleted file mode 100644
index db6bb4cf23..0000000000
--- a/.changeset/old-crews-serve.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend-module-incremental-ingestion': minor
----
-
-**BREAKING** Removed support for the legacy backend, please [migrate to the new backend system](https://github.com/backstage/backstage/tree/v1.38.0/plugins/catalog-backend-module-incremental-ingestion#installation). Also, if you were importing from the `/alpha` export of this package, you should remove the `/alpha` part.
diff --git a/.changeset/olive-baths-punch.md b/.changeset/olive-baths-punch.md
new file mode 100644
index 0000000000..6c2a7b8ded
--- /dev/null
+++ b/.changeset/olive-baths-punch.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': minor
+---
+
+**BREAKING**: Removed support for `.icon.svg` imports, which have been deprecated since the 1.19 release.
diff --git a/.changeset/open-bottles-film.md b/.changeset/open-bottles-film.md
new file mode 100644
index 0000000000..68c04f8ada
--- /dev/null
+++ b/.changeset/open-bottles-film.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-catalog-graph': patch
+'@backstage/plugin-api-docs': patch
+'@backstage/plugin-org': patch
+---
+
+Updated README instructions for the new frontend system
diff --git a/.changeset/open-ghosts-fix.md b/.changeset/open-ghosts-fix.md
deleted file mode 100644
index 144f24dea0..0000000000
--- a/.changeset/open-ghosts-fix.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-Fixed an issue with Canon's DataTable.Pagination component showing the wrong number for the "to" count.
diff --git a/.changeset/open-lands-shop.md b/.changeset/open-lands-shop.md
deleted file mode 100644
index 5205e83cbe..0000000000
--- a/.changeset/open-lands-shop.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Update keyboard focus on when clicking hash links. This fixes the issue where the "skip to content" link rendered by Material MkDocs isn't focused when used.
diff --git a/.changeset/open-seas-ring.md b/.changeset/open-seas-ring.md
new file mode 100644
index 0000000000..d8249f940c
--- /dev/null
+++ b/.changeset/open-seas-ring.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+hide pagination `queryparams` if pagination mode is set to none
diff --git a/.changeset/orange-teams-smell.md b/.changeset/orange-teams-smell.md
new file mode 100644
index 0000000000..ed3514d00d
--- /dev/null
+++ b/.changeset/orange-teams-smell.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Tweaked the return types from `createExtension` and `createExtensionBlueprint` to avoid the forwarding of `ConfigurableExtensionDataRef` into exported types.
diff --git a/.changeset/petite-spoons-flash.md b/.changeset/petite-spoons-flash.md
new file mode 100644
index 0000000000..806704f196
--- /dev/null
+++ b/.changeset/petite-spoons-flash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': minor
+---
+
+Add resizable panels width for the editor and preview panels in the template editor and template form playground layouts. Users can now resize these panels by dragging the divider between the two areas.
diff --git a/.changeset/plenty-items-move.md b/.changeset/plenty-items-move.md
new file mode 100644
index 0000000000..6c55010d21
--- /dev/null
+++ b/.changeset/plenty-items-move.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': minor
+---
+
+Backstage UI - HeaderPage - We are updating the breadcrumb to be more visible and accessible.
diff --git a/.changeset/polite-trains-notice.md b/.changeset/polite-trains-notice.md
new file mode 100644
index 0000000000..6b204b2b10
--- /dev/null
+++ b/.changeset/polite-trains-notice.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Updated Menu component in Backstage UI to use useId() from React Aria instead of React to support React 17.
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 51d53067bd..b4b86bf5b0 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -2,299 +2,325 @@
"mode": "pre",
"tag": "next",
"initialVersions": {
- "example-app": "0.2.108",
- "@backstage/app-defaults": "1.6.1",
- "example-app-next": "0.0.22",
- "app-next-example-plugin": "0.0.22",
- "example-backend": "0.0.37",
- "@backstage/backend-app-api": "1.2.2",
- "@backstage/backend-defaults": "0.9.0",
+ "example-app": "0.2.111",
+ "@backstage/app-defaults": "1.6.4",
+ "example-app-next": "0.0.25",
+ "app-next-example-plugin": "0.0.25",
+ "example-backend": "0.0.40",
+ "@backstage/backend-app-api": "1.2.5",
+ "@backstage/backend-defaults": "0.11.1",
"@backstage/backend-dev-utils": "0.1.5",
- "@backstage/backend-dynamic-feature-service": "0.6.2",
- "@backstage/backend-openapi-utils": "0.5.2",
- "@backstage/backend-plugin-api": "1.3.0",
- "@backstage/backend-test-utils": "1.4.0",
- "@backstage/canon": "0.3.0",
- "@backstage/catalog-client": "1.9.1",
- "@backstage/catalog-model": "1.7.3",
- "@backstage/cli": "0.32.0",
+ "@backstage/backend-dynamic-feature-service": "0.7.2",
+ "@backstage/backend-openapi-utils": "0.5.5",
+ "@backstage/backend-plugin-api": "1.4.1",
+ "@backstage/backend-test-utils": "1.7.0",
+ "@backstage/canon": "0.6.0",
+ "@backstage/catalog-client": "1.10.2",
+ "@backstage/catalog-model": "1.7.5",
+ "@backstage/cli": "0.33.1",
"@backstage/cli-common": "0.1.15",
"@backstage/cli-node": "0.2.13",
"@backstage/codemods": "0.1.52",
- "@backstage/config": "1.3.2",
- "@backstage/config-loader": "1.10.0",
- "@backstage/core-app-api": "1.16.1",
- "@backstage/core-compat-api": "0.4.1",
- "@backstage/core-components": "0.17.1",
- "@backstage/core-plugin-api": "1.10.6",
- "@backstage/create-app": "0.6.1",
- "@backstage/dev-utils": "1.1.9",
- "e2e-test": "0.2.27",
+ "@backstage/config": "1.3.3",
+ "@backstage/config-loader": "1.10.2",
+ "@backstage/core-app-api": "1.18.0",
+ "@backstage/core-compat-api": "0.4.4",
+ "@backstage/core-components": "0.17.4",
+ "@backstage/core-plugin-api": "1.10.9",
+ "@backstage/create-app": "0.7.1",
+ "@backstage/dev-utils": "1.1.12",
+ "e2e-test": "0.2.30",
"@backstage/e2e-test-utils": "0.1.1",
"@backstage/errors": "1.2.7",
- "@backstage/eslint-plugin": "0.1.10",
- "@backstage/frontend-app-api": "0.11.1",
- "@backstage/frontend-defaults": "0.2.1",
- "@backstage/frontend-dynamic-feature-loader": "0.1.0",
- "@internal/frontend": "0.0.8",
- "@backstage/frontend-plugin-api": "0.10.1",
- "@backstage/frontend-test-utils": "0.3.1",
- "@backstage/integration": "1.16.3",
- "@backstage/integration-aws-node": "0.1.15",
- "@backstage/integration-react": "1.2.6",
+ "@backstage/eslint-plugin": "0.1.11",
+ "@backstage/frontend-app-api": "0.11.4",
+ "@backstage/frontend-defaults": "0.2.4",
+ "@backstage/frontend-dynamic-feature-loader": "0.1.3",
+ "@internal/frontend": "0.0.11",
+ "@backstage/frontend-plugin-api": "0.10.4",
+ "@backstage/frontend-test-utils": "0.3.4",
+ "@backstage/integration": "1.17.1",
+ "@backstage/integration-aws-node": "0.1.17",
+ "@backstage/integration-react": "1.2.9",
"@internal/opaque": "0.0.1",
- "@backstage/release-manifests": "0.0.12",
- "@backstage/repo-tools": "0.13.2",
- "@internal/scaffolder": "0.0.8",
- "@techdocs/cli": "1.9.2",
- "techdocs-cli-embedded-app": "0.2.107",
- "@backstage/test-utils": "1.7.7",
- "@backstage/theme": "0.6.5",
+ "@backstage/release-manifests": "0.0.13",
+ "@backstage/repo-tools": "0.15.0",
+ "@internal/scaffolder": "0.0.11",
+ "@techdocs/cli": "1.9.5",
+ "techdocs-cli-embedded-app": "0.2.110",
+ "@backstage/test-utils": "1.7.10",
+ "@backstage/theme": "0.6.7",
"@backstage/types": "1.2.1",
+ "@backstage/ui": "0.6.0",
"@backstage/version-bridge": "1.0.11",
- "yarn-plugin-backstage": "0.0.4",
- "@backstage/plugin-api-docs": "0.12.6",
+ "yarn-plugin-backstage": "0.0.7",
+ "@backstage/plugin-api-docs": "0.12.9",
"@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.10",
- "@backstage/plugin-app": "0.1.8",
- "@backstage/plugin-app-backend": "0.5.1",
- "@backstage/plugin-app-node": "0.1.32",
- "@backstage/plugin-app-visualizer": "0.1.18",
- "@backstage/plugin-auth-backend": "0.24.5",
- "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.2",
- "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.7",
- "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.2",
- "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-github-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-google-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-guest-provider": "0.2.7",
- "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.7",
- "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.2",
- "@backstage/plugin-auth-backend-module-okta-provider": "0.2.2",
- "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.2",
- "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.2",
- "@backstage/plugin-auth-node": "0.6.2",
- "@backstage/plugin-auth-react": "0.1.14",
- "@backstage/plugin-bitbucket-cloud-common": "0.2.29",
- "@backstage/plugin-catalog": "1.29.0",
- "@backstage/plugin-catalog-backend": "1.32.1",
- "@backstage/plugin-catalog-backend-module-aws": "0.4.10",
- "@backstage/plugin-catalog-backend-module-azure": "0.3.4",
- "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.1",
- "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.4.7",
- "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.4.0",
- "@backstage/plugin-catalog-backend-module-gcp": "0.3.7",
- "@backstage/plugin-catalog-backend-module-gerrit": "0.3.1",
- "@backstage/plugin-catalog-backend-module-github": "0.8.0",
- "@backstage/plugin-catalog-backend-module-github-org": "0.3.9",
- "@backstage/plugin-catalog-backend-module-gitlab": "0.6.5",
- "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.8",
- "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.6.5",
- "@backstage/plugin-catalog-backend-module-ldap": "0.11.4",
- "@backstage/plugin-catalog-backend-module-logs": "0.1.9",
- "@backstage/plugin-catalog-backend-module-msgraph": "0.6.9",
- "@backstage/plugin-catalog-backend-module-openapi": "0.2.9",
- "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.9",
- "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.7",
- "@backstage/plugin-catalog-backend-module-unprocessed": "0.5.7",
- "@backstage/plugin-catalog-common": "1.1.3",
- "@backstage/plugin-catalog-graph": "0.4.18",
- "@backstage/plugin-catalog-import": "0.12.13",
- "@backstage/plugin-catalog-node": "1.16.3",
- "@backstage/plugin-catalog-react": "1.17.0",
- "@backstage/plugin-catalog-unprocessed-entities": "0.2.16",
- "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.7",
- "@backstage/plugin-config-schema": "0.1.67",
- "@backstage/plugin-devtools": "0.1.26",
- "@backstage/plugin-devtools-backend": "0.5.4",
- "@backstage/plugin-devtools-common": "0.1.15",
- "@backstage/plugin-events-backend": "0.5.1",
- "@backstage/plugin-events-backend-module-aws-sqs": "0.4.10",
- "@backstage/plugin-events-backend-module-azure": "0.2.19",
- "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.19",
- "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.0",
- "@backstage/plugin-events-backend-module-gerrit": "0.2.19",
- "@backstage/plugin-events-backend-module-github": "0.3.0",
- "@backstage/plugin-events-backend-module-gitlab": "0.3.0",
- "@backstage/plugin-events-backend-test-utils": "0.1.43",
- "@backstage/plugin-events-node": "0.4.10",
- "@internal/plugin-todo-list": "1.0.38",
- "@internal/plugin-todo-list-backend": "1.0.38",
- "@internal/plugin-todo-list-common": "1.0.24",
- "@backstage/plugin-gateway-backend": "1.0.0",
- "@backstage/plugin-home": "0.8.7",
- "@backstage/plugin-home-react": "0.1.25",
- "@backstage/plugin-kubernetes": "0.12.6",
- "@backstage/plugin-kubernetes-backend": "0.19.5",
- "@backstage/plugin-kubernetes-cluster": "0.0.24",
- "@backstage/plugin-kubernetes-common": "0.9.4",
- "@backstage/plugin-kubernetes-node": "0.2.5",
- "@backstage/plugin-kubernetes-react": "0.5.6",
- "@backstage/plugin-notifications": "0.5.4",
- "@backstage/plugin-notifications-backend": "0.5.5",
- "@backstage/plugin-notifications-backend-module-email": "0.3.8",
- "@backstage/plugin-notifications-backend-module-slack": "0.1.0",
- "@backstage/plugin-notifications-common": "0.0.8",
- "@backstage/plugin-notifications-node": "0.2.14",
- "@backstage/plugin-org": "0.6.38",
- "@backstage/plugin-org-react": "0.1.37",
- "@backstage/plugin-permission-backend": "0.6.0",
- "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.7",
- "@backstage/plugin-permission-common": "0.8.4",
- "@backstage/plugin-permission-node": "0.9.1",
- "@backstage/plugin-permission-react": "0.4.33",
- "@backstage/plugin-proxy-backend": "0.6.1",
- "@backstage/plugin-proxy-node": "0.1.3",
- "@backstage/plugin-scaffolder": "1.30.0",
- "@backstage/plugin-scaffolder-backend": "1.32.0",
- "@backstage/plugin-scaffolder-backend-module-azure": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.9",
- "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.8",
- "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.9",
- "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-github": "0.7.0",
- "@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.0",
- "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.9",
- "@backstage/plugin-scaffolder-backend-module-rails": "0.5.8",
- "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.8",
- "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.9",
- "@backstage/plugin-scaffolder-common": "1.5.10",
- "@backstage/plugin-scaffolder-node": "0.8.1",
- "@backstage/plugin-scaffolder-node-test-utils": "0.2.1",
- "@backstage/plugin-scaffolder-react": "1.15.0",
- "@backstage/plugin-search": "1.4.25",
- "@backstage/plugin-search-backend": "2.0.1",
- "@backstage/plugin-search-backend-module-catalog": "0.3.3",
- "@backstage/plugin-search-backend-module-elasticsearch": "1.7.1",
- "@backstage/plugin-search-backend-module-explore": "0.3.1",
- "@backstage/plugin-search-backend-module-pg": "0.5.43",
- "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.8",
- "@backstage/plugin-search-backend-module-techdocs": "0.4.1",
- "@backstage/plugin-search-backend-node": "1.3.10",
- "@backstage/plugin-search-common": "1.2.17",
- "@backstage/plugin-search-react": "1.8.8",
- "@backstage/plugin-signals": "0.0.18",
- "@backstage/plugin-signals-backend": "0.3.3",
- "@backstage/plugin-signals-node": "0.1.19",
- "@backstage/plugin-signals-react": "0.0.12",
- "@backstage/plugin-techdocs": "1.12.5",
- "@backstage/plugin-techdocs-addons-test-utils": "1.0.47",
- "@backstage/plugin-techdocs-backend": "2.0.1",
- "@backstage/plugin-techdocs-common": "0.1.0",
- "@backstage/plugin-techdocs-module-addons-contrib": "1.1.23",
- "@backstage/plugin-techdocs-node": "1.13.2",
- "@backstage/plugin-techdocs-react": "1.2.16",
- "@backstage/plugin-user-settings": "0.8.21",
- "@backstage/plugin-user-settings-backend": "0.3.1",
- "@backstage/plugin-user-settings-common": "0.0.1",
- "@backstage/plugin-events-backend-module-google-pubsub": "0.0.0"
+ "@backstage/plugin-app": "0.1.11",
+ "@backstage/plugin-app-backend": "0.5.4",
+ "@backstage/plugin-app-node": "0.1.35",
+ "@backstage/plugin-app-visualizer": "0.1.21",
+ "@backstage/plugin-auth-backend": "0.25.2",
+ "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.5",
+ "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.10",
+ "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.5",
+ "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-github-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-google-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-guest-provider": "0.2.10",
+ "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.10",
+ "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.5",
+ "@backstage/plugin-auth-backend-module-okta-provider": "0.2.5",
+ "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.5",
+ "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.5",
+ "@backstage/plugin-auth-node": "0.6.5",
+ "@backstage/plugin-auth-react": "0.1.17",
+ "@backstage/plugin-bitbucket-cloud-common": "0.3.1",
+ "@backstage/plugin-catalog": "1.31.1",
+ "@backstage/plugin-catalog-backend": "3.0.0",
+ "@backstage/plugin-catalog-backend-module-aws": "0.4.13",
+ "@backstage/plugin-catalog-backend-module-azure": "0.3.7",
+ "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.4",
+ "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.5.1",
+ "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.5.1",
+ "@backstage/plugin-catalog-backend-module-gcp": "0.3.10",
+ "@backstage/plugin-catalog-backend-module-gerrit": "0.3.4",
+ "@backstage/plugin-catalog-backend-module-gitea": "0.1.2",
+ "@backstage/plugin-catalog-backend-module-github": "0.10.1",
+ "@backstage/plugin-catalog-backend-module-github-org": "0.3.12",
+ "@backstage/plugin-catalog-backend-module-gitlab": "0.7.1",
+ "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.11",
+ "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.2",
+ "@backstage/plugin-catalog-backend-module-ldap": "0.11.7",
+ "@backstage/plugin-catalog-backend-module-logs": "0.1.12",
+ "@backstage/plugin-catalog-backend-module-msgraph": "0.7.2",
+ "@backstage/plugin-catalog-backend-module-openapi": "0.2.12",
+ "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.12",
+ "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.10",
+ "@backstage/plugin-catalog-backend-module-unprocessed": "0.6.2",
+ "@backstage/plugin-catalog-common": "1.1.5",
+ "@backstage/plugin-catalog-graph": "0.4.21",
+ "@backstage/plugin-catalog-import": "0.13.3",
+ "@backstage/plugin-catalog-node": "1.17.2",
+ "@backstage/plugin-catalog-react": "1.19.1",
+ "@backstage/plugin-catalog-unprocessed-entities": "0.2.19",
+ "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.9",
+ "@backstage/plugin-config-schema": "0.1.70",
+ "@backstage/plugin-devtools": "0.1.29",
+ "@backstage/plugin-devtools-backend": "0.5.7",
+ "@backstage/plugin-devtools-common": "0.1.17",
+ "@backstage/plugin-events-backend": "0.5.4",
+ "@backstage/plugin-events-backend-module-aws-sqs": "0.4.13",
+ "@backstage/plugin-events-backend-module-azure": "0.2.22",
+ "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.22",
+ "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.3",
+ "@backstage/plugin-events-backend-module-gerrit": "0.2.22",
+ "@backstage/plugin-events-backend-module-github": "0.4.2",
+ "@backstage/plugin-events-backend-module-gitlab": "0.3.3",
+ "@backstage/plugin-events-backend-module-google-pubsub": "0.1.2",
+ "@backstage/plugin-events-backend-module-kafka": "0.1.1",
+ "@backstage/plugin-events-backend-test-utils": "0.1.46",
+ "@backstage/plugin-events-node": "0.4.13",
+ "@internal/plugin-todo-list": "1.0.41",
+ "@internal/plugin-todo-list-backend": "1.0.41",
+ "@internal/plugin-todo-list-common": "1.0.26",
+ "@backstage/plugin-gateway-backend": "1.0.3",
+ "@backstage/plugin-home": "0.8.10",
+ "@backstage/plugin-home-react": "0.1.28",
+ "@backstage/plugin-kubernetes": "0.12.9",
+ "@backstage/plugin-kubernetes-backend": "0.19.8",
+ "@backstage/plugin-kubernetes-cluster": "0.0.27",
+ "@backstage/plugin-kubernetes-common": "0.9.6",
+ "@backstage/plugin-kubernetes-node": "0.3.2",
+ "@backstage/plugin-kubernetes-react": "0.5.9",
+ "@backstage/plugin-mcp-actions-backend": "0.1.1",
+ "@backstage/plugin-notifications": "0.5.7",
+ "@backstage/plugin-notifications-backend": "0.5.8",
+ "@backstage/plugin-notifications-backend-module-email": "0.3.11",
+ "@backstage/plugin-notifications-backend-module-slack": "0.1.3",
+ "@backstage/plugin-notifications-common": "0.0.10",
+ "@backstage/plugin-notifications-node": "0.2.17",
+ "@backstage/plugin-org": "0.6.41",
+ "@backstage/plugin-org-react": "0.1.40",
+ "@backstage/plugin-permission-backend": "0.7.2",
+ "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.10",
+ "@backstage/plugin-permission-common": "0.9.1",
+ "@backstage/plugin-permission-node": "0.10.2",
+ "@backstage/plugin-permission-react": "0.4.36",
+ "@backstage/plugin-proxy-backend": "0.6.4",
+ "@backstage/plugin-proxy-node": "0.1.6",
+ "@backstage/plugin-scaffolder": "1.33.0",
+ "@backstage/plugin-scaffolder-backend": "2.1.0",
+ "@backstage/plugin-scaffolder-backend-module-azure": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.12",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.11",
+ "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.13",
+ "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-github": "0.8.1",
+ "@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.3",
+ "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.12",
+ "@backstage/plugin-scaffolder-backend-module-rails": "0.5.11",
+ "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.11",
+ "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.12",
+ "@backstage/plugin-scaffolder-common": "1.6.0",
+ "@backstage/plugin-scaffolder-node": "0.10.0",
+ "@backstage/plugin-scaffolder-node-test-utils": "0.3.1",
+ "@backstage/plugin-scaffolder-react": "1.18.0",
+ "@backstage/plugin-search": "1.4.28",
+ "@backstage/plugin-search-backend": "2.0.4",
+ "@backstage/plugin-search-backend-module-catalog": "0.3.6",
+ "@backstage/plugin-search-backend-module-elasticsearch": "1.7.4",
+ "@backstage/plugin-search-backend-module-explore": "0.3.4",
+ "@backstage/plugin-search-backend-module-pg": "0.5.46",
+ "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.11",
+ "@backstage/plugin-search-backend-module-techdocs": "0.4.4",
+ "@backstage/plugin-search-backend-node": "1.3.13",
+ "@backstage/plugin-search-common": "1.2.19",
+ "@backstage/plugin-search-react": "1.9.2",
+ "@backstage/plugin-signals": "0.0.21",
+ "@backstage/plugin-signals-backend": "0.3.6",
+ "@backstage/plugin-signals-node": "0.1.22",
+ "@backstage/plugin-signals-react": "0.0.15",
+ "@backstage/plugin-techdocs": "1.13.2",
+ "@backstage/plugin-techdocs-addons-test-utils": "1.0.51",
+ "@backstage/plugin-techdocs-backend": "2.0.4",
+ "@backstage/plugin-techdocs-common": "0.1.1",
+ "@backstage/plugin-techdocs-module-addons-contrib": "1.1.26",
+ "@backstage/plugin-techdocs-node": "1.13.5",
+ "@backstage/plugin-techdocs-react": "1.3.1",
+ "@backstage/plugin-user-settings": "0.8.24",
+ "@backstage/plugin-user-settings-backend": "0.3.4",
+ "@backstage/plugin-user-settings-common": "0.0.1"
},
"changesets": [
- "angry-sites-fold",
- "beige-kiwis-flow",
- "brave-donuts-sink",
- "brave-eggs-mate",
- "brave-toes-switch",
- "breezy-hotels-deny",
- "bright-moles-sort",
- "bumpy-showers-design",
- "busy-badgers-hang",
- "calm-toys-occur",
- "chatty-showers-cheat",
- "chilly-trams-cheer",
- "chubby-cougars-run",
- "chubby-needles-vanish",
- "cold-humans-check",
- "common-goats-raise",
- "cool-bikes-push",
- "cool-cities-grab",
- "cool-colts-float",
- "cool-knives-design",
- "crazy-chefs-sin",
- "create-app-1745325336",
- "create-app-1745936753",
- "cruel-lights-sip",
- "cyan-pots-appear",
- "deep-ties-move",
- "dirty-grapes-vanish",
- "dry-carpets-hope",
- "dull-doodles-trade",
- "early-colts-accept",
- "early-dryers-teach",
- "eight-toys-feel",
- "eleven-ghosts-strive",
- "famous-cities-stand",
- "fancy-frogs-like",
- "floppy-days-tell",
- "four-peaches-talk",
- "fruity-bags-flow",
- "good-islands-drive",
- "green-trainers-float",
- "heavy-baths-rule",
- "heavy-onions-swim",
- "huge-olives-do",
- "icy-mugs-glow",
- "khaki-grapes-sink",
- "large-experts-sort",
- "large-lemons-clap",
- "lazy-tires-show",
- "lovely-cats-take",
- "mean-parents-build",
- "mighty-carrots-decide",
- "neat-glasses-occur",
- "neat-glasses-occured",
- "new-hands-scream",
- "nice-vans-vanish",
- "old-crews-serve",
- "open-ghosts-fix",
- "open-lands-shop",
- "pretty-corners-speak",
- "pretty-seas-hug",
- "public-socks-agree",
- "real-rings-smoke",
- "real-sheep-chew",
- "renovate-4fc113d",
- "renovate-68baea0",
- "renovate-e32145b",
- "renovate-ee17247",
- "sad-showers-begin",
- "sad-taxes-bake",
- "shaggy-stingrays-check",
- "sharp-ligers-beg",
- "sharp-numbers-doubt",
- "shiny-symbols-grow",
- "short-teeth-juggle",
- "silent-clubs-roll",
- "slick-brooms-start",
- "slimy-peas-post",
- "slow-drinks-enjoy",
- "small-eggs-develop",
- "spicy-steaks-swim",
- "spotty-doors-design",
- "stale-symbols-joke",
- "tame-areas-behave",
- "ten-spies-explode",
- "ten-tables-build",
- "thick-hotels-rhyme",
- "true-breads-rhyme",
- "twenty-kiwis-punch",
- "warm-cases-bathe",
- "warm-llamas-return",
- "wicked-dingos-stand",
- "wise-cobras-sink",
- "wise-pillows-smile",
- "yellow-beans-eat",
- "yellow-cows-tickle"
+ "afraid-poets-thank",
+ "blue-apples-pump",
+ "brave-pumas-attack",
+ "bright-elephants-sparkle",
+ "calm-geese-serve",
+ "chatty-coats-sin",
+ "chatty-dodos-design",
+ "chatty-schools-post",
+ "clean-chairs-sit-2",
+ "clean-chairs-sit",
+ "clever-plants-warn",
+ "cold-heads-arrive",
+ "cold-lemons-design",
+ "common-heads-build",
+ "component-refs-app",
+ "component-refs-breaking-app",
+ "component-refs-breaking-frontend-plugin-api",
+ "crazy-pants-exist",
+ "create-app-1753196727",
+ "create-app-1754401469",
+ "cruel-bars-buy",
+ "cruel-zoos-argue",
+ "deep-apples-attack",
+ "deep-mangos-dig",
+ "eight-sloths-walk",
+ "eleven-tigers-drop",
+ "empty-years-grow",
+ "every-schools-find",
+ "evil-forks-hang",
+ "evil-phones-unite",
+ "fancy-ducks-help",
+ "fast-jars-push",
+ "fifty-ads-dance",
+ "five-ducks-hide",
+ "floppy-groups-hug",
+ "fluffy-otters-cry",
+ "four-spiders-jump",
+ "free-months-share",
+ "fruity-rockets-rhyme",
+ "full-streets-take",
+ "funny-brooms-trade",
+ "funny-dancers-start",
+ "fuzzy-ducks-jump",
+ "fuzzy-ducks-speak",
+ "gentle-cars-arrive",
+ "great-hounds-fix",
+ "great-snakes-dress",
+ "green-lies-invite copy",
+ "green-lies-invite",
+ "honest-moons-rest",
+ "honest-seas-repeat",
+ "honest-snakes-draw",
+ "hot-clowns-behave",
+ "huge-heads-occur",
+ "huge-paws-design",
+ "itchy-doodles-boil",
+ "late-squids-feel",
+ "lemon-ways-lay",
+ "little-bugs-care",
+ "long-grapes-glow",
+ "lovely-fans-write",
+ "major-comics-stay",
+ "mighty-cycles-stay",
+ "mira-looking-ostrich",
+ "moody-clowns-hear",
+ "nej-inte-ostrich",
+ "nice-actors-cheer",
+ "nice-buttons-return",
+ "nice-crabs-clean",
+ "odd-beans-sell",
+ "olive-baths-punch",
+ "open-bottles-film",
+ "open-seas-ring",
+ "orange-teams-smell",
+ "petite-spoons-flash",
+ "polite-trains-notice",
+ "quick-keys-post",
+ "quiet-parks-cheer",
+ "renovate-49770ce",
+ "renovate-c6c2a22",
+ "rich-seals-itch",
+ "ripe-comics-sip",
+ "rotten-rats-dream",
+ "sad-candies-open",
+ "sad-cities-lay",
+ "seven-crabs-stick",
+ "shaggy-parrots-deny",
+ "shiny-rats-accept",
+ "short-parks-love",
+ "silent-bats-jam",
+ "sixty-clowns-float",
+ "slick-cameras-bet",
+ "small-trams-do",
+ "smart-planes-march",
+ "solid-ducks-flow",
+ "spotty-clowns-lose",
+ "spotty-icons-shake",
+ "strong-dogs-raise",
+ "tame-sloths-boil",
+ "tangy-pets-smoke",
+ "tender-crabs-stay",
+ "tender-olives-clean",
+ "thick-breads-add",
+ "thick-hotels-enter",
+ "thirty-dingos-allow",
+ "thirty-eagles-run",
+ "thirty-jobs-cut",
+ "three-mammals-move",
+ "three-snakes-deny",
+ "tired-lamps-start",
+ "twenty-pumas-brush",
+ "violet-weeks-trade",
+ "wet-ghosts-rhyme",
+ "whole-glasses-visit",
+ "whole-hands-cut",
+ "wild-apes-care",
+ "yellow-ducks-burn"
]
}
diff --git a/.changeset/pretty-corners-speak.md b/.changeset/pretty-corners-speak.md
deleted file mode 100644
index 8e24d212fe..0000000000
--- a/.changeset/pretty-corners-speak.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-test-utils': minor
----
-
-Add a functional `mockServices.events()`
diff --git a/.changeset/pretty-seas-hug.md b/.changeset/pretty-seas-hug.md
deleted file mode 100644
index 216f9af18f..0000000000
--- a/.changeset/pretty-seas-hug.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-react': patch
----
-
-Fixed an issue causing entities of kind user and group to be empty when an owner was selected
diff --git a/.changeset/public-socks-agree.md b/.changeset/public-socks-agree.md
deleted file mode 100644
index 7febb17cc0..0000000000
--- a/.changeset/public-socks-agree.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-node-test-utils': patch
----
-
-Include optional `user` in `createMockActionContext`
diff --git a/.changeset/quick-keys-post.md b/.changeset/quick-keys-post.md
new file mode 100644
index 0000000000..c0e56be791
--- /dev/null
+++ b/.changeset/quick-keys-post.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Remove stylesheet import from Select component.
diff --git a/.changeset/quiet-parks-cheer.md b/.changeset/quiet-parks-cheer.md
new file mode 100644
index 0000000000..1e49ce506d
--- /dev/null
+++ b/.changeset/quiet-parks-cheer.md
@@ -0,0 +1,42 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+Added support for advanced parameter types in extension blueprints. The primary purpose of this is to allow extension authors to use type inference in the definition of the blueprint parameters. This often removes the need for extra imports and improves discoverability of blueprint parameters.
+
+This feature is introduced through the new `defineParams` option of `createExtensionBlueprint`, along with accompanying `createExtensionBlueprintParams` function to help implement the new format.
+
+The following is an example of how to create an extension blueprint that uses the new option:
+
+```ts
+const ExampleBlueprint = createExtensionBlueprint({
+ kind: 'example',
+ attachTo: { id: 'example', input: 'example' },
+ output: [exampleComponentDataRef, exampleFetcherDataRef],
+ defineParams(params: {
+ component(props: ExampleProps): JSX.Element | null;
+ fetcher(options: FetchOptions): Promise>;
+ }) {
+ // The returned params must be wrapped with `createExtensionBlueprintParams`
+ return createExtensionBlueprintParams(params);
+ },
+ *factory(params) {
+ // These params are now inferred
+ yield exampleComponentDataRef(params.component);
+ yield exampleFetcherDataRef(params.fetcher);
+ },
+});
+```
+
+Usage of the above example looks as follows:
+
+```ts
+const example = ExampleBlueprint.make({
+ params: defineParams => defineParams({
+ component: ...,
+ fetcher: ...,
+ }),
+});
+```
+
+This `defineParams => defineParams()` is also known as the "callback syntax" and is required if a blueprint is created with the new `defineParams` option. The callback syntax can also optionally be used for other blueprints too, which means that it is not a breaking change to remove the `defineParams` option, as long as the external parameter types remain compatible.
diff --git a/.changeset/real-rings-smoke.md b/.changeset/real-rings-smoke.md
deleted file mode 100644
index 832d7e3c6e..0000000000
--- a/.changeset/real-rings-smoke.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-display entity-ref in GroupProfileCard so groups can easily determine their Group ID
diff --git a/.changeset/real-sheep-chew.md b/.changeset/real-sheep-chew.md
deleted file mode 100644
index 9ae5b5ae9e..0000000000
--- a/.changeset/real-sheep-chew.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-components': patch
----
-
-Fix the hidden sidebar's sub-menu when the sidebar is scrollable
diff --git a/.changeset/renovate-49770ce.md b/.changeset/renovate-49770ce.md
new file mode 100644
index 0000000000..82be361499
--- /dev/null
+++ b/.changeset/renovate-49770ce.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Updated dependency `linkifyjs` to `4.3.2`.
diff --git a/.changeset/renovate-4fc113d.md b/.changeset/renovate-4fc113d.md
deleted file mode 100644
index abec879c27..0000000000
--- a/.changeset/renovate-4fc113d.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Updated dependency `@octokit/request` to `^8.0.0`.
diff --git a/.changeset/renovate-68baea0.md b/.changeset/renovate-68baea0.md
deleted file mode 100644
index 6370fc8834..0000000000
--- a/.changeset/renovate-68baea0.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/cli': patch
----
-
-Updated dependency `react-refresh` to `^0.17.0`.
diff --git a/.changeset/renovate-c6c2a22.md b/.changeset/renovate-c6c2a22.md
new file mode 100644
index 0000000000..ba551042f5
--- /dev/null
+++ b/.changeset/renovate-c6c2a22.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend-module-okta-provider': patch
+---
+
+Updated dependency `@davidzemon/passport-okta-oauth` to `^0.0.7`.
diff --git a/.changeset/renovate-e32145b.md b/.changeset/renovate-e32145b.md
deleted file mode 100644
index e1fdbcf02d..0000000000
--- a/.changeset/renovate-e32145b.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-compat-api': patch
----
-
-Updated dependency `@backstage-community/plugin-puppetdb` to `^0.6.0`.
diff --git a/.changeset/renovate-ee17247.md b/.changeset/renovate-ee17247.md
deleted file mode 100644
index a97a63d138..0000000000
--- a/.changeset/renovate-ee17247.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-'@backstage/plugin-kubernetes-backend': patch
-'@backstage/plugin-kubernetes-common': patch
-'@backstage/plugin-kubernetes-node': patch
-'@backstage/plugin-kubernetes-react': patch
-'@backstage/plugin-kubernetes': patch
----
-
-Updated dependency `@kubernetes/client-node` to `1.1.2`.
diff --git a/.changeset/rich-seals-itch.md b/.changeset/rich-seals-itch.md
new file mode 100644
index 0000000000..4ef1510c6e
--- /dev/null
+++ b/.changeset/rich-seals-itch.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Updated the recommended naming of the blueprint param callback from `define` to `defineParams`, making the syntax `defineParams => defineParams(...)`.
diff --git a/.changeset/ripe-comics-sip.md b/.changeset/ripe-comics-sip.md
new file mode 100644
index 0000000000..b5fb1e7f2b
--- /dev/null
+++ b/.changeset/ripe-comics-sip.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-github': patch
+---
+
+This change introduces single user versions of the user group resolution code in the multi org provider that will not page through all membership when updating a single user.
diff --git a/.changeset/rotten-rats-dream.md b/.changeset/rotten-rats-dream.md
new file mode 100644
index 0000000000..65cb58b43a
--- /dev/null
+++ b/.changeset/rotten-rats-dream.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend-module-github': patch
+---
+
+Fixed bug in the `customProperties` type which was preventing it being used to set a list of values against a key (e.g. for multi-select fields)
diff --git a/.changeset/sad-candies-open.md b/.changeset/sad-candies-open.md
new file mode 100644
index 0000000000..fb8108c9dd
--- /dev/null
+++ b/.changeset/sad-candies-open.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-events-backend-module-kafka': patch
+---
+
+Remove luxon dependency and minor internal improvements
diff --git a/.changeset/sad-cities-lay.md b/.changeset/sad-cities-lay.md
new file mode 100644
index 0000000000..141c093b46
--- /dev/null
+++ b/.changeset/sad-cities-lay.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs-backend': patch
+---
+
+Updated CachedEntityLoader to use BackstageCredentials instead of raw tokens for cache key generation. It now uses principal-based identification (user entity ref for users, subject for services) instead of token-based keys, providing more consistent caching behavior.
diff --git a/.changeset/sad-showers-begin.md b/.changeset/sad-showers-begin.md
deleted file mode 100644
index 7fce23a2ab..0000000000
--- a/.changeset/sad-showers-begin.md
+++ /dev/null
@@ -1,66 +0,0 @@
----
-'@backstage/plugin-catalog-backend': major
----
-
-**BREAKING**: Removed all deprecated exports, and removed support for the old backend system.
-
-It also removes the `CodeOwnersProcessor` from the default set of processors, because it is expensive to run and has vague semantics. You need to update your backend to add it to the `catalogProcessingExtensionPoint` if you wish to continue using it.
-
-The following removed exports are available from `@backstage/plugin-catalog-node`:
-
-- `locationSpecToMetadataName`
-- `locationSpecToLocationEntity`
-- `processingResult`
-- `EntitiesSearchFilter`
-- `EntityFilter`
-- `DeferredEntity`
-- `EntityRelationSpec`
-- `CatalogProcessor`
-- `CatalogProcessorParser`
-- `CatalogProcessorCache`
-- `CatalogProcessorEmit`
-- `CatalogProcessorLocationResult`
-- `CatalogProcessorEntityResult`
-- `CatalogProcessorRelationResult`
-- `CatalogProcessorErrorResult`
-- `CatalogProcessorRefreshKeysResult`
-- `CatalogProcessorResult`
-- `EntityProvider`
-- `EntityProviderConnection`
-- `EntityProviderMutation`
-- `AnalyzeOptions`
-- `LocationAnalyzer`
-- `ScmLocationAnalyzer`
-- `PlaceholderResolver`
-- `PlaceholderResolverParams`
-- `PlaceholderResolverRead`
-- `PlaceholderResolverResolveUrl`
-- `parseEntityYaml`
-
-The following removed exports are available from `@backstage/plugin-catalog-common`:
-
-- `LocationSpec`
-- `AnalyzeLocationRequest`
-- `AnalyzeLocationResponse`
-- `AnalyzeLocationExistingEntity`
-- `AnalyzeLocationGenerateEntity`
-- `AnalyzeLocationEntityField`
-
-The following removed exports are instead implemented in the new backend system by `@backstage/plugin-search-backend-module-catalog`:
-
-- `defaultCatalogCollatorEntityTransformer`
-- `CatalogCollatorEntityTransformer`
-- `DefaultCatalogCollator`
-
-The following exports are removed without a direct replacement:
-
-- `DefaultCatalogCollatorFactory`
-- `DefaultCatalogCollatorFactoryOptions`
-- `LocationEntityProcessor`
-- `LocationEntityProcessorOptions`
-- `CatalogBuilder`
-- `CatalogEnvironment`
-- `CatalogPermissionRuleInput`
-- `CatalogProcessingEngine`
-- `createRandomProcessingInterval`
-- `ProcessingIntervalFunction`
diff --git a/.changeset/sad-taxes-bake.md b/.changeset/sad-taxes-bake.md
deleted file mode 100644
index 61a843a265..0000000000
--- a/.changeset/sad-taxes-bake.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': patch
----
-
-Fixed bug in fs:delete that prevented wildcard patterns from matching paths starting with "."
diff --git a/.changeset/seven-crabs-stick.md b/.changeset/seven-crabs-stick.md
new file mode 100644
index 0000000000..19db3d7042
--- /dev/null
+++ b/.changeset/seven-crabs-stick.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Added added defaults for all type parameters of `ExtensionDataRef` and deprecated `AnyExtensionDataRef`, as it is now redundant.
diff --git a/.changeset/shaggy-parrots-deny.md b/.changeset/shaggy-parrots-deny.md
new file mode 100644
index 0000000000..1c8d8bad7e
--- /dev/null
+++ b/.changeset/shaggy-parrots-deny.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Fixed getLocationByEntity to use `original_value` instead of `value` when querying search table
diff --git a/.changeset/shaggy-stingrays-check.md b/.changeset/shaggy-stingrays-check.md
deleted file mode 100644
index 74e0013224..0000000000
--- a/.changeset/shaggy-stingrays-check.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-org': patch
----
-
-Fixed missing spec.profile field on MyGroupsSidebarItem.tsx so the group spec.profile.displayName is shown on the sidebar"
diff --git a/.changeset/sharp-ligers-beg.md b/.changeset/sharp-ligers-beg.md
deleted file mode 100644
index 0582ed72d2..0000000000
--- a/.changeset/sharp-ligers-beg.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog-backend': minor
----
-
-Adds the ability to disable the default entity processors using a new boolean app config item `catalog.disableDefaultProcessors`.
diff --git a/.changeset/sharp-numbers-doubt.md b/.changeset/sharp-numbers-doubt.md
deleted file mode 100644
index 81e1313780..0000000000
--- a/.changeset/sharp-numbers-doubt.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-'@backstage/plugin-catalog-react': minor
----
-
-Added EntityOrderFilter to sort entities by different fields/columns. This new filter allows users to specify the order in which entities are displayed in the catalog.
-
-Example usage:
-
-```ts
-import {
- EntityOrderFilter,
- useEntityList,
-} from '@backstage/plugin-catalog-react';
-// ...
-const { updateFilters } = useEntityList();
-
-// ...
-updateFilters({
- order: new EntityOrderFilter([
- {
- field: 'metadata.name',
- order: 'desc',
- },
- ]),
-});
-```
diff --git a/.changeset/shiny-rats-accept.md b/.changeset/shiny-rats-accept.md
new file mode 100644
index 0000000000..1c9bb96764
--- /dev/null
+++ b/.changeset/shiny-rats-accept.md
@@ -0,0 +1,5 @@
+---
+'@backstage/repo-tools': patch
+---
+
+Removed build-in ignore of the `packages/canon` package for knip reports.
diff --git a/.changeset/shiny-symbols-grow.md b/.changeset/shiny-symbols-grow.md
deleted file mode 100644
index 18dd3b8b1f..0000000000
--- a/.changeset/shiny-symbols-grow.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend': patch
-'@backstage/plugin-scaffolder-react': patch
-'@backstage/plugin-scaffolder': patch
----
-
-Fixing a bug where the name for `templatingExtensions` was incorrectly set to `templateExtensions`
diff --git a/.changeset/short-parks-love.md b/.changeset/short-parks-love.md
new file mode 100644
index 0000000000..ba17d494f6
--- /dev/null
+++ b/.changeset/short-parks-love.md
@@ -0,0 +1,6 @@
+---
+'@backstage/frontend-plugin-api': patch
+'@backstage/plugin-app': patch
+---
+
+Adjusted the dialog API types to have more sensible defaults
diff --git a/.changeset/short-teeth-juggle.md b/.changeset/short-teeth-juggle.md
deleted file mode 100644
index e0f1073db3..0000000000
--- a/.changeset/short-teeth-juggle.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
-'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
-'@backstage/plugin-catalog-backend-module-backstage-openapi': patch
-'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
-'@backstage/plugin-search-backend-module-elasticsearch': patch
-'@backstage/plugin-catalog-backend-module-github-org': patch
-'@backstage/plugin-scaffolder-backend-module-gerrit': patch
-'@backstage/plugin-scaffolder-backend-module-github': patch
-'@backstage/plugin-scaffolder-backend-module-gitlab': patch
-'@backstage/plugin-catalog-backend-module-msgraph': patch
-'@backstage/plugin-catalog-backend-module-gitlab': patch
-'@backstage/plugin-catalog-backend-module-logs': patch
-'@backstage/plugin-catalog-backend-module-aws': patch
-'@backstage/frontend-plugin-api': patch
-'@backstage/backend-plugin-api': patch
-'@backstage/plugin-kubernetes-backend': patch
-'@backstage/plugin-kubernetes-cluster': patch
-'@backstage/plugin-scaffolder-backend': patch
-'@backstage/backend-defaults': patch
-'@backstage/frontend-app-api': patch
-'@backstage/plugin-kubernetes-common': patch
-'@backstage/plugin-permission-common': patch
-'@backstage/backend-app-api': patch
-'@backstage/core-compat-api': patch
-'@backstage/core-components': patch
-'@backstage/plugin-kubernetes-react': patch
-'@backstage/plugin-scaffolder-react': patch
-'@backstage/plugin-techdocs-backend': patch
-'@backstage/plugin-kubernetes-node': patch
-'@backstage/plugin-scaffolder-node': patch
-'@backstage/config-loader': patch
-'@backstage/plugin-techdocs-react': patch
-'@backstage/plugin-catalog-graph': patch
-'@backstage/plugin-techdocs-node': patch
-'@backstage/plugin-auth-backend': patch
-'@backstage/repo-tools': patch
-'@backstage/plugin-auth-react': patch
-'@backstage/plugin-kubernetes': patch
-'@backstage/plugin-scaffolder': patch
-'@backstage/plugin-api-docs': patch
-'@backstage/plugin-techdocs': patch
-'@backstage/canon': patch
-'@backstage/cli': patch
-'@backstage/plugin-home': patch
-'@backstage/plugin-org': patch
----
-
-Removed various typos
diff --git a/.changeset/silent-bats-jam.md b/.changeset/silent-bats-jam.md
new file mode 100644
index 0000000000..fc8486b8d6
--- /dev/null
+++ b/.changeset/silent-bats-jam.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Add `startCollapsed` prop on the `SearchField` component in BUI.
diff --git a/.changeset/silent-clubs-roll.md b/.changeset/silent-clubs-roll.md
deleted file mode 100644
index c80f884331..0000000000
--- a/.changeset/silent-clubs-roll.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-permission-backend': minor
----
-
-**BREAKING** Removed support for the legacy backend system, please [migrate to the new backend system](https://backstage.io/docs/backend-system/building-backends/migrating)
diff --git a/.changeset/sixty-clowns-float.md b/.changeset/sixty-clowns-float.md
new file mode 100644
index 0000000000..4f0489f38c
--- /dev/null
+++ b/.changeset/sixty-clowns-float.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': minor
+---
+
+**BREAKING ALPHA**: The `defaultPath`, `defaultTitle`, and `defaultGroup` params of `PageBlueprint` has been renamed to `path`, `title`, and `group`. The `convertLegacyEntityContentExtension` utility has also received the same change. This change does not affect the compatibility of extensions created with older versions of this blueprint.
diff --git a/.changeset/slick-brooms-start.md b/.changeset/slick-brooms-start.md
deleted file mode 100644
index dec874a867..0000000000
--- a/.changeset/slick-brooms-start.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-events-backend-module-github': patch
----
-
-Correct README installation instructions.
diff --git a/.changeset/slick-cameras-bet.md b/.changeset/slick-cameras-bet.md
new file mode 100644
index 0000000000..4bee2cc007
--- /dev/null
+++ b/.changeset/slick-cameras-bet.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes': patch
+---
+
+Removed the kubernetes content padding to avoid double padding on k8s entity page
diff --git a/.changeset/slimy-peas-post.md b/.changeset/slimy-peas-post.md
deleted file mode 100644
index 6a0a80e323..0000000000
--- a/.changeset/slimy-peas-post.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-plugin-api': patch
----
-
-Minor doc comment update
diff --git a/.changeset/slow-drinks-enjoy.md b/.changeset/slow-drinks-enjoy.md
deleted file mode 100644
index 5a171b8fd1..0000000000
--- a/.changeset/slow-drinks-enjoy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/integration-aws-node': patch
----
-
-Fixed bug in DefaultAwsCredentialsManager where aws.mainAccount.region has no effect on the STS region used for account ID lookup during credential provider lookup when falling back to the main account, and it does not default to us-east-1
diff --git a/.changeset/small-eggs-develop.md b/.changeset/small-eggs-develop.md
deleted file mode 100644
index 618b877fa7..0000000000
--- a/.changeset/small-eggs-develop.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/plugin-scaffolder-react': minor
-'@backstage/plugin-scaffolder': minor
----
-
-add templating extensions page
diff --git a/.changeset/small-trams-do.md b/.changeset/small-trams-do.md
new file mode 100644
index 0000000000..a3d0e394a6
--- /dev/null
+++ b/.changeset/small-trams-do.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `element` param for `AppRootElementBlueprint` no longer accepts a component. If you are currently passing a component such as `element: () => ` or `element: MyComponent`, simply switch to `element: `.
diff --git a/.changeset/smart-planes-march.md b/.changeset/smart-planes-march.md
new file mode 100644
index 0000000000..619c37c675
--- /dev/null
+++ b/.changeset/smart-planes-march.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-catalog': patch
+---
+
+Allow filter to be an array in config schema
diff --git a/.changeset/solid-ducks-flow.md b/.changeset/solid-ducks-flow.md
new file mode 100644
index 0000000000..7828216898
--- /dev/null
+++ b/.changeset/solid-ducks-flow.md
@@ -0,0 +1,7 @@
+---
+'@backstage/frontend-defaults': patch
+'@backstage/frontend-app-api': patch
+'@backstage/cli': patch
+---
+
+Deprecated new frontend system config setting `app.experimental.packages` to just `app.packages`. The old config will continue working for the time being, but may be removed in a future release.
diff --git a/.changeset/spicy-steaks-swim.md b/.changeset/spicy-steaks-swim.md
deleted file mode 100644
index b2323c9b34..0000000000
--- a/.changeset/spicy-steaks-swim.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-github': patch
----
-
-Added optional assignees parameter to `publish:github:pull-request` action
diff --git a/.changeset/spotty-clowns-lose.md b/.changeset/spotty-clowns-lose.md
new file mode 100644
index 0000000000..e550fe48de
--- /dev/null
+++ b/.changeset/spotty-clowns-lose.md
@@ -0,0 +1,5 @@
+---
+'@backstage/repo-tools': patch
+---
+
+Added `stringEnums` to `mustache` templates
diff --git a/.changeset/spotty-doors-design.md b/.changeset/spotty-doors-design.md
deleted file mode 100644
index 22ee61c9b0..0000000000
--- a/.changeset/spotty-doors-design.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-notifications-backend-module-slack': patch
----
-
-Added email-based Slack User ID lookup if `metadata.annotations.slack.com/bot-notify` is missing from user entity
diff --git a/.changeset/spotty-icons-shake.md b/.changeset/spotty-icons-shake.md
new file mode 100644
index 0000000000..0c4f318cd9
--- /dev/null
+++ b/.changeset/spotty-icons-shake.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': patch
+---
+
+Added support for passing through `allowUnknownExtensionConfig` as a flag
diff --git a/.changeset/stale-symbols-joke.md b/.changeset/stale-symbols-joke.md
deleted file mode 100644
index ea4f172c1c..0000000000
--- a/.changeset/stale-symbols-joke.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-user-settings': patch
----
-
-Uppercase language name in language select
diff --git a/.changeset/strong-dogs-raise.md b/.changeset/strong-dogs-raise.md
new file mode 100644
index 0000000000..76220474a9
--- /dev/null
+++ b/.changeset/strong-dogs-raise.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': patch
+---
+
+Added a default implementation of the `SwappableComponentsApi` and removing the legacy `ComponentsApi` implementation
diff --git a/.changeset/sweet-papayas-slide.md b/.changeset/sweet-papayas-slide.md
deleted file mode 100644
index 9fbc067ca7..0000000000
--- a/.changeset/sweet-papayas-slide.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-search-react': patch
----
-
-Fix memoization of `filterValue` in `SearchFilter.Autocomplete` to prevent unintended resets
diff --git a/.changeset/tame-areas-behave.md b/.changeset/tame-areas-behave.md
deleted file mode 100644
index 6d5c776d8b..0000000000
--- a/.changeset/tame-areas-behave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-scaffolder-backend-module-notifications': patch
----
-
-Change notification send scaffolder action to use native zod schemas
diff --git a/.changeset/tame-sloths-boil.md b/.changeset/tame-sloths-boil.md
new file mode 100644
index 0000000000..8b718fe970
--- /dev/null
+++ b/.changeset/tame-sloths-boil.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Updated the `app.packages` config setting now that it no longer is experimental
diff --git a/.changeset/tangy-pets-smoke.md b/.changeset/tangy-pets-smoke.md
new file mode 100644
index 0000000000..f7438da333
--- /dev/null
+++ b/.changeset/tangy-pets-smoke.md
@@ -0,0 +1,6 @@
+---
+'@backstage/frontend-plugin-api': patch
+'@backstage/frontend-app-api': patch
+---
+
+Improved runtime error message clarity when extension factories don't return an iterable object.
diff --git a/.changeset/ten-spies-explode.md b/.changeset/ten-spies-explode.md
deleted file mode 100644
index 53a37fbd74..0000000000
--- a/.changeset/ten-spies-explode.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/integration': minor
----
-
-Implement Edit URL feature for Gerrit 3.9+.
-
-It's possible to disable the edit url by adding the `disableEditUrl: true` config in the Gerrit integration.
diff --git a/.changeset/ten-tables-build.md b/.changeset/ten-tables-build.md
deleted file mode 100644
index 9ddae808fa..0000000000
--- a/.changeset/ten-tables-build.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-auth-backend': patch
----
-
-The `static` key store now issues tokens with the same structure as other key stores. Tokens now include the `typ` field in the header and the `uip` (user identity proof) in the payload.
diff --git a/.changeset/tender-crabs-stay.md b/.changeset/tender-crabs-stay.md
new file mode 100644
index 0000000000..ac3296ea4e
--- /dev/null
+++ b/.changeset/tender-crabs-stay.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': minor
+---
+
+**Breaking** We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component.
diff --git a/.changeset/tender-olives-clean.md b/.changeset/tender-olives-clean.md
new file mode 100644
index 0000000000..1923b6bdc0
--- /dev/null
+++ b/.changeset/tender-olives-clean.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-defaults': patch
+---
+
+**BREAKING**: The `loadingComponent` option has been renamed to `loadingElement`, which is now found under `advanced.loadingElement`. The default loading element has also been switched to `` from `@backstage/core-components`. This is of course an improvement over the previous `"Loading..."` text, but also helps prevent flicker when the app loading is fast.
diff --git a/.changeset/thick-breads-add.md b/.changeset/thick-breads-add.md
new file mode 100644
index 0000000000..94b19d258d
--- /dev/null
+++ b/.changeset/thick-breads-add.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-signals': patch
+'@backstage/plugin-home': patch
+---
+
+**BREAKING ALPHA**: The `app-root-element` extension now only accepts `JSX.Element` in its `element` param, meaning overrides need to be updated.
diff --git a/.changeset/thick-hotels-enter.md b/.changeset/thick-hotels-enter.md
new file mode 100644
index 0000000000..300586f570
--- /dev/null
+++ b/.changeset/thick-hotels-enter.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-github': patch
+---
+
+Fix GitHub catalog entity provider branch matching on event processing.
diff --git a/.changeset/thick-hotels-rhyme.md b/.changeset/thick-hotels-rhyme.md
deleted file mode 100644
index b7047dcd71..0000000000
--- a/.changeset/thick-hotels-rhyme.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-techdocs': patch
----
-
-Add hover and focus styling to the "copy to clipboard" button within codeblocks in techdocs. Also added an aria-label to the button for accessibility.
diff --git a/.changeset/thirty-dingos-allow.md b/.changeset/thirty-dingos-allow.md
new file mode 100644
index 0000000000..f60c2b0d44
--- /dev/null
+++ b/.changeset/thirty-dingos-allow.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Added `FavoriteToggleProps`.
diff --git a/.changeset/thirty-eagles-run.md b/.changeset/thirty-eagles-run.md
new file mode 100644
index 0000000000..10ca1af381
--- /dev/null
+++ b/.changeset/thirty-eagles-run.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': minor
+---
+
+The `AppNodeSpec.plugin` property is now required.
diff --git a/.changeset/thirty-jobs-cut.md b/.changeset/thirty-jobs-cut.md
new file mode 100644
index 0000000000..6875a92271
--- /dev/null
+++ b/.changeset/thirty-jobs-cut.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-test-utils': patch
+'@backstage/backend-defaults': patch
+'@backstage/plugin-catalog-backend': patch
+---
+
+Updated `better-sqlite3` to v12
diff --git a/.changeset/thirty-jobs-look.md b/.changeset/thirty-jobs-look.md
new file mode 100644
index 0000000000..570ac79808
--- /dev/null
+++ b/.changeset/thirty-jobs-look.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+add `getResources` method to `permissionIntegrationRouter` for frontend task permission checks
diff --git a/.changeset/three-mammals-move.md b/.changeset/three-mammals-move.md
new file mode 100644
index 0000000000..646e60f84c
--- /dev/null
+++ b/.changeset/three-mammals-move.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': minor
+---
+
+Implement max length for scaffolder auditor audit logging with default of 256
diff --git a/.changeset/three-snakes-deny.md b/.changeset/three-snakes-deny.md
new file mode 100644
index 0000000000..8de233f870
--- /dev/null
+++ b/.changeset/three-snakes-deny.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+The Node.js transform in `@backstage/cli/config/nodeTransformHooks.mjs` now supports the built-in type stripping in Node.js, which is enabled by default from v22.18.0.
diff --git a/.changeset/tired-lamps-start.md b/.changeset/tired-lamps-start.md
new file mode 100644
index 0000000000..97b4e61ca3
--- /dev/null
+++ b/.changeset/tired-lamps-start.md
@@ -0,0 +1,15 @@
+---
+'@backstage/create-app': patch
+---
+
+Updated the `better-sqlite` dependency from `v9.0.0` to `v13.0.0`. You can apply this change to your instance by applying the following change to your `packages/backend/package.json` and running `yarn install`.
+
+```diff
+ "dependencies": {
+ "app": "link:../app",
+- "better-sqlite3": "^9.0.0",
++ "better-sqlite3": "^12.0.0",
+ "node-gyp": "^10.0.0",
+ "pg": "^8.11.3"
+ }
+```
diff --git a/.changeset/true-breads-rhyme.md b/.changeset/true-breads-rhyme.md
deleted file mode 100644
index d54f6c18d2..0000000000
--- a/.changeset/true-breads-rhyme.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-'@backstage/backend-test-utils': minor
-'@backstage/backend-defaults': patch
----
-
-Added Valkey support alongside Redis in backend-defaults cache clients, using the new Keyv Valkey package. Also extended backend-test-utils to support Valkey in tests.
diff --git a/.changeset/true-trains-tie.md b/.changeset/true-trains-tie.md
deleted file mode 100644
index 678e6a85e9..0000000000
--- a/.changeset/true-trains-tie.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/plugin-notifications-backend-module-slack': patch
----
-
-Notifications which mention user entity refs are now replaced with Slack compatible mentions.
-
-Example: `Welcome <@user:default/billy>!` -> `Welcome <@U123456890>!`
diff --git a/.changeset/twenty-kiwis-punch.md b/.changeset/twenty-kiwis-punch.md
deleted file mode 100644
index 6c54760247..0000000000
--- a/.changeset/twenty-kiwis-punch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-defaults': patch
----
-
-Bug fix: Pass user provided token through to gitlab url resolvers
diff --git a/.changeset/twenty-pumas-brush.md b/.changeset/twenty-pumas-brush.md
new file mode 100644
index 0000000000..6306fe0607
--- /dev/null
+++ b/.changeset/twenty-pumas-brush.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Adds onTabSelectionChange to ui header component.
diff --git a/.changeset/violet-weeks-trade.md b/.changeset/violet-weeks-trade.md
new file mode 100644
index 0000000000..32b425dbf2
--- /dev/null
+++ b/.changeset/violet-weeks-trade.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-app-api': patch
+---
+
+Moved `createSpecializedApp` options to a new `CreateSpecializedAppOptions` type.
diff --git a/.changeset/warm-cases-bathe.md b/.changeset/warm-cases-bathe.md
deleted file mode 100644
index 21e9ceb098..0000000000
--- a/.changeset/warm-cases-bathe.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/backend-defaults': patch
----
-
-The `GithubUrlReader` will now use the token from `options` when fetching repo details
diff --git a/.changeset/warm-llamas-return.md b/.changeset/warm-llamas-return.md
deleted file mode 100644
index 743ad0a5bb..0000000000
--- a/.changeset/warm-llamas-return.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-events-backend-module-google-pubsub': minor
----
-
-Added a module that is able to transfer messages from Google Pub/Sub subscriptions into the Backstage events system.
diff --git a/.changeset/wet-ghosts-rhyme.md b/.changeset/wet-ghosts-rhyme.md
new file mode 100644
index 0000000000..f1867bfb5e
--- /dev/null
+++ b/.changeset/wet-ghosts-rhyme.md
@@ -0,0 +1,23 @@
+---
+'@backstage/frontend-defaults': minor
+'@backstage/frontend-app-api': minor
+---
+
+**BREAKING**: Restructured some of option fields of `createApp` and `createSpecializedApp`.
+
+- For `createApp`, all option fields _except_ `features` and `bindRoutes` have been moved into a new `advanced` object field.
+- For `createSpecializedApp`, all option fields _except_ `features`, `config`, and `bindRoutes` have been moved into a new `advanced` object field.
+
+This helps highlight that some options are meant to rarely be needed or used, and simplifies the usage of those options that are almost always required.
+
+As an example, if you used to supply a custom config loader, you would update your code as follows:
+
+```diff
+ createApp({
+ features: [...],
+- configLoader: new MyCustomLoader(),
++ advanced: {
++ configLoader: new MyCustomLoader(),
++ },
+ })
+```
diff --git a/.changeset/whole-glasses-visit.md b/.changeset/whole-glasses-visit.md
new file mode 100644
index 0000000000..e318ce5956
--- /dev/null
+++ b/.changeset/whole-glasses-visit.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Added inline documentation for `createExtension`, `createExtensionBlueprint`, `createFrontendPlugin`, and `createFrontendModule`.
diff --git a/.changeset/whole-hands-cut.md b/.changeset/whole-hands-cut.md
new file mode 100644
index 0000000000..e7ea0059e3
--- /dev/null
+++ b/.changeset/whole-hands-cut.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': minor
+---
+
+**BREAKING**: The `CommonAnalyticsContext` has been removed, and inlined into `AnalyticsContextValue` instead.
diff --git a/.changeset/wicked-dingos-stand.md b/.changeset/wicked-dingos-stand.md
deleted file mode 100644
index 92d84825d1..0000000000
--- a/.changeset/wicked-dingos-stand.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/core-plugin-api': patch
----
-
-The `TranslationApi` now 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.
diff --git a/.changeset/wild-apes-care.md b/.changeset/wild-apes-care.md
new file mode 100644
index 0000000000..36bc822ec8
--- /dev/null
+++ b/.changeset/wild-apes-care.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-scaffolder-node-test-utils': patch
+'@backstage/plugin-scaffolder-backend': minor
+'@backstage/plugin-scaffolder-node': patch
+---
+
+Add step info to scaffolder action context to access the step id and name.
diff --git a/.changeset/wise-cobras-sink.md b/.changeset/wise-cobras-sink.md
deleted file mode 100644
index 7a6a73c726..0000000000
--- a/.changeset/wise-cobras-sink.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/canon': patch
----
-
-Use the Field component from Base UI within the TextField.
diff --git a/.changeset/wise-pillows-smile.md b/.changeset/wise-pillows-smile.md
deleted file mode 100644
index febdeab2c4..0000000000
--- a/.changeset/wise-pillows-smile.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'yarn-plugin-backstage': patch
----
-
-Add both `npm:` and `backstage:` ranges to the lockfile to ensure compatibility with tools that parse the lockfile and ensure dependencies stay locked when building dist workspaces.
diff --git a/.changeset/yellow-beans-eat.md b/.changeset/yellow-beans-eat.md
deleted file mode 100644
index 2380b19a6f..0000000000
--- a/.changeset/yellow-beans-eat.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@backstage/plugin-catalog': patch
----
-
-Fix for missing `routeRef` when using `core-plugin-api` in a dialog context
diff --git a/.changeset/yellow-cows-tickle.md b/.changeset/yellow-cows-tickle.md
deleted file mode 100644
index 026c7444f0..0000000000
--- a/.changeset/yellow-cows-tickle.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@backstage/catalog-client': minor
-'@backstage/plugin-catalog-react': minor
-'@backstage/plugin-catalog-node': minor
----
-
-Add `getLocations` method to `CatalogApi` and `CatalogClient`. This method calls the [`GET /locations`](https://backstage.io/docs/features/software-catalog/software-catalog-api/#get-locations) endpoint from the catalog backend.
diff --git a/.changeset/yellow-ducks-burn.md b/.changeset/yellow-ducks-burn.md
new file mode 100644
index 0000000000..c76a548d54
--- /dev/null
+++ b/.changeset/yellow-ducks-burn.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Allow js files to be processed by the nodeTransform loader
diff --git a/.eslintignore b/.eslintignore
index ea8f6760c7..5cfe8188d3 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,7 +7,7 @@
**/.git/**
**/public/**
**/microsite/**
-**/canon-docs/**
+**/docs-ui/**
**/templates/**
**/sample-templates/**
playwright.config.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index 409b820783..54f9e69576 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -18,8 +18,26 @@ var path = require('path');
module.exports = {
root: true,
- plugins: ['@spotify', 'notice', 'react', 'testing-library'],
+ plugins: ['@spotify', 'notice', 'react', 'testing-library', '@backstage'],
rules: {
+ '@backstage/no-mixed-plugin-imports': [
+ 'error',
+ {
+ // TODO: Fix these either by right role or by moving things to new packages
+ excludedTargetPackages: [
+ '@backstage/plugin-catalog',
+ '@backstage/plugin-techdocs',
+ '@backstage/plugin-app',
+ '@backstage/plugin-catalog-backend',
+ '@backstage/test-utils',
+ '@backstage/plugin-auth-backend',
+ '@backstage/plugin-permission-backend',
+ '@backstage/plugin-kubernetes-backend',
+ '@backstage/config-loader',
+ '@backstage/plugin-app-backend'
+ ],
+ }
+ ],
'react/react-in-jsx-scope': 'off',
'notice/notice': [
'error',
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 4c51c8f111..89fba0c8ad 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -7,28 +7,52 @@
* @backstage/maintainers @backstage/reviewers
yarn.lock @backstage/maintainers @backstage-service
*/yarn.lock @backstage/maintainers @backstage-service
+/.changeset @backstage/operations-maintainers
/.changeset/*.md
+/.github @backstage/operations-maintainers
/beps/0001-notifications-system @backstage/maintainers @backstage/notifications-maintainers
/docs @backstage/maintainers @backstage/documentation-maintainers
/docs/assets/search @backstage/search-maintainers
-/docs/features/search @backstage/search-maintainers
+/docs/auth @backstage/auth-maintainers
+/docs/backend-system @backstage/framework-maintainers
+/docs/deployment @backstage/tooling-maintainers
/docs/dls @backstage/design-system-maintainers
+/docs/features/search @backstage/search-maintainers
/docs/features/techdocs @backstage/techdocs-maintainers
+/docs/permissions @backstage/permission-maintainers
/docs/plugins/integrating-search-into-plugins.md @backstage/search-maintainers
+/docs/releases @backstage/operations-maintainers
+/docs/tooling @backstage/tooling-maintainers
/microsite @backstage/documentation-maintainers
/microsite/data/plugins @backstage/maintainers
-/packages/cli/src/commands/onboard @backstage/sharks
+/microsite/static @backstage/maintainers @backstage/documentation-maintainers
+/packages @backstage/framework-maintainers
/packages/backend-openapi-utils @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers
-/packages/canon @backstage/design-system-maintainers
+/packages/catalog-client @backstage/catalog-maintainers
+/packages/catalog-model @backstage/catalog-maintainers
+/packages/cli @backstage/tooling-maintainers
+/packages/cli-* @backstage/tooling-maintainers
+/packages/cli/src/commands/onboard @backstage/sharks
+/packages/e2e-test @backstage/operations-maintainers
+/packages/eslint-plugin @backstage/tooling-maintainers
+/packages/release-manifests @backstage/operations-maintainers
+/packages/repo-tools @backstage/tooling-maintainers
/packages/techdocs-cli @backstage/techdocs-maintainers
/packages/techdocs-cli-embedded-app @backstage/techdocs-maintainers
+/packages/ui @backstage/design-system-maintainers
+/packages/yarn-plugin @backstage/tooling-maintainers
+/plugins/app @backstage/framework-maintainers
+/plugins/app-* @backstage/framework-maintainers
+/plugins/auth @backstage/auth-maintainers
+/plugins/auth-* @backstage/auth-maintainers
/plugins/api-docs @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers
/plugins/bitbucket-cloud-common @backstage/maintainers @backstage/reviewers @pjungermann
/plugins/catalog @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers
/plugins/catalog-* @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers
/plugins/catalog-backend-module-aws @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann
/plugins/catalog-backend-module-bitbucket-cloud @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann
-/plugins/catalog-backend-module-backstage-openapi @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers
+/plugins/catalog-backend-module-backstage-openapi @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers
+/plugins/catalog-backend-module-gitea @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers
/plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann
/plugins/catalog-backend-module-puppetdb @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers
/plugins/catalog-graph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @backstage/sda-se-reviewers
@@ -56,6 +80,8 @@ yarn.lock @backstage/maintainers @backst
/plugins/user-settings-backend @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers
/plugins/user-settings-common @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers
+/scripts @backstage/operations-maintainers
+
/packages/backend-plugin-api/src/services/definitions/AuditorService.ts @backstage/maintainers @backstage/auditor-maintainers
/packages/backend-defaults/src/entrypoints/auditor @backstage/maintainers @backstage/auditor-maintainers
/packages/backend-defaults/report-auditor.api.md @backstage/maintainers @backstage/auditor-maintainers
diff --git a/.github/ISSUE_TEMPLATE/.common.yaml b/.github/ISSUE_TEMPLATE/.common.yaml
index c870b21b94..eac60aaa2b 100644
--- a/.github/ISSUE_TEMPLATE/.common.yaml
+++ b/.github/ISSUE_TEMPLATE/.common.yaml
@@ -42,6 +42,7 @@ body:
- Events System
- Home
- Kubernetes Plugin
+ - Management of this repository
- Microsite
- Notifications
- OpenAPI Tooling
diff --git a/.github/ISSUE_TEMPLATE/01_bug.yaml b/.github/ISSUE_TEMPLATE/01_bug.yaml
index ccaebe8bff..303a4fcc61 100644
--- a/.github/ISSUE_TEMPLATE/01_bug.yaml
+++ b/.github/ISSUE_TEMPLATE/01_bug.yaml
@@ -58,6 +58,7 @@ body:
- Events System
- Home
- Kubernetes Plugin
+ - Management of this repository
- Microsite
- Notifications
- OpenAPI Tooling
diff --git a/.github/ISSUE_TEMPLATE/02_documentation.yaml b/.github/ISSUE_TEMPLATE/02_documentation.yaml
index dc9ede2c53..aaf54fc4a0 100644
--- a/.github/ISSUE_TEMPLATE/02_documentation.yaml
+++ b/.github/ISSUE_TEMPLATE/02_documentation.yaml
@@ -37,6 +37,7 @@ body:
- Events System
- Home
- Kubernetes Plugin
+ - Management of this repository
- Microsite
- Notifications
- OpenAPI Tooling
diff --git a/.github/ISSUE_TEMPLATE/03_suggestion.yaml b/.github/ISSUE_TEMPLATE/03_suggestion.yaml
index cafdd7066f..05a98e0956 100644
--- a/.github/ISSUE_TEMPLATE/03_suggestion.yaml
+++ b/.github/ISSUE_TEMPLATE/03_suggestion.yaml
@@ -50,6 +50,7 @@ body:
- Events System
- Home
- Kubernetes Plugin
+ - Management of this repository
- Microsite
- Notifications
- OpenAPI Tooling
diff --git a/.github/ISSUE_TEMPLATE/04_maintenance.yaml b/.github/ISSUE_TEMPLATE/04_maintenance.yaml
index bf81efa5f6..da25225e68 100644
--- a/.github/ISSUE_TEMPLATE/04_maintenance.yaml
+++ b/.github/ISSUE_TEMPLATE/04_maintenance.yaml
@@ -48,6 +48,7 @@ body:
- Events System
- Home
- Kubernetes Plugin
+ - Management of this repository
- Microsite
- Notifications
- OpenAPI Tooling
diff --git a/.github/advanced-issue-labeler.yml b/.github/advanced-issue-labeler.yml
index 4148b4236c..dfd6a036c9 100644
--- a/.github/advanced-issue-labeler.yml
+++ b/.github/advanced-issue-labeler.yml
@@ -9,8 +9,8 @@ policy:
keys: ['Auth']
- name: 'area:catalog'
keys: ['Catalog']
- - name: 'area:core'
- keys: ['Core Framework', 'CLI Tooling']
+ - name: 'area:framework'
+ keys: ['Core Framework']
- name: 'area:design-system'
keys: ['Design System']
- name: 'area:documentation'
@@ -25,6 +25,8 @@ policy:
keys: ['Notifications']
- name: 'area:openapi-tooling'
keys: ['OpenAPI Tooling']
+ - name: 'area:operations'
+ keys: ['Management of this repository']
- name: 'area:permission'
keys: ['Permission Framework']
- name: 'area:search'
@@ -33,6 +35,8 @@ policy:
keys: ['Software Templates']
- name: 'area:techdocs'
keys: ['TechDocs']
+ - name: 'area:tooling'
+ keys: ['CLI Tooling']
- id: ['integration']
block-list: []
label:
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000000..4f0e0ac47d
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,31 @@
+This is a TypeScript project structured as a monorepo using Yarn workspaces.
+
+## Code Standards
+
+The following files contain guidelines for the project:
+
+- `/STYLE.md`: guidelines for code style.
+- `/REVIEWING.md`: guidelines for pull requests.
+- `/SECURITY.md`: guidelines for security.
+- `/docs/architecture-decisions/`: contains the architecture decisions for the project.
+
+## Development Flow
+
+Before any of these commands can be run, you need to run `yarn install` in the project root.
+
+- Build: There is no need to build the project during development, and it is verified automatically in the CI pipeline.
+- Test: Use `yarn test ` in the project root to run tests. The path can be either a single file or a directory, and be omitted to run tests for all changed files.
+- Type checking: Use `yarn tsc` in the project root to run the type checker.
+- Code formatting: Use `yarn prettier --write ` to format code.
+- Lint: Use `yarn lint --fix` in the project root to run the linter.
+- API reports: Before submitting a pull request with changes to any package in the workspace, run `yarn build:api-reports` in the project root to generate API reports for all packages.
+
+You MUST NOT create a release by running `yarn changesets version` or `yarn release` as part of any changes. Releases are created by separate workflows.
+
+All changes that affect the published version of packages in the `/packages` and `/plugins` directories must be accompanied by a changeset. See the guidelines in `/REVIEWING.md` for information on how to write good changesets. Changesets are stored in the `/.changeset` directory. Breaking changes must be accompanied by a `minor` version bump for packages that below version `1.0.0`, or a `major` version bump for packages that are at version `1.0.0` or higher.
+
+Never update ESLint, Prettier, or TypeScript configuration files unless specifically requested.
+
+## Repository Structure
+
+See `/docs/contribute/project-structure.md` for a detailed description of the repository structure.
diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 77faa9354f..da3cf3e8fb 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -31,9 +31,9 @@
matchSourceUrls: ['https://github.com/microsoft/rushstack{/,}**'],
},
{
- groupName: 'SVGR monorepo packages',
+ groupName: 'Module-federation monorepo packages',
rangeStrategy: 'replace',
- matchSourceUrls: ['https://github.com/gregberge/svgr{/,}**'],
+ matchSourceUrls: ['https://github.com/module-federation/core{/,}**'],
},
// We update yarn packages manually as it's gzip'd and we don't want to pollute the repository too much.
{
diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt
index f9a0595489..4682640f90 100644
--- a/.github/vale/config/vocabularies/Backstage/accept.txt
+++ b/.github/vale/config/vocabularies/Backstage/accept.txt
@@ -10,6 +10,7 @@ Airbrakes
ajv
Alaria
Alef
+allowedHosts
allowlisted
Anddddd
Apdex
@@ -43,6 +44,7 @@ bugfixes
builtins
bundler
bundlers
+bursty
callout
CDNs
Chai
@@ -89,6 +91,7 @@ CVEs
daemonsets
Datadog
dataflow
+dataloader
dayjs
debounce
debounces
@@ -101,6 +104,8 @@ deliverables
denormalized
dependabot
deps
+dequeue
+dequeueing
deserialization
destructured
destructuring
@@ -110,8 +115,6 @@ devcontainer
devcontainers
devops
devs
-dequeue
-dequeueing
dialogs
disambiguator
discoverability
@@ -149,8 +152,8 @@ FireHydrant
Firekube
Firestore
Fiverr
-Flightcontrol
flightcontrol
+Flightcontrol
Francesco
Frontside
Gaurav
@@ -174,8 +177,8 @@ Hackathons
haproxy
hardcoded
hardcoding
-Harness
harness
+Harness
Helidon
Henneke
Heroku
@@ -198,9 +201,10 @@ Indal
indexable
ingestors
inlined
-inlining
inlinehilite
+inlining
integrator's
+intellij
interop
interoperate
iterable
@@ -284,6 +288,7 @@ namespaced
namespaces
Namespaces
namespacing
+navbar
neuro
newrelic
nginx
@@ -303,6 +308,7 @@ oidc
Okta
Olausson
Oldsberg
+onboarded
onboarding
Onboarding
onelogin
@@ -310,14 +316,16 @@ OpenSearch
OpenShift
openssl
orgs
-Overridable
overridable
+Overridable
padding
paddings
pagerduty
pageview
Pandey
parallelization
+param
+params
parseable
Patrik
pattison
@@ -362,6 +370,7 @@ readonly
rebase
rebasing
Recharts
+redactions
Redash
redis
reimplement
@@ -371,6 +380,7 @@ replicasets
repo
Repo
repos
+requestors
rerender
rerenders
resourcequotas
@@ -380,8 +390,11 @@ Reusability
roadmaps
rollbar
rollout
+rollouts
Roboto
+rollbar
Rollbar
+rollout
Rollup
routable
Routable
@@ -397,9 +410,10 @@ sanitization
scaffolded
scaffolder
Scaffolder
-scrollbar
SCM
SCMs
+scrollable
+scrollbar
sdks
seb
semlas
@@ -407,14 +421,15 @@ semver
sendmail
serializable
Serverless
+severities
shoutout
SIG
signoff
SIGs
siloed
Sinon
-snackbars
snackbar
+snackbars
Snyk
Sonarqube
sourcemaps
@@ -431,6 +446,7 @@ statefulsets
stdout
storable
storages
+Streamable
stringified
stringify
subcommand
@@ -451,6 +467,7 @@ Superfences
superset
supertype
SVGs
+swappable
talkdesk
Talkdesk
Tanzu
@@ -484,6 +501,7 @@ transpiled
transpiler
transpilers
truthy
+tsconfig
TSDoc
typeahead
ui
@@ -534,7 +552,4 @@ zod
Zolotusky
zoomable
zsh
-scrollable
-severities
-intellij
-tsconfig
+resizable
diff --git a/.github/workflows/api-breaking-changes-comment.yml b/.github/workflows/api-breaking-changes-comment.yml
index af625f67ab..ee215ba8dd 100644
--- a/.github/workflows/api-breaking-changes-comment.yml
+++ b/.github/workflows/api-breaking-changes-comment.yml
@@ -23,7 +23,7 @@ jobs:
comment-cache-key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
disable-sudo: true
egress-policy: block
@@ -74,7 +74,7 @@ jobs:
- name: Cache Comment
if: ${{ steps.event.outputs.ACTION != 'closed' }}
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: comment.md
key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }}
diff --git a/.github/workflows/api-breaking-changes.yml b/.github/workflows/api-breaking-changes.yml
index 74473f30d5..f72d9c29bf 100644
--- a/.github/workflows/api-breaking-changes.yml
+++ b/.github/workflows/api-breaking-changes.yml
@@ -14,7 +14,7 @@ jobs:
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml
index ec6dd0c85c..f21ef62d8d 100644
--- a/.github/workflows/automate_area-labels.yml
+++ b/.github/workflows/automate_area-labels.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml
index c1245c59b9..c41f4dd8f3 100644
--- a/.github/workflows/automate_changeset_feedback.yml
+++ b/.github/workflows/automate_changeset_feedback.yml
@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml
index ebe2ef739d..59da292109 100644
--- a/.github/workflows/automate_merge_message.yml
+++ b/.github/workflows/automate_merge_message.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml
index 6be74ae99f..d6c86b9afb 100644
--- a/.github/workflows/automate_stale.yml
+++ b/.github/workflows/automate_stale.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml
index 472a7a4e72..35901d37b2 100644
--- a/.github/workflows/ci-noop.yml
+++ b/.github/workflows/ci-noop.yml
@@ -40,7 +40,7 @@ jobs:
name: Test ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 059596265e..ba1d1047a3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -28,7 +28,7 @@ jobs:
name: Install ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -64,7 +64,7 @@ jobs:
name: Verify ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -127,9 +127,9 @@ jobs:
- name: build all packages
run: yarn backstage-cli repo build --all
- # For now canon has a custom build script and needs to be built separately
- - name: build canon
- run: yarn --cwd packages/canon build
+ # For now BUI has a custom build script and needs to be built separately
+ - name: build BUI
+ run: yarn --cwd packages/ui build
- name: verify type dependencies
run: yarn lint:type-deps
diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml
index b48bd2683d..285c2e6c41 100644
--- a/.github/workflows/cron.yml
+++ b/.github/workflows/cron.yml
@@ -10,7 +10,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml
index e1547801ef..e0f4ec29ed 100644
--- a/.github/workflows/deploy_docker-image.yml
+++ b/.github/workflows/deploy_docker-image.yml
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -52,17 +52,17 @@ jobs:
working-directory: ./example-app
- name: Login to GitHub Container Registry
- uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
+ uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
+ uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Build and push
- uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
+ uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: './example-app'
file: ./example-app/packages/backend/Dockerfile
diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml
index 5045e0c96f..cf596fde4b 100644
--- a/.github/workflows/deploy_microsite.yml
+++ b/.github/workflows/deploy_microsite.yml
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -80,6 +80,34 @@ jobs:
if-no-files-found: error
retention-days: 1
+ # Use the lower-level cache actions for the success cache, so that we can store the cache even on failed builds
+ - name: restore package-docs cache
+ uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-${{ github.run_id }}
+ restore-keys: |
+ ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-
+
+ - name: build API reference (beta)
+ run: yarn backstage-repo-tools package-docs
+
+ - name: upload API reference (beta)
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: stable-reference-beta
+ path: type-docs/
+ if-no-files-found: error
+ retention-days: 1
+
+ # Always save success cache even if there were failures, that way it can be used in re-triggered builds
+ - name: save package-docs cache
+ uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ if: always()
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-${{ github.run_id }}
+
- name: microsite yarn install
run: yarn install --immutable
working-directory: microsite
@@ -107,7 +135,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -136,20 +164,42 @@ jobs:
if-no-files-found: error
retention-days: 1
- # Also build and upload storybook
- - name: storybook yarn install
- run: yarn install --immutable
- working-directory: storybook
+ # Use the lower-level cache actions for the success cache, so that we can store the cache even on failed builds
+ - name: restore package-docs cache
+ uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-${{ github.run_id }}
+ restore-keys: |
+ ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-
- - name: storybook build
+ - name: build API reference (beta)
+ run: yarn backstage-repo-tools package-docs
+
+ - name: upload API reference (beta)
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: next-reference-beta
+ path: type-docs/
+ if-no-files-found: error
+ retention-days: 1
+
+ # Always save success cache even if there were failures, that way it can be used in re-triggered builds
+ - name: save package-docs cache
+ uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ if: always()
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-${{ github.run_id }}
+
+ - name: Build Storybook
run: yarn build-storybook
- working-directory: storybook
- - name: storybook upload
+ - name: Upload Storybook
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: storybook
- path: storybook/dist/
+ path: dist-storybook
if-no-files-found: error
retention-days: 1
@@ -190,7 +240,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -265,8 +315,18 @@ jobs:
name: storybook
path: microsite/build/storybook
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ with:
+ name: stable-reference-beta
+ path: microsite/build/api/stable/
+
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ with:
+ name: next-reference-beta
+ path: microsite/build/api/next/
+
- name: Check the build output
- run: ls microsite/build && ls microsite/build/storybook
+ run: ls microsite/build && ls microsite/build/storybook && ls microsite/build/api/stable && ls microsite/build/api/next
- name: Deploy both microsite and storybook to gh-pages
uses: JamesIves/github-pages-deploy-action@6c2d9db40f9296374acc17b90404b6e8864128c8 # v4.7.3
diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml
index b1d79713a4..2a82ddc2a3 100644
--- a/.github/workflows/deploy_packages.yml
+++ b/.github/workflows/deploy_packages.yml
@@ -110,9 +110,9 @@ jobs:
- name: build
run: yarn backstage-cli repo build --all
- # For now canon has a custom build script and needs to be built separately
- - name: build canon
- run: yarn --cwd packages/canon build
+ # For now BUI has a custom build script and needs to be built separately
+ - name: build BUI
+ run: yarn --cwd packages/ui build
- name: verify type dependencies
run: yarn lint:type-deps
@@ -151,7 +151,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml
index 50d0e4ceb0..17c76c19c2 100644
--- a/.github/workflows/issue.yaml
+++ b/.github/workflows/issue.yaml
@@ -16,7 +16,7 @@ jobs:
if: github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml
index e2bdb4c1cb..d5970deae8 100644
--- a/.github/workflows/pr-review-comment-trigger.yaml
+++ b/.github/workflows/pr-review-comment-trigger.yaml
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml
index e108f3a4d7..9db0792eaa 100644
--- a/.github/workflows/pr-review-comment.yaml
+++ b/.github/workflows/pr-review-comment.yaml
@@ -17,7 +17,7 @@ jobs:
steps:
# Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index ab2630c2d9..33dd3d00ce 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -18,7 +18,7 @@ jobs:
if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request )
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 45eb5de5c8..a1ab80ac79 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -29,7 +29,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -39,7 +39,7 @@ jobs:
persist-credentials: false
- name: 'Run analysis'
- uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
+ uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
- uses: github/codeql-action/upload-sarif@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+ uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
sarif_file: results.sarif
diff --git a/.github/workflows/sync_canon.yml b/.github/workflows/sync_canon.yml
index 2177177df0..3b85c1c49d 100644
--- a/.github/workflows/sync_canon.yml
+++ b/.github/workflows/sync_canon.yml
@@ -1,14 +1,14 @@
-name: Sync Canon Docs
+name: Sync BUI Docs
on:
push:
branches: [master]
jobs:
- sync-canon-docs:
+ sync-docs-ui:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -26,36 +26,36 @@ jobs:
with:
cache-prefix: ${{ runner.os }}-v20.x
- - name: Checkout backstage/canon-docs
+ - name: Checkout backstage/docs-ui
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
- repository: backstage/canon-docs
- path: canon-external-docs
+ repository: backstage/docs-ui
+ path: bui-external-docs
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
- name: Configure Git
run: |
git config --global user.email noreply@backstage.io
- git config --global user.name 'Github Canon Docs workflow'
+ git config --global user.name 'Github BUI Docs workflow'
- name: Install dependencies
- working-directory: canon-docs
+ working-directory: docs-ui
run: yarn install
- - name: Build Canon Docs
- working-directory: canon-docs
+ - name: Build Docs UI
+ working-directory: docs-ui
run: |
yarn build
- - name: Replace contents of canon-external-docs repo with docs build output
- working-directory: canon-external-docs
+ - name: Replace contents of bui-external-docs repo with docs build output
+ working-directory: bui-external-docs
run: |
git rm -rf .
- cp -R ../canon-docs/dist/. .
+ cp -R ../docs-ui/dist/. .
- - name: Commit to canon-storybook repo
- working-directory: canon-external-docs
+ - name: Commit to bui-storybook repo
+ working-directory: bui-external-docs
run: |
git add .
- git commit -am "Canon Docs build for backstage/backstage@${{ github.sha }}"
+ git commit -am "BUI Docs build for backstage/backstage@${{ github.sha }}"
git push
diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml
index ee97f3fef3..33cab94280 100644
--- a/.github/workflows/sync_code-formatting.yml
+++ b/.github/workflows/sync_code-formatting.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -30,7 +30,7 @@ jobs:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- name: Run Prettier on ADOPTERS.md
- uses: creyD/prettier_action@31355f8eef017f8aeba2e0bc09d8502b13dbbad1 # v4.3
+ uses: creyD/prettier_action@8c18391fdc98ed0d884c6345f03975edac71b8f0 # v4.6
with:
# Modifies commit only if prettier autofixed the ADOPTERS.md
prettier_options: --config docs/prettier.config.js --write ADOPTERS.md
diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml
index 42efaa1142..181d48eb38 100644
--- a/.github/workflows/sync_dependabot-changesets.yml
+++ b/.github/workflows/sync_dependabot-changesets.yml
@@ -11,7 +11,7 @@ jobs:
if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml
index 1c9d37aef0..a9c4b3722b 100644
--- a/.github/workflows/sync_release-manifest.yml
+++ b/.github/workflows/sync_release-manifest.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml
index 2eb8f13dbc..2331e2c30f 100644
--- a/.github/workflows/sync_renovate-changesets.yml
+++ b/.github/workflows/sync_renovate-changesets.yml
@@ -11,7 +11,7 @@ jobs:
if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml
index b7cc0b33c7..3716c1f48b 100644
--- a/.github/workflows/sync_snyk-github-issues.yml
+++ b/.github/workflows/sync_snyk-github-issues.yml
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -29,7 +29,7 @@ jobs:
cache-prefix: ${{ runner.os }}-v20.x
- name: Create Snyk report
- uses: snyk/actions/node@cdb760004ba9ea4d525f2e043745dfe85bb9077e # master
+ uses: snyk/actions/node@77490d94e966421e076e95ad8fa87aa55e5ca409 # master
continue-on-error: true # Snyk CLI exits with error when vulnerabilities are found
with:
args: >
diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml
index 741471d558..cfebf43554 100644
--- a/.github/workflows/sync_snyk-monitor.yml
+++ b/.github/workflows/sync_snyk-monitor.yml
@@ -25,13 +25,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Monitor and Synchronize Snyk Policies
- uses: snyk/actions/node@cdb760004ba9ea4d525f2e043745dfe85bb9077e # master
+ uses: snyk/actions/node@77490d94e966421e076e95ad8fa87aa55e5ca409 # master
with:
command: monitor
args: >
@@ -46,7 +46,7 @@ jobs:
# Above we run the `monitor` command, this runs the `test` command which is
# the one that generates the SARIF report that we can upload to GitHub.
- name: Create Snyk report
- uses: snyk/actions/node@cdb760004ba9ea4d525f2e043745dfe85bb9077e # master
+ uses: snyk/actions/node@77490d94e966421e076e95ad8fa87aa55e5ca409 # master
continue-on-error: true # To make sure that SARIF upload gets called
with:
args: >
@@ -58,6 +58,6 @@ jobs:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
NODE_OPTIONS: --max-old-space-size=7168
- name: Upload Snyk report
- uses: github/codeql-action/upload-sarif@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+ uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
sarif_file: snyk.sarif
diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml
index 4a33b2241e..e33651a69e 100644
--- a/.github/workflows/sync_version-packages.yml
+++ b/.github/workflows/sync_version-packages.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -24,13 +24,10 @@ jobs:
fetch-tags: true
token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
- - name: Fetch tags # See https://github.com/actions/checkout/issues/2041
- run: git fetch --tags
-
- name: Install Dependencies
run: yarn --immutable
- name: Create Release Pull Request
- uses: backstage/changesets-action@291bfc1f76d1dcfbf967f5810dc0423592eae09a # v2.3.1
+ uses: backstage/changesets-action@a39baf18913e669734ffb00c2fd9900472cfa240 # v2.3.2
with:
# Calls out to `changeset version`, but also runs prettier
version: yarn release
diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml
index c33acfd86d..df6f004171 100644
--- a/.github/workflows/verify_accessibility-noop.yml
+++ b/.github/workflows/verify_accessibility-noop.yml
@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml
index 02a303f9ea..48e243b002 100644
--- a/.github/workflows/verify_accessibility.yml
+++ b/.github/workflows/verify_accessibility.yml
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml
index c4b21a9e1f..99915974a4 100644
--- a/.github/workflows/verify_codeql.yml
+++ b/.github/workflows/verify_codeql.yml
@@ -42,7 +42,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -55,7 +55,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+ uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -66,7 +66,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+ uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -80,4 +80,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+ uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml
index a3b80f498a..6c855eeea4 100644
--- a/.github/workflows/verify_docs-quality.yml
+++ b/.github/workflows/verify_docs-quality.yml
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml
index 65fc6eccc9..aa3358f2f7 100644
--- a/.github/workflows/verify_e2e-linux-noop.yml
+++ b/.github/workflows/verify_e2e-linux-noop.yml
@@ -29,7 +29,7 @@ jobs:
name: E2E Linux ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml
index 0995a85216..5ff4d2b0ce 100644
--- a/.github/workflows/verify_e2e-linux.yml
+++ b/.github/workflows/verify_e2e-linux.yml
@@ -43,7 +43,7 @@ jobs:
name: E2E Linux ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml
index fc30b377bc..080d14a743 100644
--- a/.github/workflows/verify_e2e-techdocs.yml
+++ b/.github/workflows/verify_e2e-techdocs.yml
@@ -32,7 +32,7 @@ jobs:
name: Techdocs
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml
index e713f33ed6..b1a4344bfc 100644
--- a/.github/workflows/verify_e2e-windows-noop.yml
+++ b/.github/workflows/verify_e2e-windows-noop.yml
@@ -25,7 +25,7 @@ jobs:
name: E2E Windows ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml
index 0dc0bdaade..eefcf22b35 100644
--- a/.github/workflows/verify_e2e-windows.yml
+++ b/.github/workflows/verify_e2e-windows.yml
@@ -33,7 +33,7 @@ jobs:
name: E2E Windows ${{ matrix.node-version }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml
index 7bc612bf64..9c811fbe9f 100644
--- a/.github/workflows/verify_fossa.yml
+++ b/.github/workflows/verify_fossa.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml
index da4bc6ba25..3466826cae 100644
--- a/.github/workflows/verify_microsite-noop.yml
+++ b/.github/workflows/verify_microsite-noop.yml
@@ -21,7 +21,7 @@ jobs:
name: Microsite
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml
index c22648bb8c..df72927514 100644
--- a/.github/workflows/verify_microsite.yml
+++ b/.github/workflows/verify_microsite.yml
@@ -28,7 +28,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -85,6 +85,32 @@ jobs:
if-no-files-found: error
retention-days: 1
+ # Use the lower-level cache actions for the success cache, so that we can store the cache even on failed builds
+ - name: restore package-docs cache
+ uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-${{ github.run_id }}
+ restore-keys: |
+ ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-
+
+ - name: build API reference (beta)
+ run: yarn backstage-repo-tools package-docs
+
+ - name: upload API reference (beta)
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: stable-reference-beta
+ path: type-docs/
+
+ # Always save success cache even if there were failures, that way it can be used in re-triggered builds
+ - name: save package-docs cache
+ uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ if: always()
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-stable-${{ github.run_id }}
+
- name: microsite yarn install
run: yarn install --immutable
working-directory: microsite
@@ -111,7 +137,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -140,20 +166,40 @@ jobs:
if-no-files-found: error
retention-days: 1
- # Also build and upload storybook
- - name: storybook yarn install
- run: yarn install --immutable
- working-directory: storybook
+ # Use the lower-level cache actions for the success cache, so that we can store the cache even on failed builds
+ - name: restore package-docs cache
+ uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-next-${{ github.run_id }}
+ restore-keys: |
+ ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-next-
- - name: storybook build
+ - name: build API reference (beta)
+ run: yarn backstage-repo-tools package-docs
+
+ - name: upload API reference (beta)
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: next-reference-beta
+ path: type-docs/
+
+ # Always save success cache even if there were failures, that way it can be used in re-triggered builds
+ - name: save package-docs cache
+ uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4
+ if: always()
+ with:
+ path: .cache/package-docs
+ key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-next-${{ github.run_id }}
+
+ - name: Build Storybook
run: yarn build-storybook
- working-directory: storybook
- - name: storybook upload
+ - name: Upload Storybook
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: storybook
- path: storybook/dist/
+ path: dist-storybook
if-no-files-found: error
retention-days: 1
@@ -188,7 +234,7 @@ jobs:
name: Microsite
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
@@ -271,3 +317,15 @@ jobs:
- name: build microsite
run: yarn build
working-directory: microsite
+
+ - name: download stable reference (beta)
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ with:
+ name: stable-reference-beta
+ path: api/stable/
+
+ - name: download next reference (beta)
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
+ with:
+ name: next-reference-beta
+ path: api/next/
diff --git a/.github/workflows/verify_microsite_accessibility-noop.yml b/.github/workflows/verify_microsite_accessibility-noop.yml
index d6f9d24b5e..5e0bc35cc0 100644
--- a/.github/workflows/verify_microsite_accessibility-noop.yml
+++ b/.github/workflows/verify_microsite_accessibility-noop.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_microsite_accessibility.yml b/.github/workflows/verify_microsite_accessibility.yml
index ee841f6fa8..40e1866b5f 100644
--- a/.github/workflows/verify_microsite_accessibility.yml
+++ b/.github/workflows/verify_microsite_accessibility.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml
index 392a218a83..98ce6b26a1 100644
--- a/.github/workflows/verify_storybook-noop.yml
+++ b/.github/workflows/verify_storybook-noop.yml
@@ -28,7 +28,7 @@ jobs:
name: Storybook
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml
index 3cc846a706..5a71caba85 100644
--- a/.github/workflows/verify_storybook.yml
+++ b/.github/workflows/verify_storybook.yml
@@ -4,7 +4,8 @@ on:
pull_request:
paths:
- '.github/workflows/verify_storybook.yml'
- - 'storybook/**'
+ - '.storybook/**'
+ - 'packages/ui/src/**'
- 'packages/config/src/**'
- 'packages/theme/src/**'
- 'packages/types/src/**'
@@ -28,37 +29,34 @@ jobs:
name: Storybook
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - name: Checkout code
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Required to retrieve git history
- - name: use node.js ${{ matrix.node-version }}
+ - name: Use node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- - name: yarn install
+
+ - name: Install dependencies
uses: backstage/actions/yarn-install@b3c1841fd69e1658ac631afafd0fb140a2309024 # v0.6.17
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- - name: storybook yarn install
- run: yarn install --immutable
- working-directory: storybook
- # Only for verification, the canon one is what we upload to Chromatic
- - run: yarn build-storybook
+ - name: Build Storybook
+ run: yarn build-storybook
- - run: yarn --cwd packages/canon build-storybook
-
- - uses: chromaui/action@e8cc4c31775280b175a3c440076c00d19a9014d7 # v11
+ - name: Deploy Storybook to Chromatic
+ uses: chromaui/action@1cfa065cbdab28f6ca3afaeb3d761383076a35aa # v11
with:
token: ${{ secrets.GITHUB_TOKEN }}
# projectToken intentionally shared to allow collaborators to run Chromatic on forks
# https://www.chromatic.com/docs/custom-ci-provider#run-chromatic-on-external-forks-of-open-source-projects
projectToken: chpt_dab72dc0f97d55b
- workingDir: packages/canon
- storybookBuildDir: storybook-static
+ storybookBuildDir: dist-storybook
diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml
index d7b172256d..363bc075b8 100644
--- a/.github/workflows/verify_windows.yml
+++ b/.github/workflows/verify_windows.yml
@@ -29,7 +29,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
+ uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
diff --git a/.gitignore b/.gitignore
index 25280b40b0..aaf05b51cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -183,4 +183,7 @@ knip.json
# Typedocs temporary files
type-docs
docs.json
-tsconfig.typedoc.tmp.json
\ No newline at end of file
+tsconfig.typedoc.tmp.json
+
+# Storybook
+dist-storybook/
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index 04ca7d780d..718387ef22 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,10 +1,10 @@
.yarn
dist
microsite
-canon-docs/.next
-canon-docs/public
-canon-docs/out
-packages/canon/css
+docs-ui/.next
+docs-ui/public
+docs-ui/out
+packages/ui/css
coverage
*.hbs
templates
diff --git a/storybook/.storybook/main.ts b/.storybook/main.ts
similarity index 79%
rename from storybook/.storybook/main.ts
rename to .storybook/main.ts
index e2f5baf207..caf2d744e3 100644
--- a/storybook/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -2,10 +2,9 @@ import type { StorybookConfig } from '@storybook/react-vite';
import { join, dirname, posix } from 'path';
-/**
- * This set of stories are the ones that we publish to backstage.io.
- */
+// This set of stories are the ones that we publish to backstage.io.
const backstageCoreStories = [
+ 'packages/ui',
'packages/core-components',
'packages/app',
'plugins/org',
@@ -15,7 +14,7 @@ const backstageCoreStories = [
'plugins/catalog-react',
];
-const rootPath = '../../';
+const rootPath = '../';
const storiesSrcMdx = 'src/**/*.mdx';
const storiesSrcGlob = 'src/**/*.stories.@(js|jsx|mjs|ts|tsx)';
@@ -27,10 +26,7 @@ const stories = backstageCoreStories.flatMap(element => [
getStoriesPath(element, storiesSrcGlob),
]);
-/**
- * This function is used to resolve the absolute path of a package.
- * It is needed in projects that use Yarn PnP or are set up within a monorepo.
- */
+// Resolve absolute path of a package. Needed in monorepos.
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, 'package.json')));
}
@@ -40,7 +36,6 @@ const config: StorybookConfig = {
addons: [
getAbsolutePath('@storybook/addon-links'),
getAbsolutePath('@storybook/addon-essentials'),
- getAbsolutePath('@chromatic-com/storybook'),
getAbsolutePath('@storybook/addon-interactions'),
getAbsolutePath('@storybook/addon-themes'),
getAbsolutePath('@storybook/addon-storysource'),
@@ -50,4 +45,5 @@ const config: StorybookConfig = {
options: {},
},
};
+
export default config;
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
new file mode 100644
index 0000000000..d81c2e9932
--- /dev/null
+++ b/.storybook/preview.tsx
@@ -0,0 +1,126 @@
+import React, { useEffect } from 'react';
+import { TestApiProvider } from '@backstage/test-utils';
+import { Content, AlertDisplay } from '@backstage/core-components';
+import { apis } from './support/apis';
+import type { Decorator, Preview } from '@storybook/react';
+import { useGlobals } from '@storybook/preview-api';
+import { UnifiedThemeProvider, themes } from '@backstage/theme';
+
+// Default Backstage theme CSS (from packages/ui)
+import '../packages/ui/src/css/styles.css';
+
+// Custom Storybook chrome/styles
+import './storybook.css';
+
+// Custom themes
+import './themes/spotify.css';
+
+const preview: Preview = {
+ globalTypes: {
+ themeMode: {
+ name: 'Theme Mode',
+ description: 'Global theme mode for components',
+ defaultValue: 'light',
+ toolbar: {
+ icon: 'circlehollow',
+ items: [
+ { value: 'light', icon: 'circlehollow', title: 'Light' },
+ { value: 'dark', icon: 'circle', title: 'Dark' },
+ ],
+ showName: true,
+ dynamicTitle: true,
+ },
+ },
+ themeName: {
+ name: 'Theme Name',
+ description: 'Global theme name for components',
+ defaultValue: 'backstage',
+ toolbar: {
+ icon: 'paintbrush',
+ items: [
+ { value: 'backstage', title: 'Backstage' },
+ { value: 'spotify', title: 'Spotify' },
+ ],
+ showName: true,
+ dynamicTitle: true,
+ },
+ },
+ },
+ initialGlobals: {
+ themeMode: 'light',
+ themeName: 'backstage',
+ },
+ parameters: {
+ layout: 'fullscreen',
+ backgrounds: {
+ disable: true,
+ },
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/i,
+ },
+ },
+ options: {
+ storySort: {
+ order: ['Backstage UI', 'Plugins', 'Layout', 'Navigation'],
+ },
+ },
+ viewport: {
+ viewports: {
+ initial: {
+ name: 'Initial',
+ styles: { width: '320px', height: '100%' },
+ },
+ xs: { name: 'Extra Small', styles: { width: '640px', height: '100%' } },
+ sm: { name: 'Small', styles: { width: '768px', height: '100%' } },
+ md: { name: 'Medium', styles: { width: '1024px', height: '100%' } },
+ lg: { name: 'Large', styles: { width: '1280px', height: '100%' } },
+ xl: {
+ name: 'Extra Large',
+ styles: { width: '1536px', height: '100%' },
+ },
+ },
+ },
+ },
+ decorators: [
+ Story => {
+ const [globals] = useGlobals();
+ const selectedTheme =
+ globals.themeMode === 'light' ? themes.light : themes.dark;
+ const selectedThemeMode = globals.themeMode || 'light';
+ const selectedThemeName = globals.themeName || 'backstage';
+
+ useEffect(() => {
+ document.body.removeAttribute('data-theme-mode');
+ document.body.removeAttribute('data-theme-name');
+ document.body.setAttribute('data-theme-mode', selectedThemeMode);
+ document.body.setAttribute('data-theme-name', selectedThemeName);
+ return () => {
+ document.body.removeAttribute('data-theme-mode');
+ document.body.removeAttribute('data-theme-name');
+ };
+ }, [selectedTheme, selectedThemeName]);
+
+ document.body.style.backgroundColor = 'var(--bui-bg)';
+ const docsStoryElements = document.getElementsByClassName('docs-story');
+ Array.from(docsStoryElements).forEach(element => {
+ (element as HTMLElement).style.backgroundColor = 'var(--bui-bg)';
+ });
+
+ return (
+
+ {/* @ts-ignore */}
+
+
+
+
+
+
+
+ );
+ },
+ ],
+};
+
+export default preview;
diff --git a/.storybook/storybook.css b/.storybook/storybook.css
new file mode 100644
index 0000000000..e69c4a8eb1
--- /dev/null
+++ b/.storybook/storybook.css
@@ -0,0 +1,38 @@
+:root {
+ --sb-panel-radius: 0;
+ --sb-panel-top: 0;
+ --sb-panel-bottom: 0;
+ --sb-panel-left: 0;
+ --sb-panel-right: 0;
+ --sb-sidebar-border: none;
+ --sb-sidebar-border-right: 1px solid var(--bui-border);
+ --sb-sidebar-bg: #000;
+ --sb-options-border: none;
+ --sb-options-border-left: 1px solid var(--bui-border);
+ --sb-content-padding-inline: 250px;
+}
+
+[data-theme-mode='dark'] {
+ --sb-sidebar-bg: var(--bui-bg-surface-1);
+}
+
+[data-theme-name='spotify'] {
+ --sb-panel-radius: var(--bui-radius-3);
+ --sb-panel-top: 8px;
+ --sb-panel-bottom: 8px;
+ --sb-panel-left: 8px;
+ --sb-panel-right: 8px;
+ --sb-sidebar-border: none;
+ --sb-sidebar-border-right: none;
+ --sb-sidebar-bg: var(--bui-bg-surface-1);
+ --sb-options-border: none;
+ --sb-options-border-left: none;
+ --sb-content-padding-inline: 258px;
+}
+
+[data-theme-name='spotify'][data-theme-mode='light'] {
+ --sb-sidebar-border: 1px solid var(--bui-border);
+ --sb-sidebar-border-right: 1px solid var(--bui-border);
+ --sb-options-border: 1px solid var(--bui-border);
+ --sb-options-border-left: 1px solid var(--bui-border);
+}
diff --git a/storybook/.storybook/apis.js b/.storybook/support/apis.js
similarity index 100%
rename from storybook/.storybook/apis.js
rename to .storybook/support/apis.js
diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css
new file mode 100644
index 0000000000..7544dd183d
--- /dev/null
+++ b/.storybook/themes/spotify.css
@@ -0,0 +1,284 @@
+@font-face {
+ font-family: CircularSpTitle;
+ font-weight: 900;
+ font-display: swap;
+ unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192,
+ U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF,
+ U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD,
+ U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0,
+ U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B,
+ U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026,
+ U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070,
+ U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126,
+ U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5,
+ U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E,
+ U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF,
+ U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788,
+ U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B,
+ U+FFFF;
+ src: url('https://encore.scdn.co/fonts/CircularSpTitle-Black-4588c99025b967475c31695b0743dd1a.woff2')
+ format('woff2'),
+ url('https://encore.scdn.co/fonts/CircularSpTitle-Black-506746f387a26f25aa3d023b3e501d34.woff')
+ format('woff');
+}
+@font-face {
+ font-family: CircularSpTitle;
+ font-weight: 700;
+ font-display: swap;
+ unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192,
+ U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF,
+ U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD,
+ U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0,
+ U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B,
+ U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026,
+ U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070,
+ U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126,
+ U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5,
+ U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E,
+ U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF,
+ U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788,
+ U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B,
+ U+FFFF;
+ src: url('https://encore.scdn.co/fonts/CircularSpTitle-Bold-b2586b06a2e1522e9d879d84c2792a58.woff2')
+ format('woff2'),
+ url('https://encore.scdn.co/fonts/CircularSpTitle-Bold-1624fb2df28c20d7203d7fb86ce8b481.woff')
+ format('woff');
+}
+@font-face {
+ font-family: CircularSp;
+ font-weight: 700;
+ font-display: swap;
+ unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192,
+ U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF,
+ U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD,
+ U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0,
+ U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B,
+ U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026,
+ U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070,
+ U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126,
+ U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5,
+ U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E,
+ U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF,
+ U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788,
+ U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B,
+ U+FFFF;
+ src: url('https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2')
+ format('woff2'),
+ url('https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff')
+ format('woff');
+}
+@font-face {
+ font-family: CircularSp;
+ font-weight: 400;
+ font-display: swap;
+ unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192,
+ U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF,
+ U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD,
+ U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0,
+ U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B,
+ U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026,
+ U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070,
+ U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126,
+ U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5,
+ U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E,
+ U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF,
+ U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788,
+ U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B,
+ U+FFFF;
+ src: url('https://encore.scdn.co/fonts/CircularSp-Book-a00e99ef9996a3a157fb6b746856d04f.woff2')
+ format('woff2'),
+ url('https://encore.scdn.co/fonts/CircularSp-Book-3f73da7d35bd81c706bce7bbb84964de.woff')
+ format('woff');
+}
+
+@font-face {
+ font-family: CircularSp;
+ font-weight: 700;
+ font-display: swap;
+ unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192,
+ U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF,
+ U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD,
+ U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0,
+ U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B,
+ U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026,
+ U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070,
+ U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126,
+ U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5,
+ U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E,
+ U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF,
+ U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788,
+ U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B,
+ U+FFFF;
+ src: url('https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2')
+ format('woff2'),
+ url('https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff')
+ format('woff');
+}
+
+[data-theme-name='spotify'] {
+ --bui-font-text: CircularSp, CircularSp-Arab, CircularSp-Hebr, CircularSp-Cyrl,
+ CircularSp-Grek, CircularSp-Deva;
+ --bui-font-title: CircularSpTitle, CircularSp-Arab, CircularSp-Hebr,
+ CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva;
+ --bui-font-regular: CircularSp, CircularSp-Arab, CircularSp-Hebr,
+ CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva;
+
+ .bui-Button {
+ border-radius: var(--bui-radius-3);
+ padding-inline: var(--bui-space-3);
+ }
+
+ .bui-ButtonIcon {
+ padding: 0;
+ }
+
+ .bui-MenuPopup {
+ box-sizing: border-box;
+ max-width: 21.25rem;
+ }
+
+ .bui-MenuSubmenuTrigger,
+ .bui-MenuItem {
+ height: auto;
+ min-height: 2rem;
+ }
+
+ .bui-Text {
+ font-family: var(--bui-font-text);
+ }
+
+ .bui-Heading {
+ font-family: var(--bui-font-title);
+ }
+
+ .bui-TableRow {
+ border: none;
+ border-radius: var(--bui-radius-4);
+ }
+
+ .bui-TableRow:hover td:first-child {
+ border-top-left-radius: var(--bui-radius-2);
+ border-bottom-left-radius: var(--bui-radius-2);
+ }
+
+ .bui-TableRow:hover td:last-child {
+ border-top-right-radius: var(--bui-radius-2);
+ border-bottom-right-radius: var(--bui-radius-2);
+ }
+
+ .bui-TableBody:before,
+ .bui-TableBody:after {
+ line-height: var(--bui-space-1);
+ content: '\200C';
+ display: block;
+ }
+
+ .bui-TableHeader .bui-TableRow {
+ border-bottom: 1px solid var(--bui-border);
+ }
+
+ .bui-TableHead {
+ font-size: var(--bui-font-size-2);
+ color: var(--bui-fg-secondary);
+ font-weight: var(--bui-font-weight-regular);
+ }
+
+ .bui-HeaderToolbar {
+ padding-top: var(--bui-space-2);
+ padding-inline: var(--bui-space-2);
+ }
+
+ .bui-HeaderToolbarWrapper {
+ border-radius: var(--bui-radius-3);
+ padding-inline: var(--bui-space-3);
+ border: none;
+ }
+
+ .bui-HeaderToolbarControls {
+ right: calc(var(--bui-space-3) - 1px);
+ }
+
+ .bui-HeaderTabsWrapper {
+ margin-top: var(--bui-space-2);
+ margin-inline: var(--bui-space-2);
+ border-radius: var(--bui-radius-3);
+ padding-inline: var(--bui-space-1);
+ border: none;
+ }
+
+ .bui-Input {
+ border-radius: var(--bui-radius-3);
+ }
+}
+
+[data-theme-mode='light'][data-theme-name='spotify'] {
+ --bui-bg: var(--bui-gray-1);
+ --bui-bg-surface-1: var(--bui-white);
+ --bui-bg-surface-2: var(--bui-gray-2);
+ --bui-bg-solid: #1ed760;
+ --bui-bg-solid-hover: #3be477;
+ --bui-bg-solid-pressed: #1abc54;
+ --bui-bg-solid-disabled: var(--bui-gray-2);
+
+ --bui-fg-primary: var(--bui-black);
+ --bui-fg-secondary: var(--bui-gray-7);
+ --bui-fg-solid: var(--bui-black);
+
+ --bui-border: var(--bui-gray-3);
+ --bui-border-hover: rgba(0, 0, 0, 0.3);
+ --bui-border-pressed: rgba(0, 0, 0, 0.5);
+ --bui-border-disabled: rgba(0, 0, 0, 0.1);
+ --bui-border-danger: #f87a7a;
+ --bui-border-warning: #e36d05;
+ --bui-border-success: #53db83;
+
+ --bui-ring: rgba(0, 0, 0, 0.2);
+
+ .bui-HeaderToolbarWrapper {
+ border: 1px solid var(--bui-border);
+ }
+
+ .bui-HeaderTabsWrapper {
+ border: 1px solid var(--bui-border);
+ }
+}
+
+[data-theme-mode='dark'][data-theme-name='spotify'] {
+ --bui-bg: var(--bui-black);
+ --bui-bg-surface-1: var(--bui-gray-1);
+ --bui-bg-surface-2: var(--bui-gray-2);
+ --bui-bg-solid: #1ed760;
+ --bui-bg-solid-hover: #3be477;
+ --bui-bg-solid-pressed: #1abc54;
+ --bui-bg-solid-disabled: #0f6c30;
+ --bui-bg-tint: #242424;
+ --bui-bg-tint-hover: #202020;
+ --bui-bg-tint-pressed: #292929;
+ --bui-bg-tint-disabled: rgba(255, 255, 255, 0.8);
+ --bui-bg-danger: #3b1219;
+ --bui-bg-warning: #302008;
+ --bui-bg-success: #132d21;
+
+ --bui-fg-primary: var(--bui-white);
+ --bui-fg-secondary: var(--bui-gray-7);
+ --bui-fg-link: var(--bui-white);
+ --bui-fg-link-hover: var(--bui-white);
+ --bui-fg-disabled: var(--bui-gray-5);
+ --bui-fg-solid: var(--bui-black);
+ --bui-fg-solid-disabled: #083618;
+ --bui-fg-tint: var(--bui-white);
+ --bui-fg-tint-disabled: var(--bui-gray-5);
+ --bui-fg-danger: #e22b2b;
+ --bui-fg-warning: #e36d05;
+ --bui-fg-success: #1db954;
+
+ --bui-border: var(--bui-gray-3);
+ --bui-border-hover: rgba(255, 255, 255, 0.4);
+ --bui-border-pressed: rgba(255, 255, 255, 0.5);
+ --bui-border-disabled: rgba(255, 255, 255, 0.2);
+ --bui-border-danger: #f87a7a;
+ --bui-border-warning: #e36d05;
+ --bui-border-success: #53db83;
+
+ --bui-ring: rgba(255, 255, 255, 0.2);
+}
diff --git a/ADOPTERS.md b/ADOPTERS.md
index e97c213adf..d20fd4a8b2 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -284,3 +284,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [Scalepoint](https://scalepoint.com) | [Yuriy Ostapenko](https://github.com/yuriyostapenko), [Dmytro Pasko](https://github.com/dimapasko), [Yuri Sedykh ](https://github.com/yuiri-sedykh), [Bartosz Wisniewski](https://github.com/Epgor) | Internal Developer Portal: Software Catalog with infrastructure resources and dependencies, Software Templates, TechDocs, Tech Radar, Kubernetes and Observability, as well as custom CI/CD components |
| [VR](https://www.vr.com.br) | [Felipe Gomes](https://www.linkedin.com/in/felipe-gomes-da-silva), [Tiago Garcia](https://www.linkedin.com/in/tiago-garcia-6301a925) | Internal portal for development squads, service catalog, documentation hub, and application mapping for the entire company ecosystem, simplifying cloud infrastructure construction through templates. |
| [Plata](https://platacard.mx/en) | [Shamil Ganiev](https://github.com/ganievs) | Internal Developer Portal for the whole engineering team |
+| [Syngenta Digital](https://www.syngentadigital.com) | [Bitan Mallick](https://www.linkedin.com/in/bitanmallick) | Internal developer portal, designed to empower developers and streamline workflows. We use software catalog, tech-radar, software templates, tech-docs and various custom plugins to ensure an efficient and collaborative development experience. |
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6a91fc4196..9413206197 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -388,7 +388,7 @@ Once you've submitted a Pull Request (PR) the various bots will come out and do
- adding labels to help make reviewing PRs easier
- checking for missing changesets or confirming them
- checking for commits for their DCO (Developer Certificate of Origin)
-- kick of the various CI builds
+- kick off the various CI builds
Once these steps are completed, it's just a matter of being patient. As the reviewers have time, they will begin reviewing your PR. When the review process begins, there may be a few layers to this, but the general rule is that you need approval from one of the core maintainers and one from the specific area impacted by your PR. You may also have someone from the community review your changes. This can really help speed things up as they may catch some early items making the review for the maintainers simpler. Once you have the two (2) approvals, it's ready to be merged, a task that is also performed by the maintainers.
diff --git a/LABELS.md b/LABELS.md
index 9ce65d0a71..f1af06d4fa 100644
--- a/LABELS.md
+++ b/LABELS.md
@@ -26,6 +26,7 @@ These labels indicate what is needed to move an issue forward before it can be a
- `needs:bep` - The issue is an advanced addition that needs a [Backstage Enhancement Proposal](./beps/README.md).
- `needs:direction` - The issue needs direction from the owners of the area.
+- `needs:discussion` - The way forward for this issue is unclear and it needs further discussion with the author and other participants.
- `needs:more-info` - The issue needs more information from the author.
- `needs:motivation` - It is not clear why this change is needed. The author should provide motivation for the change, for instance by giving examples of concrete use cases or scenarios.
- `needs:repro` - The issue cannot be reproduced by the owners of the area. The author should provide more information to help them reproduce the issue, if possible with a minimal reproduction repository.
@@ -39,19 +40,21 @@ These labels indicate which part of Backstage an issue or pull request relates t
- `area:auditor` - Auditor service and it's use in plugins.
- `area:auth` - Authentication and 3rd party authorization.
- `area:catalog` - The Catalog plugin and the Software Catalog model and integrations.
-- `area:core` - The core Backstage framework.
-- `area:design-system` - The Canon design system and library.
+- `area:design-system` - The Backstage UI design system and library.
- `area:documentation` - Documentation for adopters, users, and developers.
- `area:events` - The Events system and integrations for other plugins.
+- `area:framework` - The core Backstage framework.
- `area:home` - The Home plugin and the main page of the Backstage site.
- `area:kubernetes` - The Kubernetes plugin and integrations for other plugins.
- `area:microsite` - The microsite at [backstage.io](https://backstage.io), excluding the documentation.
- `area:notifications` - The Notifications plugin and integrations for other plugins.
- `area:openapi-tooling` - The OpenAPI tooling it's use in plugins.
+- `area:operations` - The management and operations of the main Backstage repository.
- `area:permission` - The Permissions system and permission integrations from other plugins.
- `area:scaffolder` - The Scaffolder plugin that powers Software Templates.
- `area:search` - The Search plugin and search integrations for other plugins.
- `area:techdocs` - The TechDocs plugin.
+- `area:tooling` - The Backstage CLI and repository tooling.
## Integration Labels - `integration:*`
@@ -79,11 +82,17 @@ These labels indicate that an issue is related to specific domains of expertise.
- `domain:tooling` - Tooling and automation in Node.js and GitHub Actions.
- `domain:web` - Frontend development using TypeScript and React.
+## Workflow Labels
+
+These labels indicate a workflow status for the owners.
+
+- `workflow:do-not-merge` - The Pull Request should not be merged.
+- `workflow:before-release` - Should be handled before the next main-line release.
+- `workflow:after-release` - Should be handled after the next main-line release.
+- `workflow:after-vacations` - To be handled once the owners return from vacation.
+
## General Labels
-- `after vacations` - To be handled once the owners return from vacation.
-- `do not merge` - The pull request should not be merged.
-- `fix before release` - Should be handled before the next release.
- `good first issue` - Good for new contributors.
- `stale` - The issue or pull request has not seen any activity for a while and will be closed if no further activity is seen.
- `no stale` - The issue or pull request should not be closed due to inactivity.
diff --git a/OWNERS.md b/OWNERS.md
index c07b803e74..d4ee3c6400 100644
--- a/OWNERS.md
+++ b/OWNERS.md
@@ -15,6 +15,21 @@ Team: @backstage/maintainers
These are the separate project areas of Backstage, each with their own project area maintainers
+### Auth
+
+Team: @backstage/auth-maintainers
+
+Scope: The Backstage auth plugin and modules, as well as client-side implementations.
+
+| Name | Organization | Team | GitHub | Discord |
+| -------------------- | ------------ | ------------- | ----------------------------------------------- | --------------- |
+| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` |
+| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` |
+| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` |
+| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` |
+| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` |
+| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
+
### Catalog
Team: @backstage/catalog-maintainers
@@ -41,17 +56,44 @@ Scope: The Backstage design system, component library, as well as surrounding to
| Charles de Dreuille | Spotify | | [cdedreuille](https://github.com/cdedreuille) | `cdedreuille` |
| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip` |
+### Documentation
+
+Team: @backstage/documentation-maintainers
+
+Scope: The Backstage Documentation and Microsite, excluding the plugins listing
+
+| Name | Organization | GitHub | Discord |
+| --------------- | ------------- | ----------------------------------------------------- | ------------- |
+| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` |
+| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` |
+| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
+
+### Framework
+
+Team: @backstage/framework-maintainers
+
+Scope: The Backstage core framework, including all revisions of the frontend and backend systems, as well as the App plugin.
+
+| Name | Organization | Team | GitHub | Discord |
+| -------------------- | ------------ | ------------- | ----------------------------------------------- | --------------- |
+| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` |
+| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` |
+| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` |
+| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` |
+| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` |
+| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
+
### Helm Charts
Team: @backstage/helm-chart-maintainers
Scope: The Backstage [Helm Chart(s)](https://github.com/backstage/charts).
-| Name | Organization | Team | GitHub | Discord |
-| -------------------- | ------------ | ---- | ---------------------------------------- | -------------- |
-| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | sabre1041#2622 |
-| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | Tumi#4346 |
-| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | vinzscam#6944 |
+| Name | Organization | Team | GitHub | Discord |
+| -------------------- | ------------ | ---- | ---------------------------------------- | ---------------- |
+| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | `sabre1041#2622` |
+| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | `Tumi#4346` |
+| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
### Home
@@ -59,12 +101,14 @@ Team: @backstage/home-maintainers
Scope: The Backstage home page and information architecture
-| Name | Organization | Team | GitHub | Discord |
-| ------------------------ | ------------ | -------------- | ---------------------------------------- | ----------------- |
-| Avantika Iyer | Spotify | Infinite Buck$ | [tikabom](http://github.com/tikabom) | - |
-| Emma Indal | Spotify | Infinite Buck$ | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 |
-| Djamaile Rahamat | Spotify | Infinite Buck$ | [djamaile](http://github.com/djamaile) | dyoqi |
-| Raghunandan Balachandran | Spotify | Infinite Buck$ | [soapraj](http://github.com/soapraj) | raghunandanb#1114 |
+| Name | Organization | Team | GitHub | Discord |
+| ------------------ | ------------ | --------------- | ----------------------------------------- | ------- |
+| Ainhoa Larumbe | Spotify | Imaginary Goats | [ainhoaL](http://github.com/ainhoaL) | - |
+| Avantika Iyer | Spotify | Imaginary Goats | [tikabom](http://github.com/tikabom) | - |
+| Daniel Jelčić | Spotify | Imaginary Goats | [djelcic](http://github.com/danieljelcic) | - |
+| Eric Peterson | Spotify | Imaginary Goats | [iamEAP](http://github.com/iamEAP) | - |
+| Musaab Elfaqih | Spotify | Imaginary Goats | [TheSabby](http://github.com/TheSabby) | - |
+| Landry Zinda-Snead | Spotify | Imaginary Goats | [landryzs](http://github.com/landryzs) | - |
### Kubernetes
@@ -76,6 +120,21 @@ Scope: The Kubernetes plugin and the base it provides for other plugins to build
| -------------- | ------------ | ---- | ---------------------------------------- | ------------ |
| Matthew Clarke | Spotify | | [mclarke47](http://github.com/mclarke47) | mclarke#0725 |
+### Operations
+
+Team: @backstage/operations-maintainers
+
+Scope: The management and operation of the main Backstage repository and release process, along with the surrounding tooling.
+
+| Name | Organization | Team | GitHub | Discord |
+| -------------------- | ------------ | ------------- | ----------------------------------------------- | --------------- |
+| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` |
+| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` |
+| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` |
+| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` |
+| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` |
+| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
+
### Permission Framework
Team: @backstage/permission-maintainers
@@ -117,6 +176,22 @@ Scope: The TechDocs plugin and related tooling
| John Philip | Spotify | ProTean | [johnphilip283](https://github.com/johnphilip283) | `john_philip#2399` |
| Sydney Achinger | Spotify | ProTean | [squid-ney](https://github.com/squid-ney) | - |
+### Tooling
+
+Team: @backstage/tooling-maintainers
+
+Scope: All published Backstage CLI tools in the main `backstage` repository that do not belong to other areas, including `@backstage/cli` and `@backstage/repo-tools`.
+
+| Name | Organization | Team | GitHub | Discord |
+| -------------------- | ------------ | ------------- | ----------------------------------------------------- | --------------- |
+| Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip#0019` |
+| Ben Lambert | Spotify | Cubic Belugas | [benjdlambert](https://github.com/benjdlambert) | `blam#2159` |
+| Camila Loiola | Spotify | Cubic Belugas | [camilaibs](http://github.com/camilaibs) | `camilal#0226` |
+| Fredrik Adelöw | Spotify | Cubic Belugas | [freben](https://github.com/freben) | `freben#3926` |
+| Mihai Tabara | Spotify | Cubic Belugas | [MihaiTabara](http://github.com/MihaiTabara) | `mihait#3107` |
+| Vincenzo Scamporlino | Spotify | Cubic Belugas | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` |
+| Aramis Sennyey | DoorDash | | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` |
+
## Incubating Project Areas
These incubating project areas have shared ownership with @backstage/maintainers.
@@ -145,18 +220,6 @@ Scope: Tooling and Community Repo Maintainers for the Backstage [Community Plugi
| Vincenzo Scamporlino | Spotify | [vinzscam](https://github.com/vinzscam) | `vinzscam` |
| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
-### Documentation
-
-Team: @backstage/documentation-maintainers
-
-Scope: The Backstage Documentation and Microsite, excluding the plugins listing
-
-| Name | Organization | GitHub | Discord |
-| --------------- | ------------- | ----------------------------------------------------- | ------------- |
-| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` |
-| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` |
-| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` |
-
### Events
Team: @backstage/events-maintainers
diff --git a/app-config.yaml b/app-config.yaml
index 89e417fad3..60842ee61a 100644
--- a/app-config.yaml
+++ b/app-config.yaml
@@ -1,8 +1,7 @@
app:
title: Backstage Example App
baseUrl: http://localhost:3000
- experimental:
- packages: all # ✨
+ packages: all # ✨
#datadogRum:
# clientToken: '123456789'
@@ -36,6 +35,12 @@ backend:
# keys:
# - secret: ${BACKEND_SECRET}
+ # Used for testing rate limiting locally
+ # rateLimit:
+ # windowMs: 1m
+ # incomingRequestLimit: 1
+ # ipAllowList: []
+
auth:
# TODO: once plugins have been migrated we can remove this, but right now it
# is require for the backend-next to work in this repo
@@ -64,83 +69,11 @@ backend:
# See README.md in the proxy-backend plugin for information on the configuration format
proxy:
endpoints:
- '/circleci/api':
- target: https://circleci.com/api/v1.1
- headers:
- Circle-Token: ${CIRCLECI_AUTH_TOKEN}
-
- '/jenkins/api':
- target: http://localhost:8080
- headers:
- Authorization: ${JENKINS_BASIC_AUTH_HEADER}
-
- '/travisci/api':
- target: https://api.travis-ci.com
- changeOrigin: true
- headers:
- Authorization: ${TRAVISCI_AUTH_TOKEN}
- travis-api-version: '3'
-
- '/newrelic/apm/api':
- target: https://api.newrelic.com/v2
- headers:
- X-Api-Key: ${NEW_RELIC_REST_API_KEY}
- allowedHeaders:
- - link
-
- '/newrelic/api':
- target: https://api.newrelic.com
- headers:
- X-Api-Key: ${NEW_RELIC_USER_KEY}
-
'/pagerduty':
target: https://api.pagerduty.com
headers:
Authorization: Token token=${PAGERDUTY_TOKEN}
- '/buildkite/api':
- target: https://api.buildkite.com/v2/
- headers:
- Authorization: ${BUILDKITE_TOKEN}
-
- '/sentry/api':
- target: https://sentry.io/api/
- allowedMethods: ['GET']
- headers:
- Authorization: ${SENTRY_TOKEN}
-
- '/ilert':
- target: https://api.ilert.com
- allowedMethods: ['GET', 'POST', 'PUT']
- allowedHeaders: ['Authorization']
- headers:
- Authorization: ${ILERT_AUTH_HEADER}
-
- '/airflow':
- target: https://your.airflow.instance.com/api/v1
- headers:
- Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
-
- '/gocd':
- target: https://your.gocd.instance.com/go/api
- allowedMethods: ['GET']
- allowedHeaders: ['Authorization']
- headers:
- Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
-
- '/dynatrace':
- target: https://your.dynatrace.instance.com/api/v2
- headers:
- Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
-
- '/stackstorm':
- target: https://your.stackstorm.instance.com/api
- headers:
- St2-Api-Key: ${ST2_API_KEY}
-
- '/puppetdb':
- target: https://your.puppetdb.instance.com
-
organization:
name: My Company
@@ -157,46 +90,6 @@ techdocs:
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3' or 'azureBlobStorage' or 'openStackSwift'. Read documentation for using alternatives.
-dynatrace:
- baseUrl: https://your.dynatrace.instance.com
-
-nomad:
- addr: 0.0.0.0
-
-# Score-cards sample configuration.
-scorecards:
- jsonDataUrl: https://raw.githubusercontent.com/Oriflame/backstage-plugins/main/plugins/score-card/sample-data/
- wikiLinkTemplate: https://link-to-wiki/{id}
-
-sentry:
- organization: my-company
-
-rollbar:
- organization: my-company
- # NOTE: The rollbar-backend & accountToken key may be deprecated in the future (replaced by a proxy config)
- accountToken: my-rollbar-account-token
-
-lighthouse:
- baseUrl: http://localhost:3003
-
-kubernetes:
- serviceLocatorMethod:
- type: 'multiTenant'
- clusterLocatorMethods:
- - type: 'config'
- clusters: []
-
-kafka:
- clientId: backstage
- clusters:
- - name: cluster
- dashboardUrl: https://akhq.io/
- brokers:
- - localhost:9092
-
-allure:
- baseUrl: http://localhost:5050/allure-docker-service
-
integrations:
github:
- host: github.com
@@ -244,7 +137,6 @@ integrations:
secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
catalog:
- useUrlReadersSearch: true
import:
entityFilename: catalog-info.yaml
pullRequestBranchName: backstage-integration
@@ -269,26 +161,6 @@ catalog:
plugins:
- catalog
- search
-
- processors:
- ldapOrg:
- ### Example for how to add your enterprise LDAP server
- # providers:
- # - target: ldaps://ds.example.net
- # bind:
- # dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
- # secret: ${LDAP_SECRET}
- # users:
- # dn: ou=people,ou=example,dc=example,dc=net
- # options:
- # filter: (uid=*)
- # map:
- # description: l
- # groups:
- # dn: ou=access,ou=groups,ou=example,dc=example,dc=net
- # options:
- # filter: (&(objectClass=some-group-class)(!(groupType=email)))
-
locations:
# Add a location here to ingest it, for example from a URL:
#
@@ -325,13 +197,16 @@ catalog:
target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml
rules:
- allow: [Template]
+
scaffolder:
+ auditor:
+ taskParameterMaxLength: 256
# Use to customize default commit author info used when new components are created
- # defaultAuthor:
- # name: Scaffolder
- # email: scaffolder@backstage.io
+ defaultAuthor:
+ name: Scaffolder
+ email: scaffolder@backstage.io
# Use to customize the default commit message when new components are created
- # defaultCommitMessage: 'Initial commit'
+ defaultCommitMessage: 'Initial commit'
auth:
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
@@ -422,80 +297,5 @@ auth:
myproxy: {}
guest: {}
-costInsights:
- engineerCost: 200000
- engineerThreshold: 0.5
- products:
- computeEngine:
- name: Compute Engine
- icon: compute
- cloudDataflow:
- name: Cloud Dataflow
- icon: data
- cloudStorage:
- name: Cloud Storage
- icon: storage
- bigQuery:
- name: BigQuery
- icon: search
- events:
- name: Events
- icon: data
- metrics:
- DAU:
- name: Daily Active Users
- default: true
- MSC:
- name: Monthly Subscribers
- currencies:
- engineers:
- label: 'Engineers 🛠'
- unit: 'engineer'
- usd:
- label: 'US Dollars 💵'
- kind: 'USD'
- unit: 'dollar'
- prefix: '$'
- rate: 1
- carbonOffsetTons:
- label: 'Carbon Offset Tons ♻️⚖️s'
- kind: 'CARBON_OFFSET_TONS'
- unit: 'carbon offset ton'
- rate: 3.5
- beers:
- label: 'Beers 🍺'
- kind: 'BEERS'
- unit: 'beer'
- rate: 4.5
- pintsIceCream:
- label: 'Pints of Ice Cream 🍦'
- kind: 'PINTS_OF_ICE_CREAM'
- unit: 'ice cream pint'
- rate: 5.5
-
-pagerDuty:
- eventsBaseUrl: 'https://events.pagerduty.com/v2'
-
-jenkins:
- instances:
- - name: default
- baseUrl: https://jenkins.example.com
- username: backstage-bot
- apiKey: 123456789abcdef0123456789abcedf012
-
-azureDevOps:
- host: dev.azure.com
- token: my-token
- organization: my-company
-
-apacheAirflow:
- baseUrl: https://your.airflow.instance.com
-
-gocd:
- baseUrl: https://your.gocd.instance.com
-
-stackstorm:
- webUrl: https://your.stackstorm.webui.instance.com
-
permission:
enabled: true
diff --git a/canon-docs/package.json b/canon-docs/package.json
deleted file mode 100644
index 5a4affc45b..0000000000
--- a/canon-docs/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "name": "canon-docs",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "build": "npm run build:css && next build",
- "build:css": "node scripts/build-css.js",
- "lint": "next lint",
- "start": "npm run build:css && next dev"
- },
- "dependencies": {
- "@codemirror/lang-sass": "^6.0.2",
- "@lezer/highlight": "^1.2.1",
- "@mdx-js/loader": "^3.1.0",
- "@mdx-js/react": "^3.1.0",
- "@next/mdx": "^15.1.4",
- "@storybook/react": "^8.6.8",
- "@uiw/codemirror-themes": "^4.23.7",
- "@uiw/react-codemirror": "^4.23.7",
- "motion": "^12.4.1",
- "next": "14.2.26",
- "react": "^18.0.2",
- "react-dom": "^18.0.2",
- "react-frame-component": "^5.2.7",
- "shiki": "^1.26.1",
- "storybook": "^8.6.8"
- },
- "devDependencies": {
- "@types/mdx": "^2.0.13",
- "@types/node": "^20",
- "@types/react": "^18.0.0",
- "@types/react-dom": "^18.0.0",
- "eslint": "^8",
- "eslint-config-next": "14.2.23",
- "lightningcss": "^1.28.2",
- "typescript": "^5"
- }
-}
diff --git a/canon-docs/public/CNAME b/canon-docs/public/CNAME
deleted file mode 100644
index 01f6d196cc..0000000000
--- a/canon-docs/public/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-canon.backstage.io
\ No newline at end of file
diff --git a/canon-docs/public/css-classname-structure.png b/canon-docs/public/css-classname-structure.png
deleted file mode 100644
index df9894ff2b..0000000000
Binary files a/canon-docs/public/css-classname-structure.png and /dev/null differ
diff --git a/canon-docs/scripts/build-css.js b/canon-docs/scripts/build-css.js
deleted file mode 100644
index dd9775150f..0000000000
--- a/canon-docs/scripts/build-css.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-const { bundle } = require('lightningcss');
-
-const source = '../../packages/canon/src/css';
-const destination = '../public';
-
-const source1 = path.join(__dirname, `${source}/core.css`);
-const destination1 = path.join(__dirname, `${destination}/core.css`);
-const source2 = path.join(__dirname, `${source}/components.css`);
-const destination2 = path.join(__dirname, `${destination}/components.css`);
-
-// Function to bundle and copy the CSS file
-const bundleAndCopyFile = async (source, destination) => {
- try {
- const result = await bundle({
- filename: source,
- minify: true,
- });
-
- fs.writeFileSync(destination, result.code);
- console.log('File bundled and copied successfully!');
- } catch (err) {
- console.error('Error bundling file:', err);
- }
-};
-
-// Initial bundle and copy
-Promise.all([
- bundleAndCopyFile(source1, destination1),
- bundleAndCopyFile(source2, destination2),
-])
- .then(() => {
- // Add an empty line after all operations are complete - It looks better in the terminal :)
- console.log('');
- })
- .catch(err => {
- console.error('Error in processing files:', err);
- });
diff --git a/canon-docs/src/app/(docs)/components/avatar/page.mdx b/canon-docs/src/app/(docs)/components/avatar/page.mdx
deleted file mode 100644
index b46caf8d62..0000000000
--- a/canon-docs/src/app/(docs)/components/avatar/page.mdx
+++ /dev/null
@@ -1,75 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { AvatarSnippet } from '@/snippets/stories-snippets';
-import { avatarPropDefs } from './props';
-
-# Avatar
-
-An avatar component with a fallback for initials.
-
-}
- code={``}
-/>
-
-
-
- Usage
- Theming
-
-
- `}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- - `canon-AvatarRoot`
- - `canon-AvatarRoot[data-size='small']`
- - `canon-AvatarRoot[data-size='medium']`
- - `canon-AvatarRoot[data-size='large']`
- - `canon-AvatarImage`
- - `canon-AvatarFallback`
-
-
-
-## API reference
-
-
-
-## Examples
-
-### Sizes
-
-Avatar sizes can be set using the `size` prop.
-
-}
- code={`
-
-
-
- `}
-/>
-
-### Fallback
-
-If the image is not available, the avatar will show the initials of the name.
-
-}
- code={``}
-/>
diff --git a/canon-docs/src/app/(docs)/components/avatar/props.ts b/canon-docs/src/app/(docs)/components/avatar/props.ts
deleted file mode 100644
index e86c67a41e..0000000000
--- a/canon-docs/src/app/(docs)/components/avatar/props.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs';
-import type { PropDef } from '@/utils/propDefs';
-
-export const avatarPropDefs: Record = {
- src: {
- type: 'string',
- },
- name: {
- type: 'string',
- },
- size: {
- type: 'enum',
- values: ['small', 'medium', 'large'],
- default: 'medium',
- responsive: true,
- },
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/box/props.ts b/canon-docs/src/app/(docs)/components/box/props.ts
deleted file mode 100644
index f3e38984dd..0000000000
--- a/canon-docs/src/app/(docs)/components/box/props.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import {
- classNamePropDefs,
- displayPropDefs,
- heightPropDefs,
- positionPropDefs,
- stylePropDefs,
- widthPropDefs,
-} from '../../../../utils/propDefs';
-import type { PropDef } from '../../../../utils/propDefs';
-
-export const boxPropDefs: Record = {
- as: {
- type: 'enum',
- values: ['div', 'span'],
- default: 'div',
- responsive: true,
- },
- ...widthPropDefs,
- ...heightPropDefs,
- ...positionPropDefs,
- ...displayPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx
deleted file mode 100644
index e1ecee8920..0000000000
--- a/canon-docs/src/app/(docs)/components/button/page.mdx
+++ /dev/null
@@ -1,136 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { ButtonSnippet } from '@/snippets/stories-snippets';
-import { buttonVariants } from '@/snippets/code-snippets';
-import { buttonPropDefs } from './props';
-
-# Button
-
-A button component that can be used to trigger actions.
-
-}
- code={`
-
-
-
-`}
-/>
-
-
-
- Usage
- Theming
-
-
-
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `}
- />
-
-
-
-
-## API reference
-
-
-
-## Examples
-
-### Variants
-
-Here's a view when buttons have different variants.
-
-}
- code={buttonVariants}
-/>
-
-### Sizes
-
-Here's a view when buttons have different sizes.
-
-}
- code={`
-
-
-`}
-/>
-
-### With Icons
-
-Here's a view when buttons have icons.
-
-}
- code={`
-
-
-
-`}
-/>
-
-### Full width
-
-Here's a view when buttons are full width.
-
-}
- code={`
-
-`}
-/>
-
-### Disabled
-
-Here's a view when buttons are disabled.
-
-}
- code={``}
-/>
-
-### Responsive
-
-Here's a view when buttons are responsive.
-
-
- Responsive Button
- `}
-/>
diff --git a/canon-docs/src/app/(docs)/components/button/props.ts b/canon-docs/src/app/(docs)/components/button/props.ts
deleted file mode 100644
index 813dcaa6f0..0000000000
--- a/canon-docs/src/app/(docs)/components/button/props.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
-import type { PropDef } from '../../../../utils/propDefs';
-
-export const buttonPropDefs: Record = {
- variant: {
- type: 'enum',
- values: ['primary', 'secondary'],
- default: 'primary',
- responsive: true,
- },
- size: {
- type: 'enum',
- values: ['small', 'medium'],
- default: 'medium',
- responsive: true,
- },
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/checkbox/page.mdx b/canon-docs/src/app/(docs)/components/checkbox/page.mdx
deleted file mode 100644
index 413636dc9a..0000000000
--- a/canon-docs/src/app/(docs)/components/checkbox/page.mdx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { CheckboxSnippet } from '@/snippets/stories-snippets';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
-import { checkboxPropDefs } from './props';
-
-# Checkbox
-
-A checkbox component that can be used to trigger actions.
-
-}
- code={``}
-/>
-
-
-
- Usage
- Theming
-
-
-
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `}
- />
-
-
-
-
-## API reference
-
-
-
-
-
-## Examples
-
-### All variants
-
-Here's a view when checkboxes have different variants.
-
-}
- code={`
-
-
-
-
- `}
-/>
diff --git a/canon-docs/src/app/(docs)/components/collapsible/page.mdx b/canon-docs/src/app/(docs)/components/collapsible/page.mdx
deleted file mode 100644
index e013dff89c..0000000000
--- a/canon-docs/src/app/(docs)/components/collapsible/page.mdx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { CollapsibleSnippet } from '@/snippets/stories-snippets';
-import {
- collapsibleRootPropDefs,
- collapsibleTriggerPropDefs,
- collapsiblePanelPropDefs,
-} from './props';
-
-# Collapsible
-
-An avatar component with a fallback for initials.
-
-}
- code={`
- (
-
- )} />
-
-
- It's the edge of the world and all of Western civilization
- The sun may rise in the East, at least it settled in a final location
- It's understood that Hollywood sells Californication
-
-
-`}
-/>
-
-
-
- Usage
- Theming
-
-
-
- (
-
- )} />
- Your content
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- - `canon-CollapsibleRoot`
- - `canon-CollapsibleTrigger`
- - `canon-CollapsiblePanel`
-
-
-
-## API reference
-
-### Collapsible.Root
-
-Groups all parts of the collapsible. Renders a `
` element.
-
-
-
-### Collapsible.Trigger
-
-The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend
-using the `render` prop to render a custom trigger.
-
- } />`}
-/>
-
-
-
-### Collapsible.Panel
-
-A panel with the collapsible contents. Renders a `
` element.
-
-
-
-## Examples
-
-Open the panel by default by setting the `defaultOpen` prop to `true`.
-
-}
- code={`
- (
-
- )} />
-
-
- It's the edge of the world and all of Western civilization
- The sun may rise in the East, at least it settled in a final location
- It's understood that Hollywood sells Californication
-
-
-`}
-/>
diff --git a/canon-docs/src/app/(docs)/components/collapsible/props.ts b/canon-docs/src/app/(docs)/components/collapsible/props.ts
deleted file mode 100644
index 02c62dc89e..0000000000
--- a/canon-docs/src/app/(docs)/components/collapsible/props.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import {
- classNamePropDefs,
- stylePropDefs,
- renderPropDefs,
-} from '@/utils/propDefs';
-import type { PropDef } from '@/utils/propDefs';
-
-export const collapsibleRootPropDefs: Record = {
- defaultOpen: {
- type: 'boolean',
- default: 'false',
- },
- open: {
- type: 'boolean',
- },
- onOpenChange: {
- type: 'enum',
- values: ['(open) => void'],
- },
- ...renderPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
-
-export const collapsibleTriggerPropDefs: Record = {
- ...renderPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
-
-export const collapsiblePanelPropDefs: Record = {
- hiddenUntilFound: {
- type: 'boolean',
- default: 'false',
- },
- keepMounted: {
- type: 'boolean',
- default: 'false',
- },
- ...renderPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/container/page.mdx b/canon-docs/src/app/(docs)/components/container/page.mdx
deleted file mode 100644
index 40f0321624..0000000000
--- a/canon-docs/src/app/(docs)/components/container/page.mdx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { CodeBlock } from '@/components/CodeBlock';
-import { PropsTable } from '@/components/PropsTable';
-import { Tabs } from '@/components/Tabs';
-import { Snippet } from '@/components/Snippet';
-import { ContainerSnippet } from '@/snippets/stories-snippets';
-import { containerPropDefs } from './props';
-
-# Container
-
-The container component let you use our default max-width and center the
-content on the page.
-
-}
- code={`
-
-`}
-/>
-
-
-
- Usage
-
-
- Hello World!
-`} />
-
-
-
-## API reference
-
-
-
-## Examples
-
-### Simple
-
-A simple example of how to use the Container component.
-
-
- Hello World
- Hello World
- Hello World
-`}
-/>
-
-### Responsive padding & margin
-
-The Container component also supports responsive values, making it easy to
-create responsive designs.
-
-
- Hello World
- Hello World
- Hello World
-`}
-/>
diff --git a/canon-docs/src/app/(docs)/components/container/props.ts b/canon-docs/src/app/(docs)/components/container/props.ts
deleted file mode 100644
index 4a3410ec12..0000000000
--- a/canon-docs/src/app/(docs)/components/container/props.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import {
- classNamePropDefs,
- stylePropDefs,
- gapPropDefs,
-} from '../../../../utils/propDefs';
-import type { PropDef } from '../../../../utils/propDefs';
-
-export const containerPropDefs: Record = {
- ...gapPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/flex/page.mdx b/canon-docs/src/app/(docs)/components/flex/page.mdx
deleted file mode 100644
index 8150f3e3c5..0000000000
--- a/canon-docs/src/app/(docs)/components/flex/page.mdx
+++ /dev/null
@@ -1,83 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import {
- flexFAQ1,
- flexSimple,
- flexResponsive,
- flexAlign,
-} from '@/snippets/code-snippets';
-import { Snippet } from '@/components/Snippet';
-import { FlexSnippet } from '@/snippets/stories-snippets';
-import { flexPropDefs } from './props';
-import { spacingPropDefs } from '../../../../utils/propDefs';
-
-# Flex
-
-This is the flex container component. It will help to define the number of
-columns that will be used in the grid. You can also define the gap between the
-columns. All values are responsive.
-
-}
- code={`
-
-
-
-`}
-/>
-
-
-
- Usage
-
-
-
-`}
- />
-
-
-
-## API reference
-
-
-
-The grid component also accepts all the spacing props from the Box component.
-
-
-
-## Common questions
-
-### Can I stack horizontally?
-
-The Flex component only allows for stacking elements vertically. If you want
-to create a column layout, please use the Grid component.
-
-
-
-## Examples
-
-### Simple
-
-A simple example of how to use the Flex component.
-
-
-
-### Responsive
-
-The Flex component also supports responsive values, making it easy to create
-responsive designs.
-
-
-
-### Align
-
-The Flex component also supports responsive alignment, making it easy to
-create responsive designs.
-
-
diff --git a/canon-docs/src/app/(docs)/components/flex/props.ts b/canon-docs/src/app/(docs)/components/flex/props.ts
deleted file mode 100644
index 2268a6909d..0000000000
--- a/canon-docs/src/app/(docs)/components/flex/props.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import {
- PropDef,
- childrenPropDefs,
- classNamePropDefs,
- stylePropDefs,
-} from '../../../../utils/propDefs';
-
-export const flexPropDefs: Record = {
- align: {
- type: 'enum',
- values: ['start', 'center', 'end', 'baseline', 'stretch'],
- responsive: true,
- },
- direction: {
- type: 'enum',
- values: ['row', 'column', 'row-reverse', 'column-reverse'],
- responsive: true,
- },
- justify: {
- type: 'enum',
- values: ['start', 'center', 'end', 'between'],
- responsive: true,
- },
- ...childrenPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/grid/props.ts b/canon-docs/src/app/(docs)/components/grid/props.ts
deleted file mode 100644
index a9e8717fa1..0000000000
--- a/canon-docs/src/app/(docs)/components/grid/props.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import {
- PropDef,
- childrenPropDefs,
- classNamePropDefs,
- stylePropDefs,
-} from '../../../../utils/propDefs';
-
-const columnsValues = [
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '10',
- '11',
- '12',
-];
-
-export const gridPropDefs: Record = {
- columns: {
- type: 'enum | string',
- values: [...columnsValues, 'auto'],
- responsive: true,
- default: 'auto',
- },
- ...childrenPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
-
-export const gridItemPropDefs: Record = {
- colSpan: {
- type: 'enum | string',
- values: [...columnsValues, 'full'],
- responsive: true,
- },
- rowSpan: {
- type: 'enum | string',
- values: [...columnsValues, 'full'],
- responsive: true,
- },
- start: {
- type: 'enum | string',
- values: [...columnsValues, 'auto'],
- responsive: true,
- },
- end: {
- type: 'enum | string',
- values: [...columnsValues, 'auto'],
- responsive: true,
- },
- ...childrenPropDefs,
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/heading/page.mdx b/canon-docs/src/app/(docs)/components/heading/page.mdx
deleted file mode 100644
index 10fd60bef1..0000000000
--- a/canon-docs/src/app/(docs)/components/heading/page.mdx
+++ /dev/null
@@ -1,74 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { HeadingSnippet } from '@/snippets/stories-snippets';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { headingPropDefs } from './props';
-
-# Heading
-
-Headings are used to structure the content of your page.
-
-}
- code={`Hello World!`}
-/>
-
-
-
- Usage
- Theming
-
-
-
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `}
- />
-
-
-
-
-## API reference
-
-
-
-## Examples
-
-### All variants
-
-The `Heading` component has a `variant` prop that can be used to change the
-appearance of the heading.
-
-}
- code={`
- Display
- Title 1
- Title 2
- Title 3
- Title 4
-`}
-/>
-
-### Responsive
-
-You can also use the `variant` prop to change the appearance of the text based
-on the screen size.
-
-
- Responsive heading
- `}
-/>
diff --git a/canon-docs/src/app/(docs)/components/heading/props.ts b/canon-docs/src/app/(docs)/components/heading/props.ts
deleted file mode 100644
index a3dd3288ff..0000000000
--- a/canon-docs/src/app/(docs)/components/heading/props.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
-import type { PropDef } from '../../../../utils/propDefs';
-
-export const headingPropDefs: Record = {
- variant: {
- type: 'enum',
- values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'],
- responsive: true,
- },
- children: {
- type: 'enum',
- values: ['ReactNode'],
- responsive: false,
- },
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/icon-button/page.mdx b/canon-docs/src/app/(docs)/components/icon-button/page.mdx
deleted file mode 100644
index 60530ec9ea..0000000000
--- a/canon-docs/src/app/(docs)/components/icon-button/page.mdx
+++ /dev/null
@@ -1,97 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { IconButtonSnippet } from '@/snippets/stories-snippets';
-import { iconButtonVariants } from '@/snippets/code-snippets';
-import { iconButtonPropDefs } from './props';
-
-# Icon Button
-
-A button component with a single icon that can be used to trigger actions.
-
-}
- code={`
-
-
- `}
-/>
-
-
-
- Usage
- Theming
-
-
-
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `}
- />
-
-
-
-
-## API reference
-
-
-
-## Examples
-
-### Variants
-
-Here's a view when buttons have different variants.
-
-}
- code={iconButtonVariants}
-/>
-
-### Sizes
-
-Here's a view when buttons have different sizes.
-
-}
- code={`
-
-
-`}
-/>
-
-### Disabled
-
-Here's a view when buttons are disabled.
-
-}
- code={``}
-/>
-
-### Responsive
-
-Here's a view when buttons are responsive.
-
-`}
-/>
diff --git a/canon-docs/src/app/(docs)/components/icon-button/props.ts b/canon-docs/src/app/(docs)/components/icon-button/props.ts
deleted file mode 100644
index bcb1580247..0000000000
--- a/canon-docs/src/app/(docs)/components/icon-button/props.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs';
-import type { PropDef } from '../../../../utils/propDefs';
-
-export const iconButtonPropDefs: Record = {
- variant: {
- type: 'enum',
- values: ['primary', 'secondary'],
- default: 'primary',
- responsive: true,
- },
- size: {
- type: 'enum',
- values: ['small', 'medium'],
- default: 'medium',
- responsive: true,
- },
- icon: { type: 'enum', values: 'icon', responsive: false },
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/icon/page.mdx b/canon-docs/src/app/(docs)/components/icon/page.mdx
deleted file mode 100644
index 66be460d13..0000000000
--- a/canon-docs/src/app/(docs)/components/icon/page.mdx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { IconSnippet } from '@/snippets/stories-snippets';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { iconPropDefs } from './props';
-
-# Icon
-
-Icons are used to represent an action or a state.
-
-}
- code={``}
-/>
-
-
-
- Usage
- Theming
-
-
-
-`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- `}
- />
-
-
-
-
-## API reference
-
-
diff --git a/canon-docs/src/app/(docs)/components/link/page.mdx b/canon-docs/src/app/(docs)/components/link/page.mdx
deleted file mode 100644
index 64a3261590..0000000000
--- a/canon-docs/src/app/(docs)/components/link/page.mdx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import {
- MenuSnippet,
- ButtonSnippet,
- LinkSnippet,
-} from '@/snippets/stories-snippets';
-import { linkPropDefs } from './props';
-
-# Link
-
-A link component that renders a `` element.
-
-}
- code={`Sign up for Backstage`}
-/>
-
-
-
- Usage
- Theming
-
-
- Sign up for Backstage`}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- - `canon-Link`
- - `canon-Link[data-variant='body']`
- - `canon-Link[data-variant='subtitle']`
- - `canon-Link[data-variant='caption']`
- - `canon-Link[data-variant='label']`
- - `canon-Link[data-weight='regular']`
- - `canon-Link[data-weight='bold']`
-
-
-
-## API reference
-
-
-
-## Examples
-
-### Variants
-
-Here's a view when links have different variants.
-
-}
- code={`
-
-
-
-
- `}
-/>
-
-### Weights
-
-Here's a view when links have different weights.
-
-}
- code={`
-
-
- `}
-/>
diff --git a/canon-docs/src/app/(docs)/components/link/props.ts b/canon-docs/src/app/(docs)/components/link/props.ts
deleted file mode 100644
index 83507c5594..0000000000
--- a/canon-docs/src/app/(docs)/components/link/props.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs';
-import type { PropDef } from '@/utils/propDefs';
-
-export const linkPropDefs: Record = {
- to: {
- type: 'string',
- },
- variant: {
- type: 'enum',
- values: ['subtitle', 'body', 'caption', 'label'],
- default: 'body',
- responsive: true,
- },
- weight: {
- type: 'enum',
- values: ['regular', 'bold'],
- default: 'regular',
- responsive: true,
- },
- ...classNamePropDefs,
- ...stylePropDefs,
-};
diff --git a/canon-docs/src/app/(docs)/components/menu/page.mdx b/canon-docs/src/app/(docs)/components/menu/page.mdx
deleted file mode 100644
index 98c4949438..0000000000
--- a/canon-docs/src/app/(docs)/components/menu/page.mdx
+++ /dev/null
@@ -1,157 +0,0 @@
-import { PropsTable } from '@/components/PropsTable';
-import { Snippet } from '@/components/Snippet';
-import { Tabs } from '@/components/Tabs';
-import { CodeBlock } from '@/components/CodeBlock';
-import { MenuSnippet } from '@/snippets/stories-snippets';
-import { BaseUI } from '@/components/HeadlessBanners/BaseUI';
-import {
- menuRootPropDefs,
- menuTriggerPropDefs,
- menuPositionerPropDefs,
- menuItemPropDefs,
-} from './props';
-
-# Menu
-
-A list of actions in a dropdown, enhanced with keyboard navigation.
-
-}
- code={`
- (
-
- )}
- />
-
-
-
- Settings
- Invite new members
- Download app
- Log out
-
-
-
- `}
-/>
-
-
-
- Usage
- Theming
-
-
-
-
-
-
-
-
-
-
-
- `}
- />
-
-
- We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with
- your brand. For additional flexibility, you can use the provided class names for each element listed below.
- - `canon-MenuTrigger`
- - `canon-MenuBackdrop`
- - `canon-MenuPositioner`
- - `canon-MenuPopup`
- - `canon-MenuArrow`
- - `canon-MenuItem`
- - `canon-MenuGroup`
- - `canon-MenuGroupLabel`
- - `canon-MenuRadioGroup`
- - `canon-MenuRadioItem`
- - `canon-MenuRadioItemIndicator`
- - `canon-MenuCheckboxItem`
- - `canon-MenuCheckboxItemIndicator`
- - `canon-MenuSubmenuTrigger`
- - `canon-MenuSeparator`
-
-
-
-## API reference
-
-
-
-### Menu.Root
-
-Groups all parts of the menu. Doesn't render its own HTML element.
-
-
-
-### Menu.Trigger
-
-The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend
-using the `render` prop to render a custom trigger.
-
- } />`} />
-
-
-
-### Menu.Positioner
-
-Positions the menu popup against the trigger. Renders a `
- ),
- pre: ({ children }) => {
- const codeContent = isValidElement(children)
- ? (children.props as { children: string }).children
- : '';
-
- return ;
- },
- code: ({ children }) => (
-
- {children}
-
- ),
- img: props => (
-
- ),
- ...components,
- };
-}
diff --git a/canon-docs/src/snippets/code-snippets.ts b/canon-docs/src/snippets/code-snippets.ts
deleted file mode 100644
index 00a9c1462d..0000000000
--- a/canon-docs/src/snippets/code-snippets.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-// Sometimes codes are not formatted correctly in the docs, so we need to use snippets
-
-export const customTheme = `:root {
- --canon-font-regular: system-ui;
- --canon-font-weight-regular: 400;
- --canon-font-weight-bold: 600;
- --canon-bg: #f8f8f8;
- --canon-bg-surface-1: #fff;
- /* ... other CSS variables */
-
- /* Add your custom components styles here */
- .canon-Button {
- background-color: #000;
- color: #fff;
- }
-}
-
-[data-theme='dark'] {
- --canon-font-regular: system-ui;
- --canon-font-weight-regular: 400;
- --canon-font-weight-bold: 600;
- --canon-bg: #f8f8f8;
- --canon-bg-surface-1: #fff;
- /* ... other CSS variables */
-
- /* Add your custom components styles here */
- .canon-Button {
- background-color: #000;
- color: #fff;
- }
-}
-`;
-
-export const grid = `import { Grid } from '@backstage/canon';
-
-
-
-
-`;
-
-export const buttonVariants = `
-
-
-
-
-`;
-
-export const iconButtonVariants = `
-
-
-
-`;
-
-export const flexFAQ1 = `
- Hello World
- Hello World
- Hello World
-`;
-
-export const flexSimple = `
- Hello World
- Hello World
- Hello World
-`;
-
-export const flexResponsive = `
- Hello World
- Hello World
- Hello World
-`;
-
-export const flexAlign = `
- Hello World
- Hello World
- Hello World
-`;
diff --git a/canon-docs/src/snippets/stories-snippets.tsx b/canon-docs/src/snippets/stories-snippets.tsx
deleted file mode 100644
index 75ee2e31c3..0000000000
--- a/canon-docs/src/snippets/stories-snippets.tsx
+++ /dev/null
@@ -1,167 +0,0 @@
-'use client';
-
-import { composeStories } from '@storybook/react';
-import * as BoxStories from '../../../packages/canon/src/components/Box/Box.stories';
-import * as ButtonStories from '../../../packages/canon/src/components/Button/Button.stories';
-import * as CheckboxStories from '../../../packages/canon/src/components/Checkbox/Checkbox.stories';
-import * as ContainerStories from '../../../packages/canon/src/components/Container/Container.stories';
-import * as GridStories from '../../../packages/canon/src/components/Grid/Grid.stories';
-import * as HeadingStories from '../../../packages/canon/src/components/Heading/Heading.stories';
-import * as IconButtonStories from '../../../packages/canon/src/components/IconButton/IconButton.stories';
-import * as IconStories from '../../../packages/canon/src/components/Icon/Icon.stories';
-import * as TextFieldStories from '../../../packages/canon/src/components/TextField/TextField.stories';
-import * as TextStories from '../../../packages/canon/src/components/Text/Text.stories';
-import * as FlexStories from '../../../packages/canon/src/components/Flex/Flex.stories';
-import * as SelectStories from '../../../packages/canon/src/components/Select/Select.stories';
-import * as MenuStories from '../../../packages/canon/src/components/Menu/Menu.stories';
-import * as LinkStories from '../../../packages/canon/src/components/Link/Link.stories';
-import * as AvatarStories from '../../../packages/canon/src/components/Avatar/Avatar.stories';
-import * as CollapsibleStories from '../../../packages/canon/src/components/Collapsible/Collapsible.stories';
-
-export const BoxSnippet = ({ story }: { story: keyof typeof BoxStories }) => {
- const stories = composeStories(BoxStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const ButtonSnippet = ({
- story,
-}: {
- story: keyof typeof ButtonStories;
-}) => {
- const stories = composeStories(ButtonStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const CheckboxSnippet = ({
- story,
-}: {
- story: keyof typeof CheckboxStories;
-}) => {
- const stories = composeStories(CheckboxStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const ContainerSnippet = ({
- story,
-}: {
- story: keyof typeof ContainerStories;
-}) => {
- const stories = composeStories(ContainerStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const FlexSnippet = ({ story }: { story: keyof typeof FlexStories }) => {
- const stories = composeStories(FlexStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const TextFieldSnippet = ({
- story,
-}: {
- story: keyof typeof TextFieldStories;
-}) => {
- const stories = composeStories(TextFieldStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const GridSnippet = ({ story }: { story: keyof typeof GridStories }) => {
- const stories = composeStories(GridStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const HeadingSnippet = ({
- story,
-}: {
- story: keyof typeof HeadingStories;
-}) => {
- const stories = composeStories(HeadingStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const IconButtonSnippet = ({
- story,
-}: {
- story: keyof typeof IconButtonStories;
-}) => {
- const stories = composeStories(IconButtonStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const IconSnippet = ({ story }: { story: keyof typeof IconStories }) => {
- const stories = composeStories(IconStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const TextSnippet = ({ story }: { story: keyof typeof TextStories }) => {
- const stories = composeStories(TextStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const SelectSnippet = ({
- story,
-}: {
- story: keyof typeof SelectStories;
-}) => {
- const stories = composeStories(SelectStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const MenuSnippet = ({ story }: { story: keyof typeof MenuStories }) => {
- const stories = composeStories(MenuStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const LinkSnippet = ({ story }: { story: keyof typeof LinkStories }) => {
- const stories = composeStories(LinkStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const AvatarSnippet = ({
- story,
-}: {
- story: keyof typeof AvatarStories;
-}) => {
- const stories = composeStories(AvatarStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
-
-export const CollapsibleSnippet = ({
- story,
-}: {
- story: keyof typeof CollapsibleStories;
-}) => {
- const stories = composeStories(CollapsibleStories);
- const StoryComponent = stories[story as keyof typeof stories];
-
- return StoryComponent ? : null;
-};
diff --git a/contrib/catalog/read-write-split/README.md b/contrib/catalog/read-write-split/README.md
new file mode 100644
index 0000000000..4a99ebe076
--- /dev/null
+++ b/contrib/catalog/read-write-split/README.md
@@ -0,0 +1,85 @@
+# Catalog Read-Write Split
+
+This article gives an overview of how you might split your catalog deployment into two - one which handles only reads (the read part of the API), and another that handles everything else (the write part of the API, and processing and ingestion etc).
+
+This is useful for several reasons:
+
+- The performance characteristics and scaling needs of those two concerns typically differ significantly
+- Moving the bursty processing and ingestion load on a separate deployment can make the important read part of the API have more deterministic response times
+- It opens up for easier cross region deployment of read nodes, while having write nodes in a single "home" region
+- It also opens up for primary/secondary split of the underlying database, with streaming replication
+
+## Overview
+
+This is a rough overview of what we will go through:
+
+- Ensure that all frontend code uses `catalogApiRef`, and all backend code uses `catalogServiceRef`, for talking to the catalog
+- Add a separate discovery name for the write deployment
+- Register both frontend and backend implementations of the catalog client that know to send traffic to the right discovery name as needed
+- Set up the backend itself with dedicated read and write configuration
+- Split the deployment into two
+- Follow up with a database split, if desired
+
+## 1. Prerequisite: Establish usage of catalog client refs
+
+First, ensure that all of your code uses _injected_ catalog clients for its catalog communications needs instead of making their own with `new`. For frontend code that means leveraging `catalogApiRef`, and for backend it means leveraging `catalogServiceRef`. This is what enables the sort of wholesale injection of custom behaviors that we are about to do, and is a strongly recommended best practice either way.
+
+- ✅ Search through your projects and ensure that there are no `new CatalogClient` calls. If you find any, consider rewriting that code to instead having the client injected through leveraging the corresponding ref.
+
+- ✅ Search through your projects and ensure that you do _not_ import the `catalogServiceRef` that specifically is in the `@backstage/plugin-catalog-node/alpha` export. That one has been deprecated for a long time and will not be targeted by this guide. If you find any, consider rewriting that code to instead inject the client from `@backstage/plugin-catalog-node` (note the lack of `/alpha`).
+
+> [!TIP]
+> If you find usages of `new CatalogClient` in tests, you can normally leave those as-is. You can however consider to later try out the `catalogApiMock` from `@backstage/plugin-catalog-react/testUtils` for frontend tests, and `catalogServiceMock` from `@backstage/plugin-catalog-node/testUtils` for backend tests. These allow you to inject a client that behaves like a complete fake catalog backend with entities in it, without complex mocking.
+
+## 2. Decide your deployment split structure
+
+We will be defining a fake plugin ID called `catalog-write`. In addition to your current single catalog deployment you will add a second one that receives traffic for `catalog-write`. You need to decide upon what your ingress to those two deployments will look like. This is highly company dependent, so we cannot give general guidance.
+
+This guide will however NOT split the code base into two. It will instead change your catalog backend code in such a way that it can support either deployment. This is all very flexible and you can tweak it as you see fit, but that's what worked well for us.
+
+This guide will assume that when all is said and done, requests for the `catalog` plugin ID resolve to the URL `https://catalog-read.example.net/api/catalog`, and requests for the `catalog-write` plugin ID resolve to the URL `https://catalog-write.example.net/api/catalog`. This is just for illustration and you shall change these to their actual correct values at your company.
+
+- ✅ Copy the contents of [the `app-config.yaml` file](./workspace/app-config.yaml) to your own. We will assume that these exact settings are applied both to your frontend and your catalog (read AND write) deployment. For now, if you are applying this guide step by step rather than all at once, you can set the URLs in there to point to your good old pre-split deployment and only update them again after the split.
+
+> [!TIP]
+> As a future refactor, you could instead break out this behavior into a custom injected discovery implementation in a library that all your projects can import. That takes a few more steps and is left as a separate exercise. If you already have such a library in your internal NPM, feel free to put it there to begin with and import from there.
+
+## 3. Get split-aware catalog clients in place
+
+Now let's put clients in place whose methods send traffic to either `catalog` or `catalog-write` as needed.
+
+- ✅ Copy [the `catalogApi.ts` file](./workspace/packages/app/src/catalogApi.ts) into your `packages/app/src` directory of the project where you develop your Backstage frontend. Then reference that file's API factory in your `packages/app/src/apis.ts` file, [as illustrated here](./workspace/packages/app/src/apis.ts).
+
+- ✅ Copy [the `catalogService.ts` file](./workspace/packages/backend/src/catalogService.ts) into your `packages/backend/src` directory of the project where you develop your Software Catalog backend. We will reference the file itself in the step below.
+
+After step 4 below is complete, these will be automatically picked up and used by all callers.
+
+> [!TIP]
+> As a future refactor, you could instead break out these clients into a node and a react library that all your projects can import. That takes a few more steps and is left as a separate exercise. If you already have such libraries in your internal NPM, feel free to put them there to begin with and import from there.
+
+## 4. Split the catalog backend
+
+We'll now perform the actual split of the catalog backend. You will make separate config files that apply to each, and adapt the backend code to handle both cases seamlessly.
+
+- ✅ Duplicate your deployment. It's highly company dependent how this is done. Some may for example duplicate some declarative `Deployment` and `Service` k8s manifests etc, but it depends.
+
+- ✅ Copy [the `app-config.catalog-read.yaml`] and [the `app-config.catalog-write.yaml`] files into your project root. You must set up your read and write deployments to load their respective files with the `--config` flag, _in addition to_ the `app-config.yaml` file and possibly `app-config.production.yaml` that they already loaded.
+
+- ✅ Copy [the `config.d.ts`](./workspace/config.d.ts) file to your catalog backend directory at `packages/backend`. You should refer to it in the `package.json`'s `"files"` and `"configSchema"` fields [as per usual](https://backstage.io/docs/conf/defining).
+
+- ✅ Update your `packages/backend/src/index.ts` file to match [the proposed structure here](./workspace/packages/backend/src/index.ts). Note how it applies the custom catalog service we copied in the previous step, and has a separate section for write-only concerns.
+
+## 5. Region and database split
+
+After the above is deployed and working, you are well set up for some next step.
+
+- Scaling your readers across multiple regions and add geo-aware routing to them, while keeping writers in a "home" region
+- Splitting the database server into a primary that the write nodes connect to, and regional secondaries with streaming replication from the primary
+
+But all of this is left as an exercise for the reader.
+
+## 6. Help make this smoother
+
+Congratulations on successfully performing your split!
+
+We would love [some help](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md) with making this process easier for others. For example, if read nodes could automatically transparently proxy traffic to write nodes as needed, we would need far less fiddling with clients at a relatively small extra cost.
diff --git a/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml b/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml
new file mode 100644
index 0000000000..33d7f34714
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml
@@ -0,0 +1,12 @@
+# This file should be given to the catalog read nodes.
+
+backend:
+ database:
+ # disable running database migrations for every plugin/module
+ skipMigrations: true
+
+catalog:
+ role: read
+
+ # disable processing engine
+ processingInterval: false
diff --git a/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml b/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml
new file mode 100644
index 0000000000..ea1659e140
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml
@@ -0,0 +1,4 @@
+# This file should be given to the catalog write nodes.
+
+catalog:
+ role: write
diff --git a/contrib/catalog/read-write-split/workspace/app-config.yaml b/contrib/catalog/read-write-split/workspace/app-config.yaml
new file mode 100644
index 0000000000..e4b09e4cb9
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/app-config.yaml
@@ -0,0 +1,19 @@
+# This is in your regular app-config.
+
+# This introduces a made-up "catalog-write" plugin ID that the frontend catalog
+# API implementation can use to resolve where to find the write nodes.
+discovery:
+ endpoints:
+ #
+ # TODO: Replace with actual URLs
+ #
+ # NOTE: Each target can also be an object with "internal" and "external"
+ # keys with different URLs, if they should be different when called by
+ # backends and the frontend, respectively.
+ #
+ - target: https://catalog-read.example.net/api/catalog
+ plugins:
+ - catalog
+ - target: https://catalog-write.example.net/api/catalog
+ plugins:
+ - catalog-write
diff --git a/contrib/catalog/read-write-split/workspace/config.d.ts b/contrib/catalog/read-write-split/workspace/config.d.ts
new file mode 100644
index 0000000000..29a80c77f8
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/config.d.ts
@@ -0,0 +1,5 @@
+export interface Config {
+ catalog: {
+ role: 'read' | 'write';
+ };
+}
diff --git a/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts b/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts
new file mode 100644
index 0000000000..12fd2bfd49
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts
@@ -0,0 +1,11 @@
+import { AnyApiFactory } from '@backstage/core-plugin-api';
+import { catalogApiFactory } from './catalogApi';
+
+// This file is already present in a typical Backstage app. We are just adding
+// the catalog API factory here to ensure that the frontend sends requests to
+// the correct set of catalog nodes depending on whether it's a read or a write
+// operation.
+export const apis: AnyApiFactory[] = [
+ // ...other APIs here...
+ catalogApiFactory,
+];
diff --git a/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts b/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts
new file mode 100644
index 0000000000..0813249f8f
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts
@@ -0,0 +1,174 @@
+import {
+ AddLocationRequest,
+ AddLocationResponse,
+ CatalogApi,
+ CatalogClient,
+ CatalogRequestOptions,
+ GetEntitiesByRefsRequest,
+ GetEntitiesByRefsResponse,
+ GetEntitiesRequest,
+ GetEntitiesResponse,
+ GetEntityAncestorsRequest,
+ GetEntityAncestorsResponse,
+ GetEntityFacetsRequest,
+ GetEntityFacetsResponse,
+ GetLocationsResponse,
+ Location,
+ QueryEntitiesRequest,
+ QueryEntitiesResponse,
+ ValidateEntityResponse,
+} from '@backstage/catalog-client';
+import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
+import {
+ createApiFactory,
+ DiscoveryApi,
+ discoveryApiRef,
+ FetchApi,
+ fetchApiRef,
+} from '@backstage/core-plugin-api';
+import { catalogApiRef } from '@backstage/plugin-catalog-react';
+
+/**
+ * Implements the catalog client for frontends, by using a custom service
+ * discovery to achieve read/write segregation.
+ */
+export class ReadWriteSplitCatalogClient implements CatalogApi {
+ #write: CatalogApi;
+ #read: CatalogApi;
+
+ constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) {
+ this.#read = new CatalogClient({
+ fetchApi: options.fetchApi,
+ discoveryApi: {
+ // This uses the normal "catalog" plugin ID
+ getBaseUrl: () => options.discoveryApi.getBaseUrl('catalog'),
+ },
+ });
+ this.#write = new CatalogClient({
+ fetchApi: options.fetchApi,
+ discoveryApi: {
+ // This uses the made-up "catalog-write" plugin ID (see app-config.yaml
+ // which defines a custom discovery endpoint for this)
+ getBaseUrl: () => options.discoveryApi.getBaseUrl('catalog-write'),
+ },
+ });
+ }
+
+ getEntities(
+ request?: GetEntitiesRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getEntities(request, options);
+ }
+
+ getEntitiesByRefs(
+ request: GetEntitiesByRefsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getEntitiesByRefs(request, options);
+ }
+
+ queryEntities(
+ request?: QueryEntitiesRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.queryEntities(request, options);
+ }
+
+ getEntityAncestors(
+ request: GetEntityAncestorsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getEntityAncestors(request, options);
+ }
+
+ getEntityByRef(
+ entityRef: string | CompoundEntityRef,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getEntityByRef(entityRef, options);
+ }
+
+ removeEntityByUid(
+ uid: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#write.removeEntityByUid(uid, options);
+ }
+
+ refreshEntity(
+ entityRef: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#write.refreshEntity(entityRef, options);
+ }
+
+ getEntityFacets(
+ request: GetEntityFacetsRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getEntityFacets(request, options);
+ }
+
+ getLocations(
+ request?: {},
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getLocations(request, options);
+ }
+
+ getLocationById(
+ id: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getLocationById(id, options);
+ }
+
+ getLocationByRef(
+ locationRef: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getLocationByRef(locationRef, options);
+ }
+
+ addLocation(
+ location: AddLocationRequest,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#write.addLocation(location, options);
+ }
+
+ removeLocationById(
+ id: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#write.removeLocationById(id, options);
+ }
+
+ getLocationByEntity(
+ entityRef: string | CompoundEntityRef,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#read.getLocationByEntity(entityRef, options);
+ }
+
+ validateEntity(
+ entity: Entity,
+ locationRef: string,
+ options?: CatalogRequestOptions,
+ ): Promise {
+ return this.#write.validateEntity(entity, locationRef, options);
+ }
+}
+
+// You should pass this to createApp.
+export const catalogApiFactory = createApiFactory({
+ api: catalogApiRef,
+ deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
+ factory: ({ discoveryApi, fetchApi }) => {
+ return new ReadWriteSplitCatalogClient({
+ discoveryApi,
+ fetchApi,
+ });
+ },
+});
diff --git a/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts b/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts
new file mode 100644
index 0000000000..80711bd4b3
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts
@@ -0,0 +1,231 @@
+import {
+ AuthService,
+ coreServices,
+ createServiceFactory,
+ DiscoveryService,
+} from '@backstage/backend-plugin-api';
+import {
+ AddLocationRequest,
+ AddLocationResponse,
+ CatalogApi,
+ CatalogClient,
+ CatalogRequestOptions,
+ GetEntitiesByRefsRequest,
+ GetEntitiesByRefsResponse,
+ GetEntitiesRequest,
+ GetEntitiesResponse,
+ GetEntityAncestorsRequest,
+ GetEntityAncestorsResponse,
+ GetEntityFacetsRequest,
+ GetEntityFacetsResponse,
+ GetLocationsResponse,
+ Location,
+ QueryEntitiesRequest,
+ QueryEntitiesResponse,
+ ValidateEntityResponse,
+} from '@backstage/catalog-client';
+import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
+import {
+ CatalogService,
+ CatalogServiceRequestOptions,
+ catalogServiceRef,
+} from '@backstage/plugin-catalog-node';
+
+/**
+ * Implements the catalog client for backends, by using a custom service
+ * discovery to achieve read/write segregation.
+ */
+export class ReadWriteSplitCatalogService implements CatalogService {
+ readonly #auth: AuthService;
+ readonly #catalogRead: CatalogApi;
+ readonly #catalogWrite: CatalogApi;
+
+ constructor(options: { auth: AuthService; discovery: DiscoveryService }) {
+ this.#auth = options.auth;
+ this.#catalogRead = new CatalogClient({
+ discoveryApi: {
+ // This uses the normal "catalog" plugin ID
+ getBaseUrl: () => options.discovery.getBaseUrl('catalog'),
+ },
+ });
+ this.#catalogWrite = new CatalogClient({
+ discoveryApi: {
+ // This uses the made-up "catalog-write" plugin ID (see app-config.yaml
+ // which defines a custom discovery endpoint for this)
+ getBaseUrl: () => options.discovery.getBaseUrl('catalog-write'),
+ },
+ });
+ }
+
+ async getEntities(
+ request: GetEntitiesRequest | undefined,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getEntities(
+ request,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getEntitiesByRefs(
+ request: GetEntitiesByRefsRequest,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getEntitiesByRefs(
+ request,
+ await this.#getOptions(options),
+ );
+ }
+
+ async queryEntities(
+ request: QueryEntitiesRequest | undefined,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.queryEntities(
+ request,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getEntityAncestors(
+ request: GetEntityAncestorsRequest,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getEntityAncestors(
+ request,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getEntityByRef(
+ entityRef: string | CompoundEntityRef,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getEntityByRef(
+ entityRef,
+ await this.#getOptions(options),
+ );
+ }
+
+ async removeEntityByUid(
+ uid: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogWrite.removeEntityByUid(
+ uid,
+ await this.#getOptions(options),
+ );
+ }
+
+ async refreshEntity(
+ entityRef: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogWrite.refreshEntity(
+ entityRef,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getEntityFacets(
+ request: GetEntityFacetsRequest,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getEntityFacets(
+ request,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getLocations(
+ options: CatalogRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getLocations(options);
+ }
+
+ async getLocationById(
+ id: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getLocationById(
+ id,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getLocationByRef(
+ locationRef: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getLocationByRef(
+ locationRef,
+ await this.#getOptions(options),
+ );
+ }
+
+ async addLocation(
+ location: AddLocationRequest,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogWrite.addLocation(
+ location,
+ await this.#getOptions(options),
+ );
+ }
+
+ async removeLocationById(
+ id: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogWrite.removeLocationById(
+ id,
+ await this.#getOptions(options),
+ );
+ }
+
+ async getLocationByEntity(
+ entityRef: string | CompoundEntityRef,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogRead.getLocationByEntity(
+ entityRef,
+ await this.#getOptions(options),
+ );
+ }
+
+ async validateEntity(
+ entity: Entity,
+ locationRef: string,
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#catalogWrite.validateEntity(
+ entity,
+ locationRef,
+ await this.#getOptions(options),
+ );
+ }
+
+ async #getOptions(
+ options: CatalogServiceRequestOptions,
+ ): Promise {
+ return this.#auth.getPluginRequestToken({
+ onBehalfOf: options.credentials,
+ targetPluginId: 'catalog',
+ });
+ }
+}
+
+// You should register this in your backend.
+export const catalogService = createServiceFactory({
+ service: catalogServiceRef,
+ deps: {
+ auth: coreServices.auth,
+ discovery: coreServices.discovery,
+ },
+ async factory({ auth, discovery }) {
+ return new ReadWriteSplitCatalogService({
+ auth,
+ discovery,
+ });
+ },
+});
diff --git a/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts b/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts
new file mode 100644
index 0000000000..0d8e9e41d9
--- /dev/null
+++ b/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts
@@ -0,0 +1,34 @@
+import { createBackend } from '@backstage/backend-defaults';
+import {
+ coreServices,
+ createBackendFeatureLoader,
+} from '@backstage/backend-plugin-api';
+import { catalogService } from './catalogService';
+
+const backend = createBackend();
+
+backend.add(import('@backstage/plugin-catalog-backend'));
+backend.add(catalogService);
+// Here at the root level, you can add more features that you want to apply to
+// BOTH the read and write nodes, as needed.
+
+backend.add(
+ createBackendFeatureLoader({
+ deps: { config: coreServices.rootConfig },
+ async *loader({ config }) {
+ if (config.getString('catalog.role') !== 'write') {
+ return;
+ }
+
+ // Here inside the loader, you can add more features that you want to
+ // apply to ONLY the write nodes, as needed. This is where providers and
+ // processors go, for example. The incremental ingestion provider line
+ // below is just an example.
+ yield import(
+ '@backstage/plugin-catalog-backend-module-incremental-ingestion'
+ );
+ },
+ }),
+);
+
+backend.start();
diff --git a/canon-docs/.eslintrc.json b/docs-ui/.eslintrc.json
similarity index 100%
rename from canon-docs/.eslintrc.json
rename to docs-ui/.eslintrc.json
diff --git a/canon-docs/.gitignore b/docs-ui/.gitignore
similarity index 100%
rename from canon-docs/.gitignore
rename to docs-ui/.gitignore
diff --git a/canon-docs/README.md b/docs-ui/README.md
similarity index 60%
rename from canon-docs/README.md
rename to docs-ui/README.md
index d91076c4cd..41b9921413 100644
--- a/canon-docs/README.md
+++ b/docs-ui/README.md
@@ -1,6 +1,6 @@
-# Canon Docs
+# Backstage UI Docs
-Canon is our internal UI library built for Backstage. We built this website to document the library and its components. You can view this website [here](https://canon.backstage.io).
+Backstage UI is our internal UI library built for Backstage. We built this website to document the library and its components. You can view this website [here](https://ui.backstage.io).
## How to run locally
diff --git a/canon-docs/next.config.mjs b/docs-ui/next.config.mjs
similarity index 57%
rename from canon-docs/next.config.mjs
rename to docs-ui/next.config.mjs
index ca221d9a8c..8e6ed8fdc0 100644
--- a/canon-docs/next.config.mjs
+++ b/docs-ui/next.config.mjs
@@ -8,6 +8,11 @@ const nextConfig = {
images: {
unoptimized: true,
},
+ typescript: {
+ // Ignore TypeScript errors during build - safe for React 18/19 compatibility issues
+ // These are type-level conflicts that don't affect runtime behavior
+ ignoreBuildErrors: true,
+ },
};
const withMDX = createMDX({});
diff --git a/docs-ui/package.json b/docs-ui/package.json
new file mode 100644
index 0000000000..71db880859
--- /dev/null
+++ b/docs-ui/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "docs-ui",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "prebuild": "yarn sync:css",
+ "build": "next build",
+ "lint": "next lint",
+ "prestart": "yarn sync:css",
+ "start": "concurrently \"yarn sync:css:watch\" \"next dev\"",
+ "sync:css": "node scripts/sync-css.js",
+ "sync:css:watch": "node scripts/sync-css.js --watch"
+ },
+ "resolutions": {
+ "@types/react": "19.1.9",
+ "@types/react-dom": "19.1.7"
+ },
+ "dependencies": {
+ "@codemirror/lang-sass": "^6.0.2",
+ "@codemirror/view": "^6.34.4",
+ "@lezer/highlight": "^1.2.1",
+ "@mdx-js/loader": "^3.1.0",
+ "@mdx-js/react": "^3.1.0",
+ "@next/mdx": "15.3.4",
+ "@remixicon/react": "^4.6.0",
+ "@storybook/react": "^8.6.12",
+ "@uiw/codemirror-themes": "^4.23.7",
+ "@uiw/react-codemirror": "^4.23.7",
+ "html-react-parser": "^5.2.5",
+ "motion": "^12.4.1",
+ "next": "15.3.4",
+ "next-mdx-remote-client": "^2.1.2",
+ "prop-types": "^15.8.1",
+ "react": "19.1.1",
+ "react-dom": "19.1.1",
+ "shiki": "^1.26.1",
+ "storybook": "^8.6.12"
+ },
+ "devDependencies": {
+ "@types/mdx": "^2.0.13",
+ "@types/node": "^20",
+ "@types/react": "19.1.9",
+ "@types/react-dom": "19.1.7",
+ "chokidar": "^3.6.0",
+ "concurrently": "^8.2.2",
+ "eslint": "^8",
+ "eslint-config-next": "15.3.4",
+ "lightningcss": "^1.28.2",
+ "typescript": "^5"
+ }
+}
diff --git a/canon-docs/public/.nojekyll b/docs-ui/public/.nojekyll
similarity index 100%
rename from canon-docs/public/.nojekyll
rename to docs-ui/public/.nojekyll
diff --git a/docs-ui/public/CNAME b/docs-ui/public/CNAME
new file mode 100644
index 0000000000..21060e506a
--- /dev/null
+++ b/docs-ui/public/CNAME
@@ -0,0 +1 @@
+ui.backstage.io
diff --git a/docs-ui/public/css-classname-structure.png b/docs-ui/public/css-classname-structure.png
new file mode 100644
index 0000000000..c241b182cc
Binary files /dev/null and b/docs-ui/public/css-classname-structure.png differ
diff --git a/docs-ui/public/theme-backstage.css b/docs-ui/public/theme-backstage.css
new file mode 100644
index 0000000000..f69672bc28
--- /dev/null
+++ b/docs-ui/public/theme-backstage.css
@@ -0,0 +1,2 @@
+/*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */
+@layer base{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;tab-size:4;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;line-height:1.15}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentColor}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}}.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--pl-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--pl-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--pl-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--pl-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--pl-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--pr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--pr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--pr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--pr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--pr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--pt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--pt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--pt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--pt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--pt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--pb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--pb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--pb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--pb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--pb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}.bui-AvatarRoot{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-bg-surface-2);border-radius:100%;justify-content:center;align-items:center;width:2rem;height:2rem;font-size:1rem;font-weight:500;line-height:1;display:inline-flex;overflow:hidden}.bui-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.bui-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.bui-AvatarRoot[data-size=large]{width:3rem;height:3rem}.bui-AvatarImage{object-fit:cover;width:100%;height:100%}.bui-AvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-Box{font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary)}.bui-Button{user-select:none;font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-bold);cursor:pointer;border-radius:var(--bui-radius-2);justify-content:center;align-items:center;gap:var(--bui-space-1_5);border:none;flex-shrink:0;padding:0;display:inline-flex;&[data-disabled=true]{cursor:not-allowed}}.bui-Button[data-variant=primary]{background-color:var(--bui-bg-solid);color:var(--bui-fg-solid);&:hover{background-color:var(--bui-bg-solid-hover);transition:background-color .15s}&:active{background-color:var(--bui-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled=true]{background-color:var(--bui-bg-solid-disabled);color:var(--bui-fg-solid-disabled)}}.bui-Button[data-variant=secondary]{background-color:var(--bui-bg-surface-1);box-shadow:inset 0 0 0 1px var(--bui-border);color:var(--bui-fg-primary);&:hover{box-shadow:inset 0 0 0 1px var(--bui-border-hover);transition:box-shadow .15s}&:active{box-shadow:inset 0 0 0 1px var(--bui-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{box-shadow:inset 0 0 0 1px var(--bui-border-disabled);color:var(--bui-fg-disabled)}}.bui-Button[data-variant=tertiary]{color:var(--bui-fg-primary);background-color:#0000;&:hover{background-color:var(--bui-bg-surface-1);transition:background-color .2s}&:active{background-color:var(--bui-bg-surface-2)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{color:var(--bui-fg-disabled);background-color:#0000}}.bui-Button[data-size=medium]{font-size:var(--bui-font-size-4);padding:0 var(--bui-space-3);height:2.5rem}.bui-Button[data-size=small]{font-size:var(--bui-font-size-3);padding:0 var(--bui-space-2);height:2rem}.bui-Button[data-size=small] svg{width:1rem;height:1rem}.bui-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.bui-ButtonIcon{justify-content:center;align-items:center}.bui-ButtonIcon[data-size=small]{width:2rem;padding:0}.bui-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.bui-Card{gap:var(--bui-space-3);background-color:var(--bui-bg-surface-1);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-3);color:var(--bui-fg-primary);border:1px solid var(--bui-border);flex-direction:column;width:100%;min-height:0;display:flex;overflow:hidden}.bui-CardBody{flex:1;min-height:0;overflow:auto}.bui-CardHeader,.bui-CardFooter{padding-inline:var(--bui-space-3)}.bui-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--bui-border);cursor:pointer;background-color:var(--bui-bg-surface-1);border:none;border-radius:2px;flex-shrink:0;justify-content:center;align-items:center;padding:0;transition:background-color .2s ease-in-out;display:flex}.bui-CheckboxRoot:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px;transition:none}.bui-CheckboxRoot[data-checked]{background-color:var(--bui-bg-solid);box-shadow:none;color:var(--bui-fg-solid)}.bui-CheckboxLabel{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .bui-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--bui-border-hover)}}}.bui-CheckboxIndicator{color:var(--bui-fg-solid);justify-content:center;align-items:center;display:flex}.bui-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.bui-Container{max-width:120rem;padding-inline:var(--bui-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.bui-Container{padding-inline:var(--bui-space-5)}}.bui-FieldError{color:var(--bui-fg-danger);font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);margin-top:var(--bui-space-2);display:inline-block}.bui-FieldLabelWrapper{margin-bottom:var(--bui-space-3);gap:var(--bui-space-1);flex-direction:column;display:flex}.bui-FieldLabel{color:var(--bui-fg-primary);cursor:pointer;font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);margin-right:auto}.bui-FieldSecondaryLabel{color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular);margin-left:var(--bui-space-1)}.bui-FieldDescription{font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);margin:0}.bui-Flex{min-width:0;display:flex}.bui-Grid{display:grid}.bui-HeaderToolbar{margin-bottom:var(--bui-space-6);&:before{content:"";background-color:var(--bui-bg);z-index:0;height:16px;position:absolute;top:0;left:0;right:0}&[data-has-tabs=true]{margin-bottom:0}}.bui-HeaderToolbarWrapper{z-index:1;background-color:var(--bui-bg-surface-1);padding-inline:var(--bui-space-5);border-bottom:1px solid var(--bui-border);color:var(--bui-fg-primary);flex-direction:row;justify-content:space-between;align-items:center;height:52px;display:flex;position:relative}.bui-HeaderToolbarContent{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-HeaderToolbarName{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);flex-direction:row;flex-shrink:0;display:flex}.bui-HeaderToolbarIcon{width:16px;height:16px;color:var(--bui-fg-primary);& svg{width:100%;height:100%}}.bui-HeaderToolbarControls{right:var(--bui-space-5);align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex;position:absolute;top:50%;transform:translateY(-50%)}.bui-HeaderTabsWrapper{margin-bottom:var(--bui-space-4);padding-inline:var(--bui-space-3);border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1)}.bui-HeaderPage{gap:var(--bui-space-1);margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6);flex-direction:column;display:flex}.bui-HeaderPageContent{flex-direction:row;justify-content:space-between;display:flex}.bui-HeaderPageTabsWrapper{margin-left:-8px}.bui-HeaderPageControls,.bui-HeaderPageBreadcrumbs{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-Icon{width:1rem;height:1rem}.bui-Link{font-family:var(--bui-font-regular);cursor:pointer;margin:0;padding:0;text-decoration-line:none;display:inline-block;&:hover{text-underline-offset:calc(.025em + 2px);text-decoration-line:underline;text-decoration-style:solid;text-decoration-thickness:min(2px,max(1px,.05em));text-decoration-color:color-mix(in srgb,currentColor 30%,transparent)}}.bui-MenuPositioner{z-index:100;outline:0}.bui-MenuPopup{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);color:var(--bui-fg-primary);transform-origin:var(--transform-origin);max-width:min(var(--available-width),340px);max-height:min(var(--available-height),500px);padding-bottom:var(--bui-space-1);border-radius:.375rem;outline:none;flex-direction:column;transition:transform .15s,opacity .15s;display:flex;position:relative;overflow:auto;&[data-starting-style],&[data-ending-style]{opacity:0;transform:scale(.9)}}.bui-MenuItem{user-select:none;align-items:center;gap:var(--bui-space-2);height:32px;color:var(--bui-fg-primary);border-radius:var(--bui-radius-2);margin-inline:var(--bui-space-1);padding-inline:var(--bui-space-2);font-size:var(--bui-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;&:first-child{margin-top:var(--bui-space-1)}&[data-highlighted]{background-color:var(--bui-gray-3)}}.bui-MenuSubmenuTrigger{user-select:none;justify-content:space-between;align-items:center;gap:var(--bui-space-2);height:32px;color:var(--bui-fg-primary);border-radius:var(--bui-radius-2);margin-inline:var(--bui-space-1);padding-inline:var(--bui-space-2);font-size:var(--bui-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;& .bui-Icon{color:var(--bui-fg-secondary)}&:first-child{margin-top:var(--bui-space-1)}&[data-popup-open],&[data-highlighted]{background-color:var(--bui-gray-3);& .bui-Icon{color:var(--bui-fg-primary)}}}.bui-MenuSeparator{background-color:var(--color-gray-200);height:1px;margin:.375rem 1rem}.bui-SubmenuComboboxSearch{padding-inline:var(--bui-space-3);border:none;border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);width:100%;height:32px;color:var(--bui-fg-primary);line-height:140%;font-size:var(--bui-font-size-3);z-index:1;outline:none;position:sticky;top:0;&::placeholder{color:var(--bui-fg-secondary)}&:disabled{opacity:.6;cursor:not-allowed}}.bui-SubmenuComboboxItems{padding-top:var(--bui-space-2);outline:none;flex-direction:column;display:flex;overflow-y:auto}.bui-SubmenuComboboxNoResults{padding-inline:var(--bui-space-3);padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-4);color:var(--bui-fg-secondary);font-size:var(--bui-font-size-3)}.bui-SubmenuComboboxItem{user-select:none;justify-content:space-between;align-items:center;gap:var(--bui-space-2);height:32px;color:var(--bui-fg-primary);border-radius:var(--bui-radius-2);margin-inline:var(--bui-space-1);padding-inline:var(--bui-space-2);font-size:var(--bui-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;&[data-highlighted]{background-color:var(--bui-gray-3)}&[data-disabled]{opacity:.5;cursor:not-allowed}}.bui-SubmenuComboboxItemCheckbox{width:16px;height:16px;color:var(--bui-fg-primary);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background:var(--bui-bg-surface-1);flex-shrink:0;justify-content:center;align-items:center;display:flex}.bui-SubmenuComboboxItemLabel{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.bui-Popover{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-1);margin-right:12px;overflow:scroll;box-shadow:0 4px 12px #0000001a}.bui-RadioGroup{color:var(--bui-fg-primary);flex-direction:column;display:flex}.bui-RadioGroup[data-orientation=horizontal] .bui-RadioGroupContent{gap:var(--bui-space-4);flex-direction:row}.bui-RadioGroupContent{gap:var(--bui-space-2);flex-direction:column;display:flex}.bui-Radio{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-2);color:var(--bui-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--bui-border);background:var(--bui-gray-1);border-radius:var(--bui-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--bui-border)}&[data-selected]{&:before{border-color:var(--bui-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--bui-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--bui-border-danger)}&[data-disabled][data-invalid]{color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}}.bui-Table{caption-side:bottom;border-collapse:collapse;width:100%}.bui-TableHeader{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out}.bui-TableHead{text-align:left;padding:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary)}.bui-TableHeadSortButton{cursor:pointer;user-select:none;align-items:center;gap:var(--bui-space-1);display:inline-flex;&:hover svg{opacity:.5}& svg{opacity:0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}&[data-sort-order=asc] svg{opacity:1;transform:rotate(0)}&[data-sort-order=desc] svg{opacity:1;transform:rotate(180deg)}}.bui-TableBody{color:var(--bui-fg-primary)}.bui-TableRow{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out;&[data-react-aria-pressable=true]{cursor:pointer}}.bui-TableBody .bui-TableRow:hover{background-color:var(--bui-gray-2)}.bui-TableCell{padding:var(--bui-space-3);font-size:var(--bui-font-size-3);padding:var(--bui-space-3);font-size:var(--bui-font-size-3)}.bui-TableCellContentWrapper{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:inline-flex}.bui-TableCellIcon,.bui-TableCellIcon svg{color:var(--bui-fg-primary);align-items:center;display:inline-flex}.bui-TableCellContent{gap:var(--bui-space-0_5);flex-direction:column;display:flex}.bui-TableCellProfile{gap:var(--bui-space-2);flex-direction:row;align-items:center;display:flex}.bui-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-bg-surface-2);border-radius:100%;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;font-size:1rem;font-weight:500;line-height:1;display:inline-flex;overflow:hidden}.bui-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.bui-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-DataTablePagination{padding-top:var(--bui-space-5);justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--bui-space-2);display:flex}.bui-DataTablePagination--select{min-width:10.5rem}.bui-Tabs{--active-tab-left:0px;--active-tab-right:0px;--active-tab-top:0px;--active-tab-bottom:0px;--active-tab-width:0px;--active-tab-height:0px;--active-transition-duration:0s;--hovered-tab-left:0px;--hovered-tab-right:0px;--hovered-tab-top:0px;--hovered-tab-bottom:0px;--hovered-tab-width:0px;--hovered-tab-height:0px;--hovered-tab-opacity:0;--hovered-transition-duration:0s}.bui-TabList{flex-direction:row;display:flex}.bui-TabListWrapper{position:relative}.bui-Tab{font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-secondary);cursor:pointer;z-index:2;height:36px;padding-inline:var(--bui-space-2);justify-content:center;align-items:center;display:flex;position:relative;&[data-selected=true]{color:var(--bui-fg-primary)}}.bui-TabActive{content:"";left:calc(var(--active-tab-left) + var(--bui-space-2));width:calc(var(--active-tab-width) - var(--bui-space-4));background-color:var(--bui-fg-primary);height:1px;transition:left var(--active-transition-duration)ease-out,opacity .15s ease-out,width var(--active-transition-duration)ease-out;opacity:1;border-radius:4px;position:absolute;bottom:-1px}.bui-TabHovered{content:"";left:var(--hovered-tab-left);top:calc(var(--hovered-tab-top) + 4px);width:var(--hovered-tab-width);height:calc(var(--hovered-tab-height) - 8px);background-color:var(--bui-gray-2);opacity:var(--hovered-tab-opacity);transition:left var(--hovered-transition-duration)ease-out,top var(--hovered-transition-duration)ease-out,width var(--hovered-transition-duration)ease-out,height var(--hovered-transition-duration)ease-out,opacity .15s ease-out;border-radius:4px;position:absolute}.bui-TabPanel{padding-inline:var(--bui-space-2);padding-top:var(--bui-space-4)}.bui-Text{font-family:var(--bui-font-regular);margin:0;padding:0}.bui-Text[data-variant=title-large]{font-size:var(--bui-font-size-8);line-height:140%}.bui-Text[data-variant=title-medium]{font-size:var(--bui-font-size-7);line-height:140%}.bui-Text[data-variant=title-small]{font-size:var(--bui-font-size-6);line-height:140%}.bui-Text[data-variant=title-x-small]{font-size:var(--bui-font-size-5);line-height:140%}.bui-Text[data-variant=body-large]{font-size:var(--bui-font-size-4);line-height:140%}.bui-Text[data-variant=body-medium]{font-size:var(--bui-font-size-3);line-height:140%}.bui-Text[data-variant=body-small]{font-size:var(--bui-font-size-2);line-height:140%}.bui-Text[data-variant=body-x-small]{font-size:var(--bui-font-size-1);line-height:140%}.bui-Text[data-weight=regular]{font-weight:var(--bui-font-weight-regular)}.bui-Text[data-weight=bold]{font-weight:var(--bui-font-weight-bold)}.bui-Text[data-color=primary]{color:var(--bui-fg-primary)}.bui-Text[data-color=secondary]{color:var(--bui-fg-secondary)}.bui-Text[data-color=danger]{color:var(--bui-fg-danger)}.bui-Text[data-color=warning]{color:var(--bui-fg-warning)}.bui-Text[data-color=success]{color:var(--bui-fg-success)}.bui-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bui-Text[data-as=span],.bui-Text[data-as=label],.bui-Text[data-as=strong],.bui-Text[data-as=em],.bui-Text[data-as=small]{display:inline-block}.bui-TextField{font-family:var(--bui-font-regular);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputWrapper{position:relative;&[data-size=small] .bui-Input{height:2rem}&[data-size=medium] .bui-Input{height:2.5rem}&[data-size=small] .bui-Input[data-icon]{padding-left:var(--bui-space-8)}&[data-size=medium] .bui-Input[data-icon]{padding-left:var(--bui-space-9)}}.bui-InputIcon{left:var(--bui-space-3);margin-right:var(--bui-space-1);color:var(--bui-fg-primary);pointer-events:none;flex-shrink:0;transition:left .2s ease-in-out;position:absolute;top:50%;transform:translateY(-50%);&[data-size=small],&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium],&[data-size=medium] svg{width:1.25rem;height:1.25rem}}.bui-Input{padding:0 var(--bui-space-3);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);width:100%;height:100%;cursor:inherit;align-items:center;transition:border-color .2s ease-in-out,outline-color .2s ease-in-out;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}&::placeholder{color:var(--bui-fg-secondary)}&[data-focused]{outline-color:var(--bui-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--bui-border-disabled)}}.bui-SearchField{&[data-empty]{& .bui-InputClear{display:none}}&[data-start-collapsed=true]{padding:0;transition:width .3s ease-in-out;&[data-collapsed=false]{cursor:pointer;&[data-size=medium]{width:2.5rem;height:2.5rem}&[data-size=small]{width:2rem;height:2rem}&[data-size=medium] .bui-Input{padding-left:0;&::placeholder{opacity:0}}&[data-size=small] .bui-Input{padding-left:0;&::placeholder{opacity:0}}&[data-size=small] .bui-InputIcon{left:var(--bui-space-2)}&[data-size=medium] .bui-InputIcon{left:10px}}}}.bui-InputClear{cursor:pointer;color:var(--bui-fg-secondary);background-color:#0000;border:none;justify-content:center;align-items:center;margin:0;padding:0;transition:color .2s ease-in-out;display:flex;position:absolute;top:0;bottom:0;right:0}.bui-InputClear:hover{color:var(--bui-fg-primary)}.bui-InputClear[data-size=small]{width:2rem;height:2rem}.bui-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.bui-InputClear svg{width:1rem;height:1rem}.bui-Skeleton{animation:var(--bui-animate-pulse);background-color:var(--bui-bg-surface-2);border-radius:var(--bui-radius-2)}.bui-Skeleton[data-rounded=true]{border-radius:var(--bui-radius-full)}.bui-Tooltip{background:var(--bui-bg-surface-1);border:1px solid var(--bui-gray-3);forced-color-adjust:none;padding:var(--bui-space-2)var(--bui-space-3);max-width:240px;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);color:var(--bui-fg-primary);border-radius:4px;outline:none;transition:transform .2s,opacity .2s;transform:translate(0,0);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}--tooltip-offset:var(--bui-space-3)&[data-placement=top]{margin-bottom:var(--tooltip-offset);--origin:translateY(4px)}&[data-placement=right]{margin-left:var(--tooltip-offset);--origin:translateX(-4px)}&[data-placement=bottom]{margin-top:var(--tooltip-offset);--origin:translateY(-4px)}&[data-placement=left]{margin-right:var(--tooltip-offset);--origin:translateX(4px)}}.bui-TooltipArrow{& svg{display:block;& path:first-child{fill:var(--bui-bg-surface-1)}& path:nth-child(2){fill:var(--bui-gray-3)}--tooltip-arrow-overlap:-2px}&[data-placement=top] svg{margin-top:var(--tooltip-arrow-overlap)}&[data-placement=bottom] svg{margin-bottom:var(--tooltip-arrow-overlap);transform:rotate(180deg)}&[data-placement=right] svg{margin-right:var(--tooltip-arrow-overlap);transform:rotate(90deg)}&[data-placement=left] svg{margin-left:var(--tooltip-arrow-overlap);transform:rotate(-90deg)}}[data-theme=dark]{& .bui-Tooltip{background:var(--bui-bg-surface-2);box-shadow:none;border:1px solid var(--bui-gray-4)}& .bui-TooltipArrow{& svg path:first-child{fill:var(--bui-bg-surface-2)}& svg path:nth-child(2){fill:var(--bui-gray-4)}}}.bui-ScrollAreaRoot{box-sizing:border-box;width:100%}.bui-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.bui-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.bui-ScrollAreaScrollbar{background-color:var(--bui-scrollbar);opacity:0;border-radius:.375rem;justify-content:center;width:.25rem;margin:.5rem;transition:opacity .15s .3s;display:flex;&[data-hovering],&[data-scrolling]{opacity:1;transition-duration:75ms;transition-delay:0s}&:before{content:"";width:1.25rem;height:100%;position:absolute}}.bui-ScrollAreaThumb{border-radius:inherit;background-color:var(--bui-scrollbar-thumb);width:100%}.bui-Select[data-invalid]{& .bui-SelectTrigger{border-color:var(--bui-fg-danger)}}.bui-SelectTrigger{box-sizing:border-box;border-radius:var(--bui-radius-3);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--bui-space-2);width:100%;display:flex;& svg{color:var(--bui-fg-secondary);flex-shrink:0}&[data-size=small]{height:2rem;padding-inline:var(--bui-space-3)}&[data-size=medium]{height:3rem;padding-inline:var(--bui-space-4)}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}&::placeholder{color:var(--bui-fg-secondary)}&:hover{border-color:var(--bui-border-hover);transition:border-color .2s ease-in-out,outline-color .2s ease-in-out}&:focus-visible{border-color:var(--bui-border-pressed);outline:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-invalid]:hover,&[data-invalid]:focus-visible{border-width:2px}&[disabled]{cursor:not-allowed;border-color:var(--bui-border-disabled);color:var(--bui-fg-disabled)}&[disabled] .bui-SelectValue{color:var(--bui-fg-disabled)}&[data-popup-open] .bui-SelectIcon{transform:rotate(180deg)}}.bui-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);text-align:left;overflow:hidden;& .bui-SelectItemIndicator{display:none}&[disabled]{color:var(--bui-fg-disabled)}}.bui-SelectItem{width:var(--anchor-width);padding-block:var(--bui-space-2);padding-left:var(--bui-space-3);padding-right:var(--bui-space-4);color:var(--bui-fg-primary);border-radius:var(--bui-radius-3);cursor:pointer;user-select:none;font-size:var(--bui-font-size-3);align-items:center;gap:var(--bui-space-1);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative;&[data-focused]{z-index:0;color:var(--bui-fg-primary);position:relative}&[data-focused]:before{content:"";z-index:-1;background-color:var(--bui-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled)}&[data-selected] .bui-SelectItemIndicator{opacity:1}}.bui-SelectItemIndicator{opacity:0;grid-area:icon;justify-content:center;align-items:center;transition:opacity .2s ease-in-out;display:flex}.bui-SelectItemLabel{flex:1;grid-area:text}.bui-Switch{align-items:center;gap:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .bui-SwitchIndicator{&:before{background:var(--bui-fg-solid)}}&[data-selected]{& .bui-SwitchIndicator{background:var(--bui-bg-solid);&:before{background:var(--bui-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--bui-gray-3)}}}&[data-focus-visible] .bui-SwitchIndicator{outline-offset:2px;outline:2px solid}}.bui-SwitchIndicator{background:var(--bui-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--bui-fg-solid);border-radius:16px;width:.857rem;height:.857rem;margin:.143rem;transition:all .2s;display:block}}
\ No newline at end of file
diff --git a/docs-ui/public/theme-spotify.css b/docs-ui/public/theme-spotify.css
new file mode 100644
index 0000000000..f3ae2b7c0d
--- /dev/null
+++ b/docs-ui/public/theme-spotify.css
@@ -0,0 +1 @@
+@font-face{font-family:CircularSpTitle;font-weight:900;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Black-4588c99025b967475c31695b0743dd1a.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Black-506746f387a26f25aa3d023b3e501d34.woff)format("woff")}@font-face{font-family:CircularSpTitle;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-b2586b06a2e1522e9d879d84c2792a58.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSpTitle-Bold-1624fb2df28c20d7203d7fb86ce8b481.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:400;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Book-a00e99ef9996a3a157fb6b746856d04f.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Book-3f73da7d35bd81c706bce7bbb84964de.woff)format("woff")}@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}[data-theme-name=spotify]{--bui-font-text:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-title:CircularSpTitle,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--bui-font-regular:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;& .bui-Button{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3)}& .bui-ButtonIcon{padding:0}& .bui-MenuPopup{box-sizing:border-box;max-width:21.25rem}& .bui-MenuSubmenuTrigger,& .bui-MenuItem{height:auto;min-height:2rem}& .bui-Text{font-family:var(--bui-font-text)}& .bui-Heading{font-family:var(--bui-font-title)}& .bui-TableRow{border-radius:var(--bui-radius-4);border:none}& .bui-TableRow:hover td:first-child{border-top-left-radius:var(--bui-radius-2);border-bottom-left-radius:var(--bui-radius-2)}& .bui-TableRow:hover td:last-child{border-top-right-radius:var(--bui-radius-2);border-bottom-right-radius:var(--bui-radius-2)}& .bui-TableBody:before,& .bui-TableBody:after{line-height:var(--bui-space-1);content:"";display:block}& .bui-TableHeader .bui-TableRow{border-bottom:1px solid var(--bui-border)}& .bui-TableHead{font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular)}& .bui-HeaderToolbar{padding-top:var(--bui-space-2);padding-inline:var(--bui-space-2)}& .bui-HeaderToolbarWrapper{border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-3);border:none}& .bui-HeaderToolbarControls{right:calc(var(--bui-space-3) - 1px)}& .bui-HeaderTabsWrapper{margin-top:var(--bui-space-2);margin-inline:var(--bui-space-2);border-radius:var(--bui-radius-3);padding-inline:var(--bui-space-1);border:none}& .bui-Input{border-radius:var(--bui-radius-3)}}[data-theme-mode=light][data-theme-name=spotify]{--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:var(--bui-gray-2);--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-solid:var(--bui-black);--bui-border:var(--bui-gray-3);--bui-border-hover:#0000004d;--bui-border-pressed:#00000080;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#0003;& .bui-HeaderToolbarWrapper,& .bui-HeaderTabsWrapper{border:1px solid var(--bui-border)}}[data-theme-mode=dark][data-theme-name=spotify]{--bui-bg:var(--bui-black);--bui-bg-surface-1:var(--bui-gray-1);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1ed760;--bui-bg-solid-hover:#3be477;--bui-bg-solid-pressed:#1abc54;--bui-bg-solid-disabled:#0f6c30;--bui-bg-tint:#242424;--bui-bg-tint-hover:#202020;--bui-bg-tint-pressed:#292929;--bui-bg-tint-disabled:#fffc;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:var(--bui-white);--bui-fg-link-hover:var(--bui-white);--bui-fg-disabled:var(--bui-gray-5);--bui-fg-solid:var(--bui-black);--bui-fg-solid-disabled:#083618;--bui-fg-tint:var(--bui-white);--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:var(--bui-gray-3);--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#fff3}
\ No newline at end of file
diff --git a/docs-ui/scripts/sync-css.js b/docs-ui/scripts/sync-css.js
new file mode 100644
index 0000000000..4763fdecc1
--- /dev/null
+++ b/docs-ui/scripts/sync-css.js
@@ -0,0 +1,149 @@
+const fs = require('fs');
+const path = require('path');
+const { bundle } = require('lightningcss');
+const chokidar = require('chokidar');
+
+// Configuration
+const config = {
+ UIPath: '../../packages/ui',
+ publicPath: '../public',
+ files: [
+ {
+ source: 'css/styles.css',
+ destination: 'theme-backstage.css',
+ name: 'Main Styles',
+ },
+ {
+ source: '../../.storybook/themes/spotify.css',
+ destination: 'theme-spotify.css',
+ name: 'Spotify Theme',
+ },
+ ],
+};
+
+class CSSSync {
+ constructor() {
+ this.UIPath = path.resolve(__dirname, config.UIPath);
+ this.publicPath = path.resolve(__dirname, config.publicPath);
+ this.isWatching = process.argv.includes('--watch');
+ }
+
+ async syncFile(fileConfig) {
+ const sourcePath = path.join(this.UIPath, fileConfig.source);
+ const destPath = path.join(this.publicPath, fileConfig.destination);
+
+ try {
+ // Check if source file exists
+ if (!fs.existsSync(sourcePath)) {
+ console.warn(`⚠️ Source file not found: ${sourcePath}`);
+ return false;
+ }
+
+ // Ensure destination directory exists
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
+
+ // Bundle and optimize CSS
+ const result = await bundle({
+ filename: sourcePath,
+ minify: true,
+ });
+
+ // Write to destination
+ fs.writeFileSync(destPath, result.code);
+
+ console.log(
+ `✅ ${fileConfig.name}: ${fileConfig.source} → ${fileConfig.destination}`,
+ );
+ return true;
+ } catch (error) {
+ console.error(`❌ Error syncing ${fileConfig.name}:`, error.message);
+ return false;
+ }
+ }
+
+ async syncAll() {
+ console.log('🔄 Syncing CSS files...\n');
+
+ let successCount = 0;
+ for (const fileConfig of config.files) {
+ if (await this.syncFile(fileConfig)) {
+ successCount++;
+ }
+ }
+
+ console.log(
+ `\n✨ Synced ${successCount}/${config.files.length} CSS files successfully!`,
+ );
+
+ if (successCount > 0) {
+ console.log('\n📁 Available CSS files in public/:');
+ config.files.forEach(file => {
+ const destPath = path.join(this.publicPath, file.destination);
+ if (fs.existsSync(destPath)) {
+ const stats = fs.statSync(destPath);
+ const size = (stats.size / 1024).toFixed(2);
+ console.log(` • ${file.destination} (${size} KB)`);
+ }
+ });
+ }
+ }
+
+ startWatching() {
+ console.log('👀 Watching for CSS changes...\n');
+
+ // Watch all source files
+ const watchPaths = config.files.map(file =>
+ path.join(this.UIPath, file.source),
+ );
+
+ const watcher = chokidar.watch(watchPaths, {
+ ignored: /node_modules/,
+ persistent: true,
+ });
+
+ watcher.on('change', async filePath => {
+ console.log(
+ `\n🔄 Change detected: ${path.relative(this.UIPath, filePath)}`,
+ );
+
+ // Find which file changed and sync it
+ const fileConfig = config.files.find(file =>
+ filePath.endsWith(file.source.replace(/\//g, path.sep)),
+ );
+
+ if (fileConfig) {
+ await this.syncFile(fileConfig);
+ }
+ });
+
+ watcher.on('error', error => console.error('❌ Watch error:', error));
+
+ // Handle process termination
+ process.on('SIGINT', () => {
+ console.log('\n👋 Stopping CSS sync...');
+ watcher.close();
+ process.exit(0);
+ });
+ }
+
+ async run() {
+ console.log('🎨 BUI CSS Sync Tool\n');
+ console.log(`📂 BUI path: ${this.UIPath}`);
+ console.log(`📂 Public path: ${this.publicPath}\n`);
+
+ // Initial sync
+ await this.syncAll();
+
+ // Watch for changes if requested
+ if (this.isWatching) {
+ this.startWatching();
+ }
+ }
+}
+
+// Run the sync tool
+const cssSync = new CSSSync();
+cssSync.run().catch(error => {
+ console.error('❌ CSS Sync failed:', error);
+ process.exit(1);
+});
diff --git a/canon-docs/src/app/(docs)/about/page.mdx b/docs-ui/src/app/about/page.mdx
similarity index 62%
rename from canon-docs/src/app/(docs)/about/page.mdx
rename to docs-ui/src/app/about/page.mdx
index a4c16ee79e..2c87a3d03e 100644
--- a/canon-docs/src/app/(docs)/about/page.mdx
+++ b/docs-ui/src/app/about/page.mdx
@@ -1,7 +1,7 @@
-# About Canon
+# About Backstage UI
-Canon is a design system created specifically for Backstage, built with React, TypeScript, and vanilla CSS.
-This open-source library is hosted in the Backstage monorepo. While it can be used in other projects, Canon
+Backstage UI is a design system created specifically for Backstage, built with React, TypeScript, and vanilla CSS.
+This open-source library is hosted in the Backstage monorepo. While it can be used in other projects, Backstage UI
is designed to deliver a consistent, accessible, and extensible experience tailored to Backstage users.
## Philosophy
@@ -17,16 +17,16 @@ and flexible theming system.
## Team
-Canon is designed and maintained primarily by Spotify's Backstage team, leveraging Spotify's expertise in
+Backstage UI is designed and maintained primarily by Spotify's Backstage team, leveraging Spotify's expertise in
crafting high-quality design and technology. Drawing from our experience in building reliable and intuitive
user experiences for the music industry, we've created a design system that looks great and works seamlessly.
## Community
-Canon is an open-source project and we welcome contributions from the community. If you are interested in
-contributing to Canon, please read our [contributing guide](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)
+Backstage UI is an open-source project and we welcome contributions from the community. If you are interested in
+contributing to Backstage UI, please read our [contributing guide](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)
and our [code of conduct](https://github.com/backstage/backstage/blob/master/CODE_OF_CONDUCT.md).
## License
-Canon is licensed under the Apache 2.0 license. See the [LICENSE](https://github.com/backstage/backstage/blob/master/LICENSE) file for more details.
+Backstage UI is licensed under the Apache 2.0 license. See the [LICENSE](https://github.com/backstage/backstage/blob/master/LICENSE) file for more details.
diff --git a/docs-ui/src/app/changelog/page.mdx b/docs-ui/src/app/changelog/page.mdx
new file mode 100644
index 0000000000..bbeaa98458
--- /dev/null
+++ b/docs-ui/src/app/changelog/page.mdx
@@ -0,0 +1,13 @@
+import { Changelog } from '@/components/Changelog';
+
+# Changelog
+
+
+
+## Version 0.1.0
+
+We're excited to share the initial release of Backstage UI 💚 In this first alpha version,
+you'll find the foundation of our design system: a set of versatile layout components
+and a handful of essential atomic elements to help you get started. While Backstage UI is
+still in its early stages, it's ready for exploration and we'd love for you to give
+it a try and share your feedback.
diff --git a/docs-ui/src/app/components/[slug]/page.tsx b/docs-ui/src/app/components/[slug]/page.tsx
new file mode 100644
index 0000000000..d6f98c8f93
--- /dev/null
+++ b/docs-ui/src/app/components/[slug]/page.tsx
@@ -0,0 +1,25 @@
+import { components, layoutComponents } from '@/utils/data';
+
+export default async function Page({
+ params,
+}: {
+ params: Promise<{ slug: string }>;
+}) {
+ const { slug } = await params;
+
+ const { default: Component } = await import(
+ `@/content/components/${slug}.mdx`
+ );
+
+ return ;
+}
+
+export function generateStaticParams() {
+ const list = [...components, ...layoutComponents];
+
+ return list.map(component => ({
+ slug: component.slug,
+ }));
+}
+
+export const dynamicParams = false;
diff --git a/docs-ui/src/app/icon.svg b/docs-ui/src/app/icon.svg
new file mode 100644
index 0000000000..b50d29e902
--- /dev/null
+++ b/docs-ui/src/app/icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/canon-docs/src/app/(docs)/theme/iconography/page.mdx b/docs-ui/src/app/iconography/page.mdx
similarity index 100%
rename from canon-docs/src/app/(docs)/theme/iconography/page.mdx
rename to docs-ui/src/app/iconography/page.mdx
diff --git a/docs-ui/src/app/install/page.mdx b/docs-ui/src/app/install/page.mdx
new file mode 100644
index 0000000000..329d477eca
--- /dev/null
+++ b/docs-ui/src/app/install/page.mdx
@@ -0,0 +1,36 @@
+import { CodeBlock } from '@/components/CodeBlock';
+
+# How to install Backstage UI
+
+## 1. Import the package
+
+Import the package using a package manager.
+
+
+
+## 2. Import the css files
+
+Import the global CSS file at the root of your application.
+
+```tsx
+import '@backstage/ui/css/styles.css';
+```
+
+## 3. Start building ✨
+
+Now you can start building your plugin using the new design system.
+
+```tsx
+import { Flex, Button, Text } from '@backstage/ui';
+
+
+ Hello World
+
+;
+```
+
+## Next steps
+
+Now that you have the basics down, you can start building your plugin using the new design system.
+Please familiarise yourself first with our theming principles. This will help you understand the core concepts of the design system.
+If you have any questions, please reach out to us on [Discord](https://discord.gg/MUpMjP2).
diff --git a/docs-ui/src/app/layout.module.css b/docs-ui/src/app/layout.module.css
new file mode 100644
index 0000000000..7399fc2485
--- /dev/null
+++ b/docs-ui/src/app/layout.module.css
@@ -0,0 +1,28 @@
+.container {
+ position: relative;
+ z-index: 20;
+ width: calc(100% - 64px);
+ margin-inline: 0 16px;
+ margin-left: 32px;
+ margin-right: 32px;
+ margin-top: 112px;
+ margin-bottom: 48px;
+ padding-inline: 40px;
+ padding-block: 48px;
+ background-color: var(--panel);
+ border-radius: 0.5rem;
+}
+
+.content {
+ width: 100%;
+ max-width: 960px;
+ margin: 0 auto;
+}
+
+@media (min-width: 768px) {
+ .container {
+ width: calc(100% - 332px - 40px);
+ margin-left: 332px;
+ margin-right: 40px;
+ }
+}
diff --git a/docs-ui/src/app/layout.tsx b/docs-ui/src/app/layout.tsx
new file mode 100644
index 0000000000..d197112431
--- /dev/null
+++ b/docs-ui/src/app/layout.tsx
@@ -0,0 +1,64 @@
+import type { Metadata } from 'next';
+import { Sidebar } from '../components/Sidebar';
+import { Toolbar } from '@/components/Toolbar';
+import { StickyHeader } from '../components/StickyHeader/StickyHeader';
+import { Providers } from './providers';
+import { CustomTheme } from '@/components/CustomTheme';
+import styles from './layout.module.css';
+
+import '../css/globals.css';
+import '/public/theme-backstage.css';
+import '/public/theme-spotify.css';
+
+export const metadata: Metadata = {
+ title: 'Backstage UI',
+ description: 'UI library for Backstage',
+ metadataBase: new URL('https://ui.backstage.io'),
+};
+
+async function getLatestPackageVersion(): Promise {
+ try {
+ const response = await fetch('https://registry.npmjs.org/@backstage/ui', {
+ next: { revalidate: 3600 }, // Cache for 1 hour
+ });
+
+ if (!response.ok) {
+ throw new Error('Failed to fetch package info');
+ }
+
+ const data = await response.json();
+ return data['dist-tags']?.latest;
+ } catch (error) {
+ console.error('Error fetching package version:', error);
+ return '0.0.0';
+ }
+}
+
+export default async function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ const packageVersion = await getLatestPackageVersion();
+
+ return (
+
+
+
+
+
+
+
+
{children}
+
+
+
+
+
+ );
+}
diff --git a/canon-docs/src/app/(docs)/theme/layout/page.mdx b/docs-ui/src/app/layout/page.mdx
similarity index 94%
rename from canon-docs/src/app/(docs)/theme/layout/page.mdx
rename to docs-ui/src/app/layout/page.mdx
index b069082b04..3c3b998490 100644
--- a/canon-docs/src/app/(docs)/theme/layout/page.mdx
+++ b/docs-ui/src/app/layout/page.mdx
@@ -3,7 +3,7 @@ import { CodeBlock } from '@/components/CodeBlock';
# Layout
-Canon is made for extensibility. We built this library to make it easy for any
+Backstage UI is made for extensibility. We built this library to make it easy for any
Backstage plugin creator to be able to build their ideas at speed ensuring
consistency across the rest of your ecosystem. Each component is designed to
be editable to match your need but sometimes you want to have more control
diff --git a/docs-ui/src/app/opengraph-image.jpg b/docs-ui/src/app/opengraph-image.jpg
new file mode 100644
index 0000000000..86546a32ee
Binary files /dev/null and b/docs-ui/src/app/opengraph-image.jpg differ
diff --git a/docs-ui/src/app/page.mdx b/docs-ui/src/app/page.mdx
new file mode 100644
index 0000000000..f31cf4524e
--- /dev/null
+++ b/docs-ui/src/app/page.mdx
@@ -0,0 +1,174 @@
+import { ComponentCards, ComponentCard } from '@/components/ComponentCards';
+
+## Welcome to Backstage UI, the new design library for Backstage plugins.
+
+This project is still under active development but we will make sure to document
+the API as we go. We are aiming to improve the general UI of Backstage and
+plugins across Backstage. This new library will take time to build but we are
+building it incrementally with not conflict with the existing theming system.
+
+### Actions
+
+
+
+
+
+
+
+
+### Layout
+
+
+
+
+
+
+
+
+
+
+### Selection and inputs
+
+
+
+
+
+
+
+
+
+
+### Navigation
+
+
+
+
+
+
+
+
+### Images and icons
+
+
+
+
+
+
+### Feedback indicators
+
+
+
+
+
+
+### Typography
+
+
+
+
+
+## Support
+
+Now that you have the basics down, you can start building your plugin using the new design system.
+Please familiarise yourself first with our theming principles. This will help you understand the core concepts of the design system.
+If you have any questions, please reach out to us on [Discord](https://discord.gg/MUpMjP2).
diff --git a/canon-docs/src/app/providers.tsx b/docs-ui/src/app/providers.tsx
similarity index 100%
rename from canon-docs/src/app/providers.tsx
rename to docs-ui/src/app/providers.tsx
diff --git a/canon-docs/src/app/(docs)/theme/responsive/page.mdx b/docs-ui/src/app/responsive/page.mdx
similarity index 94%
rename from canon-docs/src/app/(docs)/theme/responsive/page.mdx
rename to docs-ui/src/app/responsive/page.mdx
index 7eb4411333..9d37b1329f 100644
--- a/canon-docs/src/app/(docs)/theme/responsive/page.mdx
+++ b/docs-ui/src/app/responsive/page.mdx
@@ -4,7 +4,7 @@ import { CodeBlock } from '@/components/CodeBlock';
# Responsive
-Canon is built on a responsive design system, meaning that the components are
+Backstage UI is built on a responsive design system, meaning that the components are
designed to adapt to different screen sizes. By default we offer a set of
breakpoints that you can use to create responsive components.
@@ -90,7 +90,7 @@ breakpoints that you can use to create responsive components.
## Responsive components
-Canon components are designed to be responsive, meaning that they will adapt
+Backstage UI components are designed to be responsive, meaning that they will adapt
to different screen sizes. Not every component is responsive, but the ones
that are will have a prop to control the responsive behavior.
diff --git a/canon-docs/src/app/(docs)/theme/theming/page.mdx b/docs-ui/src/app/theming/page.mdx
similarity index 73%
rename from canon-docs/src/app/(docs)/theme/theming/page.mdx
rename to docs-ui/src/app/theming/page.mdx
index ed7f801db0..73275020bc 100644
--- a/canon-docs/src/app/(docs)/theme/theming/page.mdx
+++ b/docs-ui/src/app/theming/page.mdx
@@ -5,7 +5,7 @@ import { customTheme } from '@/snippets/code-snippets';
# Theming
-Canon's theming is built entirely on CSS, without relying on any CSS-in-JS libraries.
+Backstage UI theming is built entirely on CSS, without relying on any CSS-in-JS libraries.
At its core, it provides a solid default theme that is easily customizable using a
comprehensive set of CSS variables. Additionally, it enables anyone to adapt the design
to their specific needs. Each component comes with fixed class names, making customization
@@ -13,8 +13,8 @@ even more straightforward.
## Light & Dark modes
-By default, Canon supports both light and dark modes using the `data-theme` attribute.
-The light theme is applied by default if no `data-theme` attribute is specified. To create
+By default, Backstage UI supports both light and dark modes using the `data-theme-mode` attribute.
+The light theme is applied by default if no `data-theme-mode` attribute is specified. To create
a custom theme, you'll need to define both light and dark modes as outlined below. If
only one mode is defined, the other will fall back to the default theme.
@@ -31,7 +31,7 @@ Here's an example of how your theme.css file should look like:
## CSS class name structure
-All Canon components come with a set of CSS classes that you can use to style them. To make it
+All Backstage UI components come with a set of CSS classes that you can use to style them. To make it
easier to identify the class name you can use, we use a specific structure for the class names.
-Every component has a unique prefix `.canon-` followed by the component name. Component props
+Every component has a unique prefix `.bui-` followed by the component name. Component props
are represented using the `data-` attribute. That way, class names are easily identifiable.
## Available CSS variables
@@ -58,7 +58,7 @@ These colors are used for special purposes like ring, scrollbar, ...
- --canon-black
+ --bui-black
Pure black color. This one should be the same in light and dark themes.
@@ -66,7 +66,7 @@ These colors are used for special purposes like ring, scrollbar, ...
- --canon-white
+ --bui-white
Pure white color. This one should be the same in light and dark themes.
@@ -74,49 +74,49 @@ These colors are used for special purposes like ring, scrollbar, ...
- --canon-gray-1
+ --bui-gray-1You can use these mostly for backgrounds colors.
- --canon-gray-2
+ --bui-gray-2You can use these mostly for backgrounds colors.
- --canon-gray-3
+ --bui-gray-3You can use these mostly for backgrounds colors.
- --canon-gray-4
+ --bui-gray-4You can use these mostly for backgrounds colors.
- --canon-gray-5
+ --bui-gray-5You can use these mostly for backgrounds colors.
- --canon-gray-6
+ --bui-gray-6You can use these mostly for backgrounds colors.
- --canon-gray-7
+ --bui-gray-7You can use these mostly for backgrounds colors.
- --canon-gray-8
+ --bui-gray-8You can use these mostly for backgrounds colors.
@@ -126,7 +126,7 @@ These colors are used for special purposes like ring, scrollbar, ...
### Core background colors
These colors are used for the background of your application. We are mostly using for now a
-single elevated background for panels. `--canon-bg` should mostly use as the main background
+single elevated background for panels. `--bui-bg` should mostly use as the main background
color of your app.
@@ -139,85 +139,85 @@ color of your app.
- --canon-bg
+ --bui-bgThe background color of your Backstage instance.
- --canon-bg-surface-1
+ --bui-bg-surface-1Use for any panels or elevated surfaces.
- --canon-bg-surface-2
+ --bui-bg-surface-2Use for any panels or elevated surfaces.
- --canon-bg-solid
+ --bui-bg-solidUsed for solid background colors.
- --canon-bg-solid-hover
+ --bui-bg-solid-hoverUsed for solid background colors when hovered.
- --canon-bg-solid-pressed
+ --bui-bg-solid-pressedUsed for solid background colors when pressed.
- --canon-bg-solid-disabled
+ --bui-bg-solid-disabledUsed for solid background colors when disabled.
- --canon-bg-tint
+ --bui-bg-tintUsed for tint background colors.
- --canon-bg-tint-hover
+ --bui-bg-tint-hoverUsed for tint background colors when hovered.
- --canon-bg-tint-focus
+ --bui-bg-tint-focusUsed for tint background colors when active.
- --canon-bg-tint-disabled
+ --bui-bg-tint-disabledUsed for tint background colors when disabled.
- --canon-bg-danger
+ --bui-bg-dangerUsed to show errors information.
- --canon-bg-warning
+ --bui-bg-warningUsed to show warnings information.
- --canon-bg-success
+ --bui-bg-successUsed to show success information.
@@ -240,7 +240,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-primary
+ --bui-fg-primary
It should be used on top of main background surfaces.
@@ -248,7 +248,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-secondary
+ --bui-fg-secondary
It should be used on top of main background surfaces.
@@ -256,7 +256,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-link
+ --bui-fg-link
It should be used on top of main background surfaces.
@@ -264,7 +264,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-link-hover
+ --bui-fg-link-hover
It should be used on top of main background surfaces.
@@ -272,7 +272,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-disabled
+ --bui-fg-disabled
It should be used on top of main background surfaces.
@@ -280,7 +280,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-solid
+ --bui-fg-solid
It should be used on top of solid background colors.
@@ -288,7 +288,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-tint
+ --bui-fg-tint
It should be used on top of tint background colors.
@@ -296,7 +296,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-tint-disabled
+ --bui-fg-tint-disabled
It should be used on top of tint background colors when disabled.
@@ -304,7 +304,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-danger
+ --bui-fg-danger
It should be used on top of danger background colors.
@@ -312,7 +312,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-warning
+ --bui-fg-warning
It should be used on top of warning background colors.
@@ -320,7 +320,7 @@ are prefixed with `fg` to make it easier to identify.
- --canon-fg-success
+ --bui-fg-success
It should be used on top of success background colors.
@@ -344,15 +344,13 @@ low contrast to help as a separator with the different background colors.
- --canon-border
-
-
- It should be used on top of `--canon-bg-surface-1`.
+ --bui-border
+ It should be used on top of `--bui-bg-surface-1`.
- --canon-border-hover
+ --bui-border-hover
Used when the component is interactive and hovered.
@@ -360,7 +358,7 @@ low contrast to help as a separator with the different background colors.
- --canon-border-pressed
+ --bui-border-pressed
Used when the component is interactive and focused.
@@ -368,27 +366,27 @@ low contrast to help as a separator with the different background colors.
- --canon-border-disabled
+ --bui-border-disabledUsed when the component is disabled.
- --canon-border-danger
+ --bui-border-danger
- It should be used on top of `--canon-bg-danger`.
+ It should be used on top of `--bui-bg-danger`.
- --canon-border-warning
+ --bui-border-warning
- It should be used on top of `--canon-bg-warning`.
+ It should be used on top of `--bui-bg-warning`.
- --canon-border-success
+ --bui-border-success
- It should be used on top of `--canon-bg-success`.
+ It should be used on top of `--bui-bg-success`.
@@ -407,19 +405,19 @@ These colors are used for special purposes like ring, scrollbar, ...
- --canon-ring
+ --bui-ringThe color of the ring.
- --canon-scrollbar
+ --bui-scrollbarThe color of the scrollbar.
- --canon-scrollbar-thumb
+ --bui-scrollbar-thumbThe color of the scrollbar thumb.
@@ -428,7 +426,7 @@ These colors are used for special purposes like ring, scrollbar, ...
### Font families
-We have two fonts that we use across Canon. The first one is the sans-serif
+We have two fonts that we use across Backstage UI. The first one is the sans-serif
font that we use for the body of the application. The second one is the
monospace font that we use for code blocks and tables.
@@ -442,13 +440,13 @@ monospace font that we use for code blocks and tables.
- --canon-font-regular
+ --bui-font-regularThe sans-serif font for the theme.
- --canon-font-mono
+ --bui-font-monoThe monospace font for the theme.
@@ -457,7 +455,7 @@ monospace font that we use for code blocks and tables.
### Font weights
-We have two font weights that we use across Canon. Regular or Bold.
+We have two font weights that we use across Backstage UI. Regular or Bold.
@@ -469,13 +467,13 @@ We have two font weights that we use across Canon. Regular or Bold.
- --canon-font-weight-regular
+ --bui-font-weight-regularThe regular font weight for the theme.
- --canon-font-weight-bold
+ --bui-font-weight-boldThe bold font weight for the theme.
@@ -484,12 +482,12 @@ We have two font weights that we use across Canon. Regular or Bold.
### Spacing
-We built a spacing system based on a single value `--canon-space`. This value is
+We built a spacing system based on a single value `--bui-space`. This value is
used to calculate the spacing for all the components. By default if you would like to
increase or decrease the spacing between your components you can do it simply by updating
-`--canon-space` and it will apply to all spacing values.
+`--bui-space` and it will apply to all spacing values.
-`--canon-space` is not used directly in any components but serve as an easy way to
+`--bui-space` is not used directly in any components but serve as an easy way to
calculate the other values.
@@ -502,7 +500,7 @@ calculate the other values.
- --canon-space
+ --bui-space
The base unit for the spacing system. Default value is `0.25rem`.
@@ -524,99 +522,99 @@ tokens for pretty much each spacing properties like padding, margin, gaps, ...
- --canon-space-0_5
+ --bui-space-0_5
- Base unit (`--canon-space`) times 0.5.
+ Base unit (`--bui-space`) times 0.5.
- --canon-space-1
+ --bui-space-1
- Base unit (`--canon-space`).
+ Base unit (`--bui-space`).
- --canon-space-1_5
+ --bui-space-1_5
- Base unit (`--canon-space`) times 1.5.
+ Base unit (`--bui-space`) times 1.5.
- --canon-space-2
+ --bui-space-2
- Base unit (`--canon-space`) times 2.
+ Base unit (`--bui-space`) times 2.
- --canon-space-3
+ --bui-space-3
- Base unit (`--canon-space`) times 3.
+ Base unit (`--bui-space`) times 3.
- --canon-space-4
+ --bui-space-4
- Base unit (`--canon-space`) times 4.
+ Base unit (`--bui-space`) times 4.
- --canon-space-5
+ --bui-space-5
- Base unit (`--canon-space`) times 5.
+ Base unit (`--bui-space`) times 5.
- --canon-space-6
+ --bui-space-6
- Base unit (`--canon-space`) times 6.
+ Base unit (`--bui-space`) times 6.
- --canon-space-7
+ --bui-space-7
- Base unit (`--canon-space`) times 7.
+ Base unit (`--bui-space`) times 7.
- --canon-space-8
+ --bui-space-8
- Base unit (`--canon-space`) times 8.
+ Base unit (`--bui-space`) times 8.
- --canon-space-9
+ --bui-space-9
- Base unit (`--canon-space`) times 9.
+ Base unit (`--bui-space`) times 9.
- --canon-space-10
+ --bui-space-10
- Base unit (`--canon-space`) times 10.
+ Base unit (`--bui-space`) times 10.
- --canon-space-11
+ --bui-space-11
- Base unit (`--canon-space`) times 11.
+ Base unit (`--bui-space`) times 11.
- --canon-space-12
+ --bui-space-12
- Base unit (`--canon-space`) times 12.
+ Base unit (`--bui-space`) times 12.
- --canon-space-13
+ --bui-space-13
- Base unit (`--canon-space`) times 13.
+ Base unit (`--bui-space`) times 13.
- --canon-space-14
+ --bui-space-14
- Base unit (`--canon-space`) times 14.
+ Base unit (`--bui-space`) times 14.
@@ -635,7 +633,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-1
+ --bui-radius-1
The radius of the component. Default value is `0.125rem`.
@@ -643,7 +641,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-2
+ --bui-radius-2
The radius of the component. Default value is `0.25rem`.
@@ -651,7 +649,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-3
+ --bui-radius-3
The radius of the component. Default value is `0.5rem`.
@@ -659,7 +657,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-4
+ --bui-radius-4
The radius of the component. Default value is `0.75rem`.
@@ -667,7 +665,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-5
+ --bui-radius-5
The radius of the component. Default value is `1rem`.
@@ -675,7 +673,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-6
+ --bui-radius-6
The radius of the component. Default value is `1.25rem`.
@@ -683,7 +681,7 @@ We use a radius system to make sure that the components have a consistent look a
- --canon-radius-full
+ --bui-radius-full
The radius of the component. Default value is `9999px`.
diff --git a/canon-docs/src/components/Banner/Banner.tsx b/docs-ui/src/components/Banner/Banner.tsx
similarity index 62%
rename from canon-docs/src/components/Banner/Banner.tsx
rename to docs-ui/src/components/Banner/Banner.tsx
index 0f055d6c92..9ad2ff0ced 100644
--- a/canon-docs/src/components/Banner/Banner.tsx
+++ b/docs-ui/src/components/Banner/Banner.tsx
@@ -1,18 +1,3 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
import styles from './styles.module.css';
export const Banner = ({
diff --git a/docs-ui/src/components/Banner/index.ts b/docs-ui/src/components/Banner/index.ts
new file mode 100644
index 0000000000..f4930c0719
--- /dev/null
+++ b/docs-ui/src/components/Banner/index.ts
@@ -0,0 +1 @@
+export { Banner } from './Banner';
diff --git a/canon-docs/src/components/Banner/styles.module.css b/docs-ui/src/components/Banner/styles.module.css
similarity index 100%
rename from canon-docs/src/components/Banner/styles.module.css
rename to docs-ui/src/components/Banner/styles.module.css
diff --git a/docs-ui/src/components/Changelog/index.tsx b/docs-ui/src/components/Changelog/index.tsx
new file mode 100644
index 0000000000..224e23d668
--- /dev/null
+++ b/docs-ui/src/components/Changelog/index.tsx
@@ -0,0 +1,75 @@
+import { changelog } from '@/utils/changelog';
+import { MDXRemote } from 'next-mdx-remote-client/rsc';
+import { formattedMDXComponents } from '@/mdx-components';
+
+export function Changelog() {
+ // Group changelog entries by version
+ const groupedChangelog = changelog.reduce((acc, entry) => {
+ if (!acc[entry.version]) {
+ acc[entry.version] = [];
+ }
+ acc[entry.version].push(entry);
+ return acc;
+ }, {} as Record);
+
+ // Sort versions in descending order
+ const sortedVersions = Object.keys(groupedChangelog).sort((a, b) =>
+ b.localeCompare(a),
+ );
+
+ const content = sortedVersions
+ .map(version => {
+ const entries = groupedChangelog[version];
+
+ // Group entries by bump type
+ const groupedByBump = entries.reduce((acc, entry) => {
+ const bumpType = entry.type || 'other';
+ if (!acc[bumpType]) {
+ acc[bumpType] = [];
+ }
+ acc[bumpType].push(entry);
+ return acc;
+ }, {} as Record);
+
+ // Define the order of bump types
+ const bumpOrder = ['breaking', 'new', 'fix', 'other'];
+
+ const bumpSections = bumpOrder
+ .filter(bumpType => groupedByBump[bumpType]?.length > 0)
+ .map(bumpType => {
+ const bumpEntries = groupedByBump[bumpType];
+ let sectionTitle = 'Other Changes';
+ if (bumpType === 'breaking') {
+ sectionTitle = 'Breaking Changes';
+ } else if (bumpType === 'new') {
+ sectionTitle = 'New Features';
+ } else if (bumpType === 'fix') {
+ sectionTitle = 'Bug Fixes';
+ }
+
+ return `### ${sectionTitle}
+
+ ${bumpEntries
+ .map(e => {
+ const prs =
+ e.prs.length > 0 &&
+ e.prs
+ .map(
+ pr =>
+ `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`,
+ )
+ .join(', ');
+ return `- ${e.description} ${prs}`;
+ })
+ .join('\n')}`;
+ })
+ .join('\n\n');
+
+ return `## Version ${version}
+
+ ${bumpSections}`;
+ })
+ .join('\n');
+
+ return ;
+}
diff --git a/docs-ui/src/components/ChangelogComponent/index.tsx b/docs-ui/src/components/ChangelogComponent/index.tsx
new file mode 100644
index 0000000000..f8832b0731
--- /dev/null
+++ b/docs-ui/src/components/ChangelogComponent/index.tsx
@@ -0,0 +1,32 @@
+import { changelog } from '@/utils/changelog';
+import { MDXRemote } from 'next-mdx-remote-client/rsc';
+import { formattedMDXComponents } from '@/mdx-components';
+import type { Component } from '@/utils/changelog';
+
+export const ChangelogComponent = ({ component }: { component: Component }) => {
+ const componentChangelog = changelog.filter(c =>
+ c.components.includes(component),
+ );
+
+ return (
+ {
+ const prs =
+ change.prs.length > 0 &&
+ change.prs
+ .map(
+ pr =>
+ `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`,
+ )
+ .join(', ');
+ return `- \`${change.version}\` - ${change.description} ${prs}`;
+ })
+ .join('\n')}`}
+ />
+ );
+};
diff --git a/docs-ui/src/components/Chip/Chip.tsx b/docs-ui/src/components/Chip/Chip.tsx
new file mode 100644
index 0000000000..b348b46c32
--- /dev/null
+++ b/docs-ui/src/components/Chip/Chip.tsx
@@ -0,0 +1,16 @@
+import { ReactNode } from 'react';
+import styles from './styles.module.css';
+
+export const Chip = ({
+ children,
+ head = false,
+}: {
+ children: ReactNode;
+ head?: boolean;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/docs-ui/src/components/Chip/index.ts b/docs-ui/src/components/Chip/index.ts
new file mode 100644
index 0000000000..63314f5e37
--- /dev/null
+++ b/docs-ui/src/components/Chip/index.ts
@@ -0,0 +1 @@
+export { Chip } from './Chip';
diff --git a/docs-ui/src/components/Chip/styles.module.css b/docs-ui/src/components/Chip/styles.module.css
new file mode 100644
index 0000000000..01ee29311d
--- /dev/null
+++ b/docs-ui/src/components/Chip/styles.module.css
@@ -0,0 +1,26 @@
+.chip {
+ display: inline-flex;
+ align-items: center;
+ font-family: monospace;
+ font-size: 13px;
+ border-radius: 6px;
+ padding: 0px 8px;
+ height: 24px;
+ margin-right: 4px;
+ background-color: #f0f0f0;
+ color: #5d5d5d;
+}
+
+.head {
+ background-color: #eaf2fd;
+ color: #2563eb;
+}
+
+[data-theme-mode='dark'] .chip {
+ background-color: #2c2c2c;
+ color: #fff;
+}
+
+[data-theme-mode='dark'] .chip.head {
+ background-color: #33405b;
+}
diff --git a/canon-docs/src/components/CodeBlock/client.tsx b/docs-ui/src/components/CodeBlock/client.tsx
similarity index 75%
rename from canon-docs/src/components/CodeBlock/client.tsx
rename to docs-ui/src/components/CodeBlock/client.tsx
index 27f5bc1a02..b4ee98f2f3 100644
--- a/canon-docs/src/components/CodeBlock/client.tsx
+++ b/docs-ui/src/components/CodeBlock/client.tsx
@@ -1,8 +1,9 @@
'use client';
import { CodeBlockProps } from '.';
-import { Text } from '../../../../packages/canon';
+import { Text } from '@backstage/ui';
import styles from './styles.module.css';
+import parse from 'html-react-parser';
export const CodeBlockClient = ({
out,
@@ -18,7 +19,7 @@ export const CodeBlockClient = ({
{title}
diff --git a/docs-ui/src/components/LayoutComponents/index.ts b/docs-ui/src/components/LayoutComponents/index.ts
new file mode 100644
index 0000000000..8efb793bbd
--- /dev/null
+++ b/docs-ui/src/components/LayoutComponents/index.ts
@@ -0,0 +1 @@
+export { LayoutComponents } from './LayoutComponents';
diff --git a/canon-docs/src/components/LayoutComponents/svgs/box.tsx b/docs-ui/src/components/LayoutComponents/svgs/box.tsx
similarity index 56%
rename from canon-docs/src/components/LayoutComponents/svgs/box.tsx
rename to docs-ui/src/components/LayoutComponents/svgs/box.tsx
index b7f6a097e5..ce1a746f32 100644
--- a/canon-docs/src/components/LayoutComponents/svgs/box.tsx
+++ b/docs-ui/src/components/LayoutComponents/svgs/box.tsx
@@ -1,18 +1,3 @@
-/*
- * Copyright 2024 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
export const BoxSvg = () => {
return (