diff --git a/.changeset/brave-teeth-reply.md b/.changeset/brave-teeth-reply.md
new file mode 100644
index 0000000000..8a500692a7
--- /dev/null
+++ b/.changeset/brave-teeth-reply.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Internal refactor to remove remnants of the old backend system
diff --git a/.changeset/brown-falcons-own.md b/.changeset/brown-falcons-own.md
new file mode 100644
index 0000000000..e38f3bbfbc
--- /dev/null
+++ b/.changeset/brown-falcons-own.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-pg': patch
+---
+
+Truncate long docs to fit PG index size limit
diff --git a/.changeset/brown-symbols-create.md b/.changeset/brown-symbols-create.md
new file mode 100644
index 0000000000..d4a62b1280
--- /dev/null
+++ b/.changeset/brown-symbols-create.md
@@ -0,0 +1,5 @@
+---
+'@techdocs/cli': minor
+---
+
+Techdocs CLI serve supports automatic refresh, relying on `mkdocs` `watch` feature.
diff --git a/.changeset/brown-turkeys-send.md b/.changeset/brown-turkeys-send.md
new file mode 100644
index 0000000000..87a1d03b01
--- /dev/null
+++ b/.changeset/brown-turkeys-send.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Log before provider-orphaning eviction happens
diff --git a/.changeset/bui-themer-bui-palette-additions.md b/.changeset/bui-themer-bui-palette-additions.md
new file mode 100644
index 0000000000..645641b787
--- /dev/null
+++ b/.changeset/bui-themer-bui-palette-additions.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-mui-to-bui': minor
+---
+
+This is the first release of the Material UI to Backstage UI migration helper plugin. It adds a new page at `/mui-to-bui` that converts an existing MUI v5 theme into Backstage UI (BUI) CSS variables, with live preview and copy/download.
diff --git a/.changeset/calm-trains-tie.md b/.changeset/calm-trains-tie.md
new file mode 100644
index 0000000000..8c399ba123
--- /dev/null
+++ b/.changeset/calm-trains-tie.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-defaults': minor
+---
+
+implement support for direct url for AzureBlobStorageUrlReader search function
diff --git a/.changeset/clever-papers-watch.md b/.changeset/clever-papers-watch.md
new file mode 100644
index 0000000000..831d4c3455
--- /dev/null
+++ b/.changeset/clever-papers-watch.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+remove default selection of tab
diff --git a/.changeset/create-app-1758639549.md b/.changeset/create-app-1758639549.md
new file mode 100644
index 0000000000..b50d431d4b
--- /dev/null
+++ b/.changeset/create-app-1758639549.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Bumped create-app version.
diff --git a/.changeset/create-app-1758718573.md b/.changeset/create-app-1758718573.md
new file mode 100644
index 0000000000..b50d431d4b
--- /dev/null
+++ b/.changeset/create-app-1758718573.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Bumped create-app version.
diff --git a/.changeset/create-app-1759243273.md b/.changeset/create-app-1759243273.md
new file mode 100644
index 0000000000..b50d431d4b
--- /dev/null
+++ b/.changeset/create-app-1759243273.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Bumped create-app version.
diff --git a/.changeset/create-app-1759849206.md b/.changeset/create-app-1759849206.md
new file mode 100644
index 0000000000..b50d431d4b
--- /dev/null
+++ b/.changeset/create-app-1759849206.md
@@ -0,0 +1,5 @@
+---
+'@backstage/create-app': patch
+---
+
+Bumped create-app version.
diff --git a/.changeset/cuddly-mugs-act.md b/.changeset/cuddly-mugs-act.md
new file mode 100644
index 0000000000..1b939d8196
--- /dev/null
+++ b/.changeset/cuddly-mugs-act.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-app-api': patch
+---
+
+Moved up registration of unhandled rejections and errors listeners to be done as early as possible, avoiding flakiness in backend startups and instead always logging these failures rather than sometimes crashing the process.
diff --git a/.changeset/curvy-bobcats-melt.md b/.changeset/curvy-bobcats-melt.md
new file mode 100644
index 0000000000..a9a5d58e5c
--- /dev/null
+++ b/.changeset/curvy-bobcats-melt.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-react': patch
+---
+
+Don't change loading to false until we've actually got some log state
diff --git a/.changeset/dependabot-eaf5987.md b/.changeset/dependabot-eaf5987.md
new file mode 100644
index 0000000000..bf1475613a
--- /dev/null
+++ b/.changeset/dependabot-eaf5987.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-notifications-backend-module-email': patch
+---
+
+chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7
diff --git a/.changeset/famous-loops-tickle.md b/.changeset/famous-loops-tickle.md
new file mode 100644
index 0000000000..ae8c9d80ee
--- /dev/null
+++ b/.changeset/famous-loops-tickle.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes-react': patch
+---
+
+The configmaps added to be rendered
diff --git a/.changeset/fast-heads-brake.md b/.changeset/fast-heads-brake.md
new file mode 100644
index 0000000000..bc9f525520
--- /dev/null
+++ b/.changeset/fast-heads-brake.md
@@ -0,0 +1,25 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Moved catalog processor and provider disabling and priorities under own config objects.
+
+This is due to issue with some existing providers, such as GitHub, using array syntax for the provider configuration.
+
+The new config format is not backwards compatible, so users will need to update their config files. The new format
+is as follows:
+
+```yaml
+catalog:
+ providerOptions:
+ providerA:
+ disabled: false
+ providerB:
+ disabled: true
+ processorOptions:
+ processorA:
+ disabled: false
+ priority: 10
+ processorB:
+ disabled: true
+```
diff --git a/.changeset/few-weeks-create.md b/.changeset/few-weeks-create.md
new file mode 100644
index 0000000000..c9de7cb4be
--- /dev/null
+++ b/.changeset/few-weeks-create.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Making href mandatory in tabs that are part of a Header component
diff --git a/.changeset/five-olives-bet.md b/.changeset/five-olives-bet.md
new file mode 100644
index 0000000000..8623e780b5
--- /dev/null
+++ b/.changeset/five-olives-bet.md
@@ -0,0 +1,5 @@
+---
+'@backstage/integration': patch
+---
+
+remove host from azure blob storage integration type
diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md
new file mode 100644
index 0000000000..bb075ce910
--- /dev/null
+++ b/.changeset/flat-peas-run.md
@@ -0,0 +1,6 @@
+---
+'@backstage/core-components': patch
+'@backstage/plugin-catalog-graph': patch
+---
+
+Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges.
diff --git a/.changeset/forty-crabs-travel.md b/.changeset/forty-crabs-travel.md
new file mode 100644
index 0000000000..83e281aa51
--- /dev/null
+++ b/.changeset/forty-crabs-travel.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-signals': patch
+---
+
+Remove `app-root-element:signals/signals-display` which was not doing anything useful
diff --git a/.changeset/full-chefs-roll.md b/.changeset/full-chefs-roll.md
new file mode 100644
index 0000000000..0a13f116ec
--- /dev/null
+++ b/.changeset/full-chefs-roll.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incompatible with Jest 30.
diff --git a/.changeset/fuzzy-trams-kick.md b/.changeset/fuzzy-trams-kick.md
new file mode 100644
index 0000000000..b433eac803
--- /dev/null
+++ b/.changeset/fuzzy-trams-kick.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-home': patch
+---
+
+fix(home): correct `clearAll` logic to properly handle `deletable` flag
diff --git a/.changeset/giant-weeks-jump.md b/.changeset/giant-weeks-jump.md
new file mode 100644
index 0000000000..1b11bd1490
--- /dev/null
+++ b/.changeset/giant-weeks-jump.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-org': patch
+---
+
+Add `initialRelationAggregation` and `showAggregateMembersToggle` options to `EntityMembersListCard` as well to `EntityOwnershipCard`
diff --git a/.changeset/heavy-cooks-divide.md b/.changeset/heavy-cooks-divide.md
new file mode 100644
index 0000000000..181cd01075
--- /dev/null
+++ b/.changeset/heavy-cooks-divide.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-notifications-backend-module-slack': minor
+---
+
+Adds username as optional config in order to send Slack notifications with a specific username in the case when using one Slack App for more than just Backstage.
diff --git a/.changeset/itchy-falcons-leave.md b/.changeset/itchy-falcons-leave.md
new file mode 100644
index 0000000000..07188e08c5
--- /dev/null
+++ b/.changeset/itchy-falcons-leave.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend-module-gcp': patch
+---
+
+Fix documentation strings to mention GCP instead of Azure
diff --git a/.changeset/legal-eagles-jog.md b/.changeset/legal-eagles-jog.md
new file mode 100644
index 0000000000..5b520af91f
--- /dev/null
+++ b/.changeset/legal-eagles-jog.md
@@ -0,0 +1,18 @@
+---
+'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch
+'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
+'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
+'@backstage/plugin-scaffolder-backend-module-notifications': patch
+'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
+'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
+'@backstage/plugin-scaffolder-backend-module-gerrit': patch
+'@backstage/plugin-scaffolder-backend-module-github': patch
+'@backstage/plugin-scaffolder-backend-module-gitlab': patch
+'@backstage/plugin-scaffolder-backend-module-sentry': patch
+'@backstage/plugin-scaffolder-backend-module-yeoman': patch
+'@backstage/plugin-scaffolder-backend-module-azure': patch
+'@backstage/plugin-scaffolder-backend-module-gitea': patch
+'@backstage/plugin-scaffolder-backend-module-rails': patch
+---
+
+Updating import for the `scaffolderActionsExtensionPoint` to be the main export
diff --git a/.changeset/modern-pugs-appear.md b/.changeset/modern-pugs-appear.md
new file mode 100644
index 0000000000..8b502fb52d
--- /dev/null
+++ b/.changeset/modern-pugs-appear.md
@@ -0,0 +1,19 @@
+---
+'@backstage/cli': patch
+---
+
+Added a new `--entrypoint` option to the `package start` command, which allows you to specify a custom entry directory/file for development applications. This is particularly useful when maintaining separate dev apps for different versions of your plugin (e.g., stable and alpha).
+
+**Example usage:**
+
+Consider the following plugin dev folder structure:
+
+```
+dev/
+ index.tsx
+ alpha/
+ index.ts
+```
+
+- The default `yarn package start` command uses the `dev/` folder as the entry point and executes `dev/index.tsx` file;
+- Running `yarn package start --entrypoint dev/alpha` will instead use `dev/alpha/` as the entry point and execute `dev/alpha/index.ts` file.
diff --git a/.changeset/nasty-moose-rescue.md b/.changeset/nasty-moose-rescue.md
new file mode 100644
index 0000000000..875c19e9a4
--- /dev/null
+++ b/.changeset/nasty-moose-rescue.md
@@ -0,0 +1,5 @@
+---
+'@backstage/frontend-plugin-api': patch
+---
+
+Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but available for use for other cases too.
diff --git a/.changeset/nice-readers-judge.md b/.changeset/nice-readers-judge.md
new file mode 100644
index 0000000000..a70ee8e501
--- /dev/null
+++ b/.changeset/nice-readers-judge.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-pg': patch
+---
+
+Added the < character to the query filter regexp
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 12e4285e7c..458c97896e 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -203,7 +203,74 @@
"@backstage/plugin-techdocs-react": "1.3.3",
"@backstage/plugin-user-settings": "0.8.26",
"@backstage/plugin-user-settings-backend": "0.3.6",
- "@backstage/plugin-user-settings-common": "0.0.1"
+ "@backstage/plugin-user-settings-common": "0.0.1",
+ "@backstage/plugin-mui-to-bui": "0.1.0"
},
- "changesets": []
+ "changesets": [
+ "brave-teeth-reply",
+ "brown-falcons-own",
+ "brown-turkeys-send",
+ "bui-themer-bui-palette-additions",
+ "calm-trains-tie",
+ "clever-papers-watch",
+ "cold-coats-show",
+ "cool-baboons-count",
+ "create-app-1758639549",
+ "create-app-1758718573",
+ "create-app-1759243273",
+ "create-app-1759849206",
+ "cuddly-mugs-act",
+ "curvy-bobcats-melt",
+ "dependabot-eaf5987",
+ "eager-toes-start",
+ "famous-loops-tickle",
+ "fast-heads-brake",
+ "fast-queens-guess",
+ "few-weeks-create",
+ "five-olives-bet",
+ "flat-peas-run",
+ "forty-crabs-travel",
+ "full-chefs-roll",
+ "fuzzy-trams-kick",
+ "giant-weeks-jump",
+ "heavy-cooks-divide",
+ "hungry-crews-fetch",
+ "itchy-falcons-leave",
+ "kind-places-reply",
+ "legal-eagles-jog",
+ "modern-pugs-appear",
+ "moody-singers-deny",
+ "nasty-moose-rescue",
+ "nice-readers-judge",
+ "public-sites-admire",
+ "public-wombats-say",
+ "rare-states-pay",
+ "ready-poems-change",
+ "ready-pots-arrive",
+ "red-dodos-work",
+ "red-times-bet",
+ "sad-women-rule",
+ "salty-words-wash",
+ "shiny-candles-hide",
+ "short-aliens-invite",
+ "silent-mice-play",
+ "six-cooks-battle",
+ "slimy-signs-agree",
+ "solid-bikes-leave",
+ "tame-hairs-smash",
+ "tender-cups-tap",
+ "thin-hoops-bathe",
+ "thirty-rules-press",
+ "tidy-coats-know",
+ "tired-mice-cheer",
+ "tough-clocks-attack",
+ "twelve-guests-sit",
+ "twelve-oranges-grin",
+ "two-emus-like",
+ "unified-theme-attr-stack",
+ "warm-items-look",
+ "wet-spiders-wait",
+ "wide-flies-jog",
+ "yarn-plugin-integration"
+ ]
}
diff --git a/.changeset/public-sites-admire.md b/.changeset/public-sites-admire.md
new file mode 100644
index 0000000000..f5f3304f9f
--- /dev/null
+++ b/.changeset/public-sites-admire.md
@@ -0,0 +1,6 @@
+---
+'@backstage/core-components': patch
+'@backstage/plugin-catalog-graph': patch
+---
+
+Fixed DependencyGraph `svg` size not adapting to the container size
diff --git a/.changeset/public-wombats-say.md b/.changeset/public-wombats-say.md
new file mode 100644
index 0000000000..b8a72e8436
--- /dev/null
+++ b/.changeset/public-wombats-say.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Fixed dependency graph automatically scrolling forever
diff --git a/.changeset/ready-poems-change.md b/.changeset/ready-poems-change.md
new file mode 100644
index 0000000000..fc95ddb99a
--- /dev/null
+++ b/.changeset/ready-poems-change.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-scaffolder-node': minor
+---
+
+**BREAKING** - Marking optional fields as required in the `TaskBroker`, these can be fixed with a no-op `() => void` if you don't want to implement the functions.
+
+- `cancel`, `recoverTasks` and `retry` are the required methods on the `TaskBroker` interface.
+
+**NOTE**: If you're affected by this breaking change, please reach out to us in an issue as we're thinking about completely removing the `TaskBroker` extension point soon and would like to hear your use cases for the upcoming re-architecture of the `scaffolder-backend` plugin.
diff --git a/.changeset/ready-pots-arrive.md b/.changeset/ready-pots-arrive.md
new file mode 100644
index 0000000000..96f13a12ae
--- /dev/null
+++ b/.changeset/ready-pots-arrive.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Add missing `templatingExtensions` option to RouterProps.contextMenu to allow global control across scaffolder pages
diff --git a/.changeset/red-dodos-work.md b/.changeset/red-dodos-work.md
new file mode 100644
index 0000000000..1bc92d2d59
--- /dev/null
+++ b/.changeset/red-dodos-work.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Added new `catalog:validate-entity` action to actions registry.
+
+This action can be used to validate entities against the software catalog.
+This is useful for validating `catalog-info.yaml` file changes locally using the
+Backstage MCP server.
diff --git a/.changeset/red-times-bet.md b/.changeset/red-times-bet.md
new file mode 100644
index 0000000000..29e89fb07f
--- /dev/null
+++ b/.changeset/red-times-bet.md
@@ -0,0 +1,13 @@
+---
+'@backstage/plugin-scaffolder-node': patch
+---
+
+**BREAKING ALPHA**: We've moved the `scaffolderActionsExtensionPoint` from `/alpha` to the main export.
+
+```tsx
+// before
+import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
+
+// after
+import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node';
+```
diff --git a/.changeset/ripe-yaks-brake.md b/.changeset/ripe-yaks-brake.md
new file mode 100644
index 0000000000..3b3097011b
--- /dev/null
+++ b/.changeset/ripe-yaks-brake.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-search-react': patch
+'@backstage/plugin-search': patch
+---
+
+Implemented AbortController request cancellation for overlapping search requests. This change ensures that when users type quickly, previous search requests are properly canceled before new ones start.
diff --git a/.changeset/sad-women-rule.md b/.changeset/sad-women-rule.md
new file mode 100644
index 0000000000..04bbbe1eed
--- /dev/null
+++ b/.changeset/sad-women-rule.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Add react router for internal routing for ButtonLinks
diff --git a/.changeset/salty-words-wash.md b/.changeset/salty-words-wash.md
new file mode 100644
index 0000000000..eec2e85331
--- /dev/null
+++ b/.changeset/salty-words-wash.md
@@ -0,0 +1,11 @@
+---
+'@backstage/backend-defaults': minor
+---
+
+Adds support for configuring server-level HTTP options through the
+`app-config.yaml` file under the `backend.server` key. Supported options
+include `headersTimeout`, `keepAliveTimeout`, `requestTimeout`, `timeout`,
+`maxHeadersCount`, and `maxRequestsPerSocket`.
+
+These are passed directly to the underlying Node.js HTTP server.
+If omitted, Node.js defaults are used.
diff --git a/.changeset/shiny-candles-hide.md b/.changeset/shiny-candles-hide.md
new file mode 100644
index 0000000000..7ec4a8062e
--- /dev/null
+++ b/.changeset/shiny-candles-hide.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
+'@backstage/plugin-notifications-backend-module-email': patch
+'@backstage/plugin-scaffolder-backend-module-gitlab': patch
+'@backstage/plugin-notifications-backend': patch
+'@backstage/plugin-notifications': patch
+---
+
+Removed unused dependencies
diff --git a/.changeset/short-aliens-invite.md b/.changeset/short-aliens-invite.md
new file mode 100644
index 0000000000..ae3bbc3831
--- /dev/null
+++ b/.changeset/short-aliens-invite.md
@@ -0,0 +1,13 @@
+---
+'@backstage/plugin-api-docs': minor
+---
+
+Remove explicit dependency on `isomorphic-form-data`.
+
+This explicit dependency was added to address [an issue](https://github.com/swagger-api/swagger-ui/issues/7436) in the
+dependency `swagger-ui-react`. That [issue has since been resolved](https://github.com/swagger-api/swagger-ui/issues/7436#issuecomment-889792304),
+and `isomorphic-form-data` no longer needs to be declared.
+
+Additionally, this changeset updates the `swagger-ui-react` dependency to version `5.19.0` or higher, which includes
+[compatibility](https://github.com/swagger-api/swagger-ui?tab=readme-ov-file#compatibility) with the latest versions of
+the OpenAPI specification.
diff --git a/.changeset/silent-mice-play.md b/.changeset/silent-mice-play.md
new file mode 100644
index 0000000000..aa14cf69e3
--- /dev/null
+++ b/.changeset/silent-mice-play.md
@@ -0,0 +1,9 @@
+---
+'@backstage/cli': patch
+---
+
+Remove unused @octokit modules from cli package
+
+- @octokit/graphql
+- @octokit/graphql-schema
+- @octokit/oauth-app
diff --git a/.changeset/six-cooks-battle.md b/.changeset/six-cooks-battle.md
new file mode 100644
index 0000000000..ecf856225e
--- /dev/null
+++ b/.changeset/six-cooks-battle.md
@@ -0,0 +1,6 @@
+---
+'@backstage/config-loader': patch
+'@backstage/config': patch
+---
+
+Allow colon to be used as config key.
diff --git a/.changeset/slimy-signs-agree.md b/.changeset/slimy-signs-agree.md
new file mode 100644
index 0000000000..c4307f0bd7
--- /dev/null
+++ b/.changeset/slimy-signs-agree.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-notifications-backend': patch
+---
+
+Fixed exclude entity reference not working in notification sending
diff --git a/.changeset/solid-bikes-leave.md b/.changeset/solid-bikes-leave.md
new file mode 100644
index 0000000000..6f1bfe0b2f
--- /dev/null
+++ b/.changeset/solid-bikes-leave.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-scaffolder-node': patch
+---
+
+**DEPRECATION**: We're going to be working on refactoring a lot of the internals of the Scaffolder backend plugin, and with that comes a lot of deprecations and removals for public types that are making these things hard.
+
+If you're using these types, please reach out to us either on Discord or a GitHub issue with your use cases.
+
+- `SerializedTask`, `SerializedTaskEvent`, `TaskBroker`, `TaskContext`, `TaskBrokerDispatchOptions`, `TaskBrokerDispatchResult`, `TaskCompletionState`, `TaskEventType`, `TaskFilter`, `TaskFilters`, `TaskStatus` are the types that have now been marked as deprecated, and will be removed in a future release.
diff --git a/.changeset/tame-hairs-smash.md b/.changeset/tame-hairs-smash.md
new file mode 100644
index 0000000000..db05708132
--- /dev/null
+++ b/.changeset/tame-hairs-smash.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
+'@backstage/plugin-bitbucket-cloud-common': patch
+---
+
+Allow for passing a `pagelen` parameter to configure the `pagelength` property of the `BitbucketCloudEntityProvider` `searchCode` pagination to resolve [bug](https://jira.atlassian.com/browse/BCLOUD-23644) pertaining to duplicate results being returned.
diff --git a/.changeset/thin-hoops-bathe.md b/.changeset/thin-hoops-bathe.md
new file mode 100644
index 0000000000..508d548431
--- /dev/null
+++ b/.changeset/thin-hoops-bathe.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Remove auto selection of tabs for tabs that all have href defined
diff --git a/.changeset/thirty-rules-press.md b/.changeset/thirty-rules-press.md
new file mode 100644
index 0000000000..d9968317cb
--- /dev/null
+++ b/.changeset/thirty-rules-press.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-defaults': minor
+---
+
+Add a new `externalTokenHandlersServiceRef` to allow custom external token validations
diff --git a/.changeset/tidy-coats-know.md b/.changeset/tidy-coats-know.md
new file mode 100644
index 0000000000..e641c12784
--- /dev/null
+++ b/.changeset/tidy-coats-know.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it
diff --git a/.changeset/tired-mice-cheer.md b/.changeset/tired-mice-cheer.md
new file mode 100644
index 0000000000..929aae0f59
--- /dev/null
+++ b/.changeset/tired-mice-cheer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Avoid overriding onChange when spreading props
diff --git a/.changeset/tough-clocks-attack.md b/.changeset/tough-clocks-attack.md
new file mode 100644
index 0000000000..caf3b33fe4
--- /dev/null
+++ b/.changeset/tough-clocks-attack.md
@@ -0,0 +1,5 @@
+---
+'@backstage/ui': patch
+---
+
+Using react router for internal links in the Menu component
diff --git a/.changeset/twelve-guests-sit.md b/.changeset/twelve-guests-sit.md
new file mode 100644
index 0000000000..0d75e07f0c
--- /dev/null
+++ b/.changeset/twelve-guests-sit.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes-react': patch
+---
+
+Fixes calculation of CPU utilization in the PodTable
diff --git a/.changeset/twelve-oranges-grin.md b/.changeset/twelve-oranges-grin.md
new file mode 100644
index 0000000000..ab1ede0a0d
--- /dev/null
+++ b/.changeset/twelve-oranges-grin.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-gitlab': patch
+---
+
+Fixed an issue in `GitlabDiscoveryEntityProvider` where entity fetching could fail for projects with special characters or that had been renamed or moved.
diff --git a/.changeset/two-emus-like.md b/.changeset/two-emus-like.md
new file mode 100644
index 0000000000..e8af7a7fa0
--- /dev/null
+++ b/.changeset/two-emus-like.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-app-visualizer': patch
+---
+
+Ensure that the text rendering has react keys for all elements
diff --git a/.changeset/unified-theme-attr-stack.md b/.changeset/unified-theme-attr-stack.md
new file mode 100644
index 0000000000..003e05018f
--- /dev/null
+++ b/.changeset/unified-theme-attr-stack.md
@@ -0,0 +1,5 @@
+---
+'@backstage/theme': patch
+---
+
+The `UnifiedThemeProvider` now coordinates theme attributes on the document `body` in case multiple theme providers are rendered.
diff --git a/.changeset/warm-items-look.md b/.changeset/warm-items-look.md
new file mode 100644
index 0000000000..b8a2abd61d
--- /dev/null
+++ b/.changeset/warm-items-look.md
@@ -0,0 +1,17 @@
+---
+'@backstage/plugin-catalog-backend-module-bitbucket-server': patch
+'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
+'@backstage/plugin-catalog-backend-module-github-org': patch
+'@backstage/plugin-catalog-backend-module-gitlab-org': patch
+'@backstage/plugin-catalog-backend-module-puppetdb': patch
+'@backstage/plugin-catalog-backend-module-msgraph': patch
+'@backstage/plugin-catalog-backend-module-gerrit': patch
+'@backstage/plugin-catalog-backend-module-github': patch
+'@backstage/plugin-catalog-backend-module-gitlab': patch
+'@backstage/plugin-catalog-backend-module-azure': patch
+'@backstage/plugin-catalog-backend-module-aws': patch
+'@backstage/plugin-kubernetes-cluster': patch
+'@backstage/plugin-kubernetes': patch
+---
+
+Removed unused dependencies
diff --git a/.changeset/wet-spiders-wait.md b/.changeset/wet-spiders-wait.md
new file mode 100644
index 0000000000..aaffc92013
--- /dev/null
+++ b/.changeset/wet-spiders-wait.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-scaffolder-backend': major
+---
+
+**BREAKING** - Removing the deprecated types and interfaces, there's no replacement for these types, and hopefully not currently used as they offer no value with the plugin being on the new backend system and no way to consume them.
+
+Affected types: `CreateWorkerOptions`, `CurrentClaimedTask`, `DatabaseTaskStore`, `DatabaseTaskStoreOptions`, `TaskManager`, `TaskStore`, `TaskStoreCreateTaskOptions`, `TaskStoreCreateTaskResult`, `TaskStoreEmitOptions`, `TaskStoreListEventsOptions`, `TaskStoreRecoverTaskOptions`, `TaskStoreShutDownTaskOptions`, `TaskWorker` and `TemplateActionRegistry`.
diff --git a/.changeset/wide-flies-jog.md b/.changeset/wide-flies-jog.md
new file mode 100644
index 0000000000..4fbafe66a1
--- /dev/null
+++ b/.changeset/wide-flies-jog.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Added missing form fields for the new frontend system.
diff --git a/.changeset/yarn-plugin-integration.md b/.changeset/yarn-plugin-integration.md
new file mode 100644
index 0000000000..2847e89273
--- /dev/null
+++ b/.changeset/yarn-plugin-integration.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Added automatic detection and support for the Backstage Yarn plugin when generating new packages with `yarn new`. When the plugin is installed, new packages will automatically use `backstage:^` ranges for `@backstage/*` dependencies.
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 4f0e0ac47d..98073c5128 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -14,7 +14,7 @@ The following files contain guidelines for the project:
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.
+- Test: Use `yarn test --no-watch ` in the project root to run tests. The path can be either a single file or a directory. Always provide a path, avoid running all tests.
- 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.
diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt
index 8f3dcb65ff..db3f3adf2c 100644
--- a/.github/vale/config/vocabularies/Backstage/accept.txt
+++ b/.github/vale/config/vocabularies/Backstage/accept.txt
@@ -282,6 +282,7 @@ modularization
monorepo
Monorepo
monorepos
+monospace
morgan
msgraph
msw
diff --git a/.github/workflows/verify_chromatic.yml b/.github/workflows/verify_chromatic.yml
index 0c9f110b4c..18511b936d 100644
--- a/.github/workflows/verify_chromatic.yml
+++ b/.github/workflows/verify_chromatic.yml
@@ -5,7 +5,7 @@ on:
push:
branches:
- master
- pull_request:
+ pull_request_target:
paths:
- '.github/workflows/verify_chromatic.yml'
- '.storybook/**'
@@ -31,6 +31,8 @@ jobs:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
+ # For pull_request_target, we need to check out the PR branch
+ ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
fetch-depth: 10000 # Required to retrieve git history
- name: Use node.js ${{ matrix.node-version }}
@@ -63,7 +65,7 @@ jobs:
packages/ui/src/**/*.css
- name: Prepare Chromatic Message
- if: github.event_name == 'pull_request' && steps.chromatic.outputs.url
+ if: github.event_name == 'pull_request_target' && steps.chromatic.outputs.url
id: prepare-message
run: |
if [ "${{ steps.chromatic.outputs.changeCount }}" = "0" ] || [ -z "${{ steps.chromatic.outputs.changeCount }}" ]; then
@@ -73,7 +75,7 @@ jobs:
fi
- name: Post Chromatic Link in PR Comment
- if: github.event_name == 'pull_request' && steps.chromatic.outputs.url
+ if: github.event_name == 'pull_request_target' && steps.chromatic.outputs.url
uses: mshick/add-pr-comment@v2
with:
message: |
diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml
index 080d14a743..64ce9e7b12 100644
--- a/.github/workflows/verify_e2e-techdocs.yml
+++ b/.github/workflows/verify_e2e-techdocs.yml
@@ -41,11 +41,10 @@ jobs:
with:
python-version: '3.9'
- - name: install dependencies
- run: yarn install --immutable
-
- - name: generate types
- run: yarn tsc
+ - name: yarn install
+ uses: backstage/actions/yarn-install@b3c1841fd69e1658ac631afafd0fb140a2309024 # v0.6.17
+ with:
+ cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- name: build techdocs-cli
working-directory: packages/techdocs-cli
diff --git a/docs-ui/src/app/theming/page.mdx b/docs-ui/src/app/theming/page.mdx
index 73275020bc..92b5256791 100644
--- a/docs-ui/src/app/theming/page.mdx
+++ b/docs-ui/src/app/theming/page.mdx
@@ -226,7 +226,7 @@ color of your app.
### Foreground colors
-Foreground colours are meant to work in pair with a background colours. Typeically this would work
+Foreground colours are meant to work in pair with a background colours. Typically this would work
for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors
are prefixed with `fg` to make it easier to identify.
diff --git a/docs-ui/src/content/components/grid.props.ts b/docs-ui/src/content/components/grid.props.ts
index 34d89785cc..6f037cd64f 100644
--- a/docs-ui/src/content/components/grid.props.ts
+++ b/docs-ui/src/content/components/grid.props.ts
@@ -43,12 +43,12 @@ export const gridItemPropDefs: Record = {
values: [...columnsValues, 'full'],
responsive: true,
},
- start: {
+ colStart: {
type: 'enum | string',
values: [...columnsValues, 'auto'],
responsive: true,
},
- end: {
+ colEnd: {
type: 'enum | string',
values: [...columnsValues, 'auto'],
responsive: true,
@@ -60,7 +60,7 @@ export const gridItemPropDefs: Record = {
export const gridUsageSnippet = `import { Grid } from '@backstage/ui';
-`;
+`;
export const gridDefaultSnippet = `
@@ -68,44 +68,44 @@ export const gridDefaultSnippet = ``;
-export const gridSimpleSnippet = `
+export const gridSimpleSnippet = `Hello WorldHello WorldHello World
-`;
+`;
-export const gridComplexSnippet = `
-
- Hello World
+export const gridComplexSnippet = `
+
+ Hello World
-
- Hello World
+
+ Hello World
-`;
+`;
-export const gridMixingRowsSnippet = `
-
- Hello World
+export const gridMixingRowsSnippet = `
+
+ Hello World
-
- Hello World
+
+ Hello World
-
- Hello World
+
+ Hello World
-`;
+`;
-export const gridResponsiveSnippet = `
+export const gridResponsiveSnippet = `
- Hello World
+
- Hello World
+ Hello World
-`;
+`;
-export const gridStartEndSnippet = `
-
- Hello World
+export const gridStartEndSnippet = `
+
+ Hello World
-`;
+`;
diff --git a/docs-ui/src/content/components/table.props.ts b/docs-ui/src/content/components/table.props.ts
index 1b40055849..d46c6b8ea7 100644
--- a/docs-ui/src/content/components/table.props.ts
+++ b/docs-ui/src/content/components/table.props.ts
@@ -212,6 +212,11 @@ export const cellPropDefs: Record = {
description:
"A string representation of the cell's contents, used for features like typeahead.",
},
+ leadingIcon: {
+ type: 'enum',
+ values: ['ReactNode'],
+ description: 'Optional icon to display before the cell content.',
+ },
...classNamePropDefs,
...stylePropDefs,
};
diff --git a/docs/assets/architecture-overview/backstage-front-back-arch.jpeg b/docs/assets/architecture-overview/backstage-front-back-arch.jpeg
new file mode 100644
index 0000000000..1cca115c95
Binary files /dev/null and b/docs/assets/architecture-overview/backstage-front-back-arch.jpeg differ
diff --git a/docs/assets/architecture-overview/simplified-service-based-plugin-architecture.jpeg b/docs/assets/architecture-overview/simplified-service-based-plugin-architecture.jpeg
new file mode 100644
index 0000000000..e8f5144c9a
Binary files /dev/null and b/docs/assets/architecture-overview/simplified-service-based-plugin-architecture.jpeg differ
diff --git a/docs/assets/architecture-overview/simplified-standalone-plugin-architecture.jpeg b/docs/assets/architecture-overview/simplified-standalone-plugin-architecture.jpeg
new file mode 100644
index 0000000000..bf96367b17
Binary files /dev/null and b/docs/assets/architecture-overview/simplified-standalone-plugin-architecture.jpeg differ
diff --git a/docs/assets/architecture-overview/simplified-third-party-plugin-architecture.jpeg b/docs/assets/architecture-overview/simplified-third-party-plugin-architecture.jpeg
new file mode 100644
index 0000000000..4b9fd1d35f
Binary files /dev/null and b/docs/assets/architecture-overview/simplified-third-party-plugin-architecture.jpeg differ
diff --git a/docs/assets/technical-overview/backstage-ui-group-ownership.png b/docs/assets/technical-overview/backstage-ui-group-ownership.png
new file mode 100644
index 0000000000..607aa7ad47
Binary files /dev/null and b/docs/assets/technical-overview/backstage-ui-group-ownership.png differ
diff --git a/docs/assets/user-interface/css-classname-structure.png b/docs/assets/user-interface/css-classname-structure.png
new file mode 100644
index 0000000000..c241b182cc
Binary files /dev/null and b/docs/assets/user-interface/css-classname-structure.png differ
diff --git a/docs/auth/service-to-service-auth.md b/docs/auth/service-to-service-auth.md
index d35aed364d..1423fa92f7 100644
--- a/docs/auth/service-to-service-auth.md
+++ b/docs/auth/service-to-service-auth.md
@@ -414,9 +414,13 @@ Each entry has one or more of the following fields:
## Adding custom or logic for validation and issuing of tokens
-The `pluginTokenHandlerDecoratorServiceRef` can be used to decorate the existing token handler without having to re-implement the entire `AuthService` implementation.
+The `pluginTokenHandlerDecoratorServiceRef` and `externalTokenHandlersServiceRef` can be used to extend the existing token handler without having to re-implement the entire `AuthService` implementation.
This is particularly useful when you want to add additional logic to the handler, such as logging or metrics or custom token validation.
+### PluginTokenHandler decoration
+
+The `pluginTokenHandlerDecoratorServiceRef` can be used to decorate the default PluginTokenHandler used for create and verify tokens from plugins.
+
The `PluginTokenHandler` interface has two methods:
- `issueToken`: This method is used to issue a token for a plugin. It takes in the `pluginId` and `targetPluginId` as arguments, and an optional `limitedUserToken` object which can be used to issue a token on behalf of another user. The method returns a promise that resolves to an object containing the issued token.
@@ -439,3 +443,109 @@ const decoratedPluginTokenHandler = createServiceFactory({
},
});
```
+
+### Adding custom ExternalTokenHandler
+
+The `externalTokenHandlersServiceRef` can be used to add custom external token handlers to the default implementation.
+
+Your service factory must return an object with a `type` property that matches the token type in your configuration (e.g., 'custom', 'api-key'). When Backstage encounters tokens of this type, it calls your `initialize` method with all the configuration entries that match this type. Your factory can return either a single token handler or an array of handlers to process and validate these tokens.
+
+:::note Note
+
+During token verification, all the token handlers are tested. Consider this when adding many token handlers, as it may impact performance.
+
+:::
+
+For example, if we want to add a custom external token handler for the `custom` type:
+
+our config would look like this:
+
+```yaml title="in e.g. app-config.production.yaml"
+backend:
+ auth:
+ externalAccess:
+ - type: custom
+ options:
+ customOptions: additional-value
+ accessRestrictions:
+ - plugin: events
+ - type: custom
+ options:
+ customOptions: another-value
+ accessRestrictions:
+ - plugin: events
+```
+
+And we can implement the custom token handler like this:
+
+```ts
+import {
+ ExternalTokenHandler,
+ externalTokenHandlersServiceRef,
+ createExternalTokenHandler,
+} from '@backstage/backend-defaults/auth';
+import { createServiceFactory } from '@backstage/backend-plugin-api';
+
+const customExternalTokenHandlers = createServiceFactory({
+ service: externalTokenHandlersServiceRef,
+ deps: {},
+ async factory() {
+ return createExternalTokenHandler({
+ type: 'custom',
+ initialize({ options }) {
+ // Initialize your handler context from config
+ const customOptions = options.getString('customOptions');
+ return { customOptions };
+ },
+ async verifyToken(token, context) {
+ // Your custom token validation logic here
+ // Return undefined if token is invalid
+ // Return { subject: 'your-subject' } if token is valid
+
+ if (token === 'valid-token') {
+ return { subject: `custom:${context.customOptions}` };
+ }
+ return undefined;
+ },
+ });
+ },
+});
+```
+
+The `createExternalTokenHandler` helper simplifies creating external token handlers with the new API:
+
+- **`type`**: A string identifier for your token handler type that matches the config
+- **`initialize`**: Called once for each config entry of this type, receives the config options and returns a context object that will be passed to `verifyToken`
+- **`verifyToken`**: Called for each token verification with the token and context, returns the subject if valid or `undefined` if not
+
+```ts
+// Example of a more complex handler with external API call
+const apiTokenHandler = createExternalTokenHandler({
+ type: 'api-validation',
+ initialize({ options }) {
+ const apiBaseUrl = options.getString('apiBaseUrl');
+ const apiKey = options.getString('apiKey');
+ return { apiBaseUrl, apiKey };
+ },
+ async verifyToken(token, { apiBaseUrl, apiKey }) {
+ try {
+ const response = await fetch(`${apiBaseUrl}/validate-token`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${apiKey}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ token }),
+ });
+
+ if (response.ok) {
+ const { userId } = await response.json();
+ return { subject: `api:${userId}` };
+ }
+ } catch (error) {
+ // Log error but don't throw - return undefined for invalid tokens
+ }
+ return undefined;
+ },
+});
+```
diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md
index cfcd606d92..022aab202b 100644
--- a/docs/backend-system/architecture/03-services.md
+++ b/docs/backend-system/architecture/03-services.md
@@ -223,6 +223,35 @@ export const customFooServiceFactory = createServiceFactory({
This allows you to provide more advanced options for the service implementation that couldn't be expressed through static configuration. It also gives users of the service implementation access to other services through dependency injection, which can be useful for their customizations.
+## Multiton
+
+By default the service reference will point to a singleton instance of the service. This mean if a new service factory uses this reference it will override the previous one. This is the most common use-case, but in some cases you may want to have multiple instances of the same service.
+For some services, it is desirable to extend the functionality instead of overriding it. For example, some services could have many handlers to address specific events, and you may want to add a new handler instead of overriding the previous one. In this case, you can use the `multiton` option when creating the service reference:
+
+```ts
+// example-service-ref.ts
+import { createServiceRef } from '@backstage/backend-plugin-api';
+
+export interface FooService {
+ foo(options: FooOptions): Promise;
+}
+
+export const fooServiceRef = createServiceRef({
+ id: 'example.foo',
+ multiton: true, // this service ref will be an array of instances
+});
+```
+
+When adding this `serviceRef` as a dependency to a factory, the factory will receive an array of instances instead of a single instance:
+
+```ts
+deps: {fooServices: fooServiceRef},
+ factory(fooServices) {
+ // fooServices is an array of instances
+ return new Bar(fooServices);
+ },
+```
+
## Service Factory Options Pattern
:::note Note
diff --git a/docs/backend-system/core-services/http-router.md b/docs/backend-system/core-services/http-router.md
index 5e065152a0..6de394f549 100644
--- a/docs/backend-system/core-services/http-router.md
+++ b/docs/backend-system/core-services/http-router.md
@@ -134,7 +134,13 @@ import {
createAuthIntegrationRouter,
createRateLimitMiddleware,
} from '@backstage/backend-defaults/httpRouter';
-import { createServiceFactory } from '@backstage/backend-plugin-api';
+import PromiseRouter from 'express-promise-router';
+import { Handler } from 'express';
+import {
+ createServiceFactory,
+ coreServices,
+ HttpRouterServiceAuthPolicy,
+} from '@backstage/backend-plugin-api';
const backend = createBackend();
diff --git a/docs/backend-system/core-services/root-http-router.md b/docs/backend-system/core-services/root-http-router.md
index 1e76fb1871..1bda95a990 100644
--- a/docs/backend-system/core-services/root-http-router.md
+++ b/docs/backend-system/core-services/root-http-router.md
@@ -65,6 +65,20 @@ backend:
# - A standard ISO formatted duration string, e.g. 'P2DT6H' or 'PT1M'.
# - An object with individual units (in plural) as keys, e.g. `{ days: 2, hours: 6 }`.
serverShutdownDelay: { seconds: 20 }
+ server:
+ # (Optional) HTTP server configuration, Node.js defaults apply otherwise
+ # Timeout values support multiple formats:
+ # - Numbers (milliseconds): 30000
+ # - Duration strings: '30s', '1 minute', '2 hours'
+ # - ISO duration strings: 'PT30S', 'PT1M', 'PT2H'
+ # - Duration objects: { seconds: 30 }, { minutes: 1 }, { hours: 2 }
+ headersTimeout: 60000
+ requestTimeout: '30s'
+ keepAliveTimeout: { seconds: 5 }
+ timeout: 'PT30S'
+ # Numeric-only settings
+ maxHeadersCount: 2000
+ maxRequestsPerSocket: 100
```
### Via Code
diff --git a/docs/conf/user-interface/icons.md b/docs/conf/user-interface/icons.md
new file mode 100644
index 0000000000..26a6f11096
--- /dev/null
+++ b/docs/conf/user-interface/icons.md
@@ -0,0 +1,124 @@
+---
+id: icons
+title: Customizing Icons
+sidebar_label: Icons
+description: Customizing Icons
+---
+
+So far you've seen how to create your own theme and add your own logo, in the following sections you'll be shown how to override the existing icons and how to add more icons
+
+## Custom Icons
+
+You can also customize the Project's _default_ icons.
+
+You can change the following [icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx).
+
+### Requirements
+
+- Files in `.svg` format
+- React components created for the icons
+
+### Create React Component
+
+In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `customIcons.tsx` file.
+
+```tsx title="customIcons.tsx"
+import { SvgIcon, SvgIconProps } from '@material-ui/core';
+
+export const ExampleIcon = (props: SvgIconProps) => (
+
+
+
+);
+```
+
+### Using the custom icon
+
+Supply your custom icon in `packages/app/src/App.tsx`
+
+```tsx title="packages/app/src/App.tsx"
+/* highlight-add-next-line */
+import { ExampleIcon } from './assets/icons/CustomIcons'
+
+
+const app = createApp({
+ apis,
+ components: {
+ {/* ... */}
+ },
+ themes: [
+ {/* ... */}
+ ],
+ /* highlight-add-start */
+ icons: {
+ github: ExampleIcon,
+ },
+ /* highlight-add-end */
+ bindRoutes({ bind }) {
+ {/* ... */}
+ }
+})
+```
+
+## Adding Icons
+
+You can add more icons, if the [default icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx) do not fit your needs, so that they can be used in other places like for Links in your entities. For this example we'll be using icons from[Material UI](https://v4.mui.com/components/material-icons/) and specifically the `AlarmIcon`. Here's how to do that:
+
+1. First you will want to open your `App.tsx` in `/packages/app/src`
+2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';`
+3. Next you want to add the icon like this to your `createApp`:
+
+ ```tsx title="packages/app/src/App.tsx"
+ const app = createApp({
+ apis: ...,
+ plugins: ...,
+ /* highlight-add-start */
+ icons: {
+ alert: AlarmIcon,
+ },
+ /* highlight-add-end */
+ themes: ...,
+ components: ...,
+ });
+ ```
+
+4. Now we can reference `alert` for our icon in our entity links like this:
+
+ ```yaml
+ apiVersion: backstage.io/v1alpha1
+ kind: Component
+ metadata:
+ name: artist-lookup
+ description: Artist Lookup
+ links:
+ - url: https://example.com/alert
+ title: Alerts
+ icon: alert
+ ```
+
+ And this is the result:
+
+ 
+
+ Another way you can use these icons is from the `AppContext` like this:
+
+ ```ts
+ import { useApp } from '@backstage/core-plugin-api';
+
+ const app = useApp();
+ const alertIcon = app.getSystemIcon('alert');
+ ```
+
+ You might want to use this method if you have an icon you want to use in several locations.
+
+:::note Note
+
+If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon`
+
+:::
diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md
new file mode 100644
index 0000000000..81acfdf720
--- /dev/null
+++ b/docs/conf/user-interface/index.md
@@ -0,0 +1,621 @@
+---
+id: index
+title: Customizing Your App's UI
+sidebar_label: Introduction
+description: Learn how to customize the look and feel of your Backstage app, including theming and branding options.
+---
+
+Backstage offers built-in support for both light and dark themes, making it easy to get started with a professional look and feel. But many teams want to go further—tailoring the interface to reflect their organization’s unique brand, identity, and experience.
+
+This section explores the different ways you can customize the appearance of your Backstage instance. You'll learn how the theming system is structured today, how to work with the two coexisting UI systems, and how to define themes that align with your visual language.
+
+## Theming architecture overview
+
+Backstage currently supports two parallel UI systems. The original theming and component model is built on Material UI (MUI), a popular React-based framework. More recently, Backstage introduced Backstage UI (BUI), a custom-designed, CSS-first system developed to meet the platform’s evolving needs. Both systems are supported today, with many parts of the ecosystem still using MUI while new components adopt BUI.
+
+