Merge branch 'backstage:master' into add-clear-and-visibility-actions-to-text-field
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Internal refactor to remove remnants of the old backend system
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-module-pg': patch
|
||||
---
|
||||
|
||||
Truncate long docs to fit PG index size limit
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@techdocs/cli': minor
|
||||
---
|
||||
|
||||
Techdocs CLI serve supports automatic refresh, relying on `mkdocs` `watch` feature.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Log before provider-orphaning eviction happens
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-defaults': minor
|
||||
---
|
||||
|
||||
implement support for direct url for AzureBlobStorageUrlReader search function
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
remove default selection of tab
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-react': patch
|
||||
---
|
||||
|
||||
Don't change loading to false until we've actually got some log state
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications-backend-module-email': patch
|
||||
---
|
||||
|
||||
chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-react': patch
|
||||
---
|
||||
|
||||
The configmaps added to be rendered
|
||||
@@ -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
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Making href mandatory in tabs that are part of a Header component
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
remove host from azure blob storage integration type
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
---
|
||||
|
||||
Added `renderEdge` prop to `<DependencyGraph />` component in `@backstage/core-components` to allow custom rendering of graph edges.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-signals': patch
|
||||
---
|
||||
|
||||
Remove `app-root-element:signals/signals-display` which was not doing anything useful
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
fix(home): correct `clearAll` logic to properly handle `deletable` flag
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Add `initialRelationAggregation` and `showAggregateMembersToggle` options to `EntityMembersListCard` as well to `EntityOwnershipCard`
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gcp': patch
|
||||
---
|
||||
|
||||
Fix documentation strings to mention GCP instead of Azure
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-module-pg': patch
|
||||
---
|
||||
|
||||
Added the < character to the query filter regexp
|
||||
+69
-2
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
---
|
||||
|
||||
Fixed DependencyGraph `svg` size not adapting to the container size
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Fixed dependency graph automatically scrolling forever
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Add missing `templatingExtensions` option to RouterProps.contextMenu to allow global control across scaffolder pages
|
||||
@@ -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.
|
||||
@@ -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';
|
||||
```
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Add react router for internal routing for ButtonLinks
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Remove unused @octokit modules from cli package
|
||||
|
||||
- @octokit/graphql
|
||||
- @octokit/graphql-schema
|
||||
- @octokit/oauth-app
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
'@backstage/config': patch
|
||||
---
|
||||
|
||||
Allow colon to be used as config key.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications-backend': patch
|
||||
---
|
||||
|
||||
Fixed exclude entity reference not working in notification sending
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Remove auto selection of tabs for tabs that all have href defined
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-defaults': minor
|
||||
---
|
||||
|
||||
Add a new `externalTokenHandlersServiceRef` to allow custom external token validations
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Avoid overriding onChange when spreading props
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Using react router for internal links in the Menu component
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-react': patch
|
||||
---
|
||||
|
||||
Fixes calculation of CPU utilization in the PodTable
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-app-visualizer': patch
|
||||
---
|
||||
|
||||
Ensure that the text rendering has react keys for all elements
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/theme': patch
|
||||
---
|
||||
|
||||
The `UnifiedThemeProvider` now coordinates theme attributes on the document `body` in case multiple theme providers are rendered.
|
||||
@@ -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
|
||||
@@ -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`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Added missing form fields for the new frontend system.
|
||||
@@ -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.
|
||||
@@ -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 <path>` 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 <path>` 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 <path>` to format code.
|
||||
- Lint: Use `yarn lint --fix` in the project root to run the linter.
|
||||
|
||||
@@ -282,6 +282,7 @@ modularization
|
||||
monorepo
|
||||
Monorepo
|
||||
monorepos
|
||||
monospace
|
||||
morgan
|
||||
msgraph
|
||||
msw
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -43,12 +43,12 @@ export const gridItemPropDefs: Record<string, PropDef> = {
|
||||
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<string, PropDef> = {
|
||||
|
||||
export const gridUsageSnippet = `import { Grid } from '@backstage/ui';
|
||||
|
||||
<Grid />`;
|
||||
<Grid.Root />`;
|
||||
|
||||
export const gridDefaultSnippet = `<Grid.Root>
|
||||
<DecorativeBox />
|
||||
@@ -68,44 +68,44 @@ export const gridDefaultSnippet = `<Grid.Root>
|
||||
<DecorativeBox />
|
||||
</Grid.Root>`;
|
||||
|
||||
export const gridSimpleSnippet = `<Grid columns={3} gap="md">
|
||||
export const gridSimpleSnippet = `<Grid.Root columns="3" gap="md">
|
||||
<Box>Hello World</Box>
|
||||
<Box>Hello World</Box>
|
||||
<Box>Hello World</Box>
|
||||
</Grid>`;
|
||||
</Grid.Root>`;
|
||||
|
||||
export const gridComplexSnippet = `<Grid columns={3} gap="md">
|
||||
<Grid.Item colSpan={1}>
|
||||
<Box>Hello World</Box>
|
||||
export const gridComplexSnippet = `<Grid.Root columns="3" gap="md">
|
||||
<Grid.Item colSpan="1">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan={2}>
|
||||
<Box>Hello World</Box>
|
||||
<Grid.Item colSpan="2">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
</Grid>`;
|
||||
</Grid.Root>`;
|
||||
|
||||
export const gridMixingRowsSnippet = `<Grid columns={3} gap="md">
|
||||
<Grid.Item colSpan={1} rowSpan={2}>
|
||||
<Box>Hello World</Box>
|
||||
export const gridMixingRowsSnippet = `<Grid.Root columns="3" gap="md">
|
||||
<Grid.Item colSpan="1" rowSpan="2">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan={2}>
|
||||
<Box>Hello World</Box>
|
||||
<Grid.Item colSpan="2">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan={2}>
|
||||
<Box>Hello World</Box>
|
||||
<Grid.Item colSpan="2">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
</Grid>`;
|
||||
</Grid.Root>`;
|
||||
|
||||
export const gridResponsiveSnippet = `<Grid columns={{ xs: 1, md: 3 }} gap={{ xs: 'xs', md: 'md' }}>
|
||||
export const gridResponsiveSnippet = `<Grid.Root columns={{ xs: 1, md: 3 }} gap={{ xs: 'xs', md: 'md' }}>
|
||||
<Grid.Item colSpan={{ xs: 1, md: 2 }}>
|
||||
<Box>Hello World</Box>
|
||||
<Hello World
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan={{ xs: 1, md: 1 }}>
|
||||
<Box>Hello World</Box>
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
</Grid>`;
|
||||
</Grid.Root>`;
|
||||
|
||||
export const gridStartEndSnippet = `<Grid columns={3} gap="md">
|
||||
<Grid.Item start={2} end={4}>
|
||||
<Box>Hello World</Box>
|
||||
export const gridStartEndSnippet = `<Grid.Root columns="3" gap="md">
|
||||
<Grid.Item colStart="2" colEnd="4">
|
||||
Hello World
|
||||
</Grid.Item>
|
||||
</Grid>`;
|
||||
</Grid.Root>`;
|
||||
|
||||
@@ -212,6 +212,11 @@ export const cellPropDefs: Record<string, PropDef> = {
|
||||
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,
|
||||
};
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 216 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 138 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 242 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -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;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -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<FooResult>;
|
||||
}
|
||||
|
||||
export const fooServiceRef = createServiceRef<FooService>({
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) => (
|
||||
<SvgIcon {...props} viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
width="1em"
|
||||
height="1em"
|
||||
display="inline-block"
|
||||
d="M11.6335 10.8398C11.6335 11.6563 12.065 12.9922 13.0863 12.9922C14.1075 12.9922 14.539 11.6563 14.539 10.8398C14.539 10.0234 14.1075 8.6875 13.0863 8.6875C12.065 8.6875 11.6335 10.0234 11.6335 10.8398V10.8398ZM2.38419e-07 8.86719C2.38419e-07 10.1133 0.126667 11.4336 0.692709 12.5781C2.19292 15.5703 6.3175 15.5 9.27042 15.5C12.2708 15.5 16.6408 15.6055 18.2004 12.5781C18.7783 11.4453 19 10.1133 19 8.86719C19 7.23047 18.4498 5.68359 17.3573 4.42969C17.5631 3.8125 17.6621 3.16406 17.6621 2.52344C17.6621 1.68359 17.4681 1.26172 17.0842 0.5C15.291 0.5 14.1431 0.851562 12.7775 1.90625C11.6296 1.63672 10.45 1.51562 9.26646 1.51562C8.19771 1.51562 7.12104 1.62891 6.08396 1.875C4.73813 0.832031 3.59021 0.5 1.81687 0.5C1.42896 1.26172 1.23896 1.68359 1.23896 2.52344C1.23896 3.16406 1.34188 3.80078 1.54375 4.40625C0.455209 5.67188 2.38419e-07 7.23047 2.38419e-07 8.86719V8.86719ZM2.54521 10.8398C2.54521 9.125 3.60208 7.61328 5.45458 7.61328C6.20271 7.61328 6.91917 7.74609 7.67125 7.84766C8.26104 7.9375 8.85083 7.97266 9.45646 7.97266C10.0581 7.97266 10.6479 7.9375 11.2417 7.84766C11.9819 7.74609 12.7063 7.61328 13.4583 7.61328C15.3108 7.61328 16.3677 9.125 16.3677 10.8398C16.3677 14.2695 13.1852 14.7969 10.4144 14.7969H8.50646C5.72375 14.7969 2.54521 14.2734 2.54521 10.8398V10.8398ZM5.81479 8.6875C6.83604 8.6875 7.2675 10.0234 7.2675 10.8398C7.2675 11.6563 6.83604 12.9922 5.81479 12.9922C4.79354 12.9922 4.36208 11.6563 4.36208 10.8398C4.36208 10.0234 4.79354 8.6875 5.81479 8.6875Z"
|
||||
/>
|
||||
</SvgIcon>
|
||||
);
|
||||
```
|
||||
|
||||
### 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`
|
||||
|
||||
:::
|
||||
@@ -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.
|
||||
|
||||
<div style="display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
||||
<div style="flex: 1; min-width: 250px; border: 1px solid #ccc; border-radius: 8px; padding: 1rem;">
|
||||
<h3 style="margin-top: 0;">MUI (Legacy)</h3>
|
||||
<ul>
|
||||
<li><strong>Theming:</strong> JS-based with <code>UnifiedThemeProvider</code></li>
|
||||
<li><strong>Coverage:</strong> Most existing plugins</li>
|
||||
<li><strong>Documentation:</strong> <a href="https://mui.com/material-ui/" target="_blank">mui.com</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 250px; border: 1px solid #ccc; border-radius: 8px; padding: 1rem;">
|
||||
<h3 style="margin-top: 0;">Backstage UI (New)</h3>
|
||||
<ul>
|
||||
<li><strong>Theming:</strong> CSS variables and tokens</li>
|
||||
<li><strong>Coverage:</strong> Growing, focused on new work</li>
|
||||
<li><strong>Documentation:</strong> <a href="https://ui.backstage.io" target="_blank">ui.backstage.io</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
:::info
|
||||
We recognize that maintaining two separate theming systems is not ideal. Because of the fundamental architectural differences between MUI and Backstage UI, it can be challenging to automate theme updates or know exactly which theme to modify for a given component. Our recommendation is to inspect the component’s code and check its class names: if you see a class name starting with `bui`, you should use the Backstage UI theming approach to style it.
|
||||
:::
|
||||
|
||||
## Creating custom themes
|
||||
|
||||
During the transition to Backstage UI, you will need to maintain themes in two places: some components and plugins still rely on MUI, while others use Backstage UI. We are working on a plugin that will make help you convert your existing MUI theme into a Backstage UI CSS file you can add to your application. We'll update this page when the plugin is available but for now you can follow progress on this PR [#31140](https://github.com/backstage/backstage/pull/31140).
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
/* highlight-add-start */
|
||||
import { lightTheme, darkTheme } from './themes'; // MUI themes
|
||||
import './styles.css'; // Backstage UI (BUI) theme
|
||||
/* highlight-add-end */
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
components,
|
||||
/* highlight-add-start */
|
||||
themes: [
|
||||
{
|
||||
id: 'light',
|
||||
title: 'Light theme',
|
||||
variant: 'light',
|
||||
icon: <LightIcon />,
|
||||
Provider: ({ children }) => (
|
||||
<UnifiedThemeProvider theme={lightTheme} children={children} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'dark',
|
||||
title: 'Dark theme',
|
||||
variant: 'dark',
|
||||
icon: <DarkIcon />,
|
||||
Provider: ({ children }) => (
|
||||
<UnifiedThemeProvider theme={darkTheme} children={children} />
|
||||
),
|
||||
},
|
||||
],
|
||||
/* highlight-add-end */
|
||||
});
|
||||
```
|
||||
|
||||
| Name | Description |
|
||||
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | Each theme has a unique `id` |
|
||||
| `title` | This will be shown in the settings page to select the right theme. |
|
||||
| `variant` | This can be either `light` or `dark`. This is also referred to as `mode`. On the `body` of your app we are inserting a data attribute to set the theme based on this value: `data-theme-mode="light"`. |
|
||||
| `icon` | This will be shown in the settings page as a visual element to complement the title. |
|
||||
| `Provider` | This is needed to set the legacy theme with MUI only. This will be become redundant later on when we fully replace with BUI but for now you need to have it for MUI to work. BUI is based on CSS and don't rely on any global providers. |
|
||||
|
||||
:::note
|
||||
Your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). Be sure to provide both `light` and `dark` modes so users can choose their preference.
|
||||
:::
|
||||
|
||||
## Create a theme for Backstage UI (New)
|
||||
|
||||
Backstage UI is built entirely using CSS. By default we are providing a default theme that include all our core CSS variables and component styles. To start customising Backstage UI to match your brand you need to create a new CSS file and import it directly in `packages/app/src/App.tsx`. All styles declared in this file will override the default styles. As your file grow you can organise it the way you want or even import multiple files.
|
||||
|
||||
Backstage UI is using light by default under `:root` but you can target it more specifically using the data attribute for mode
|
||||
|
||||
```css title="packages/app/src/styles.css"
|
||||
:root {
|
||||
/* Use :root to set styles for both light and dark themes */
|
||||
.bui-Button {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme-mode='light'] {
|
||||
/* Light theme specific styles */
|
||||
--bui-bg: #f8f8f8;
|
||||
--bui-fg-primary: #000;
|
||||
}
|
||||
|
||||
[data-theme-mode='dark'] {
|
||||
/* Dark theme specific styles */
|
||||
--bui-bg: #333333;
|
||||
--bui-fg-primary: #fff;
|
||||
}
|
||||
```
|
||||
|
||||
### CSS variables
|
||||
|
||||
By adjusting just a few theme variables, you can easily transform the look and feel of your Backstage instance to align with your brand identity. All colors are defined using these variables, ensuring they adapt seamlessly to both light and dark modes.
|
||||
|
||||
We recommend starting with a core set of CSS variables to quickly achieve a branded experience. You’ll also find a complete list of available variables below, giving you full flexibility to fine-tune the design to your needs.
|
||||
|
||||
And if you’d like to go even further, you can target specific component class names for advanced customization.
|
||||
|
||||
| Token Name | Description |
|
||||
| -------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `--bui-bg` | This is used to define the background color of your app. It will only be used once. |
|
||||
| `--bui-bg-surface-1` | We ar using this color to sit on top of `--bui-bg` mostly for `Card`, `Dialog`, ... |
|
||||
| `--bui-bg-surface-2` | This is for content inside elevated components. This colour is less common. |
|
||||
| `--bui-bg-solid` | This is used for main actions like primary buttons. |
|
||||
| `--bui-fg-solid` | This is for texts or icons on top of a solid backgrounds. |
|
||||
| `--bui-fg-primary` | Your primary text or icon colours. |
|
||||
| `--bui-fg-secondary` | Your secondary text or icon colours. |
|
||||
| `--bui-fg-link` | Used for links. |
|
||||
| `--bui-border` | Main borders around surfaces like `Card`, `Dialog`, ... |
|
||||
| `--bui-font-regular` | The main font of your app. |
|
||||
|
||||
<details>
|
||||
<summary>All available CSS variables</summary>
|
||||
|
||||
#### Base colors
|
||||
|
||||
These colors are used for special purposes like ring, scrollbar, ...
|
||||
|
||||
| Token Name | Description |
|
||||
| -------------- | ----------------------------------------------------------------------- |
|
||||
| `--bui-black` | Pure black color. This one should be the same in light and dark themes. |
|
||||
| `--bui-white` | Pure white color. This one should be the same in light and dark themes. |
|
||||
| `--bui-gray-1` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-2` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-3` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-4` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-5` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-6` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-7` | You can use these mostly for backgrounds colors. |
|
||||
| `--bui-gray-8` | You can use these mostly for backgrounds colors. |
|
||||
|
||||
#### 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. `--bui-bg` should mostly use as the main background color of your app.
|
||||
|
||||
| Token Name | Description |
|
||||
| ------------------------- | ------------------------------------------------ |
|
||||
| `--bui-bg` | The background color of your Backstage instance. |
|
||||
| `--bui-bg-surface-1` | Use for any panels or elevated surfaces. |
|
||||
| `--bui-bg-surface-2` | Use for any panels or elevated surfaces. |
|
||||
| `--bui-bg-solid` | Used for solid background colors. |
|
||||
| `--bui-bg-solid-hover` | Used for solid background colors when hovered. |
|
||||
| `--bui-bg-solid-pressed` | Used for solid background colors when pressed. |
|
||||
| `--bui-bg-solid-disabled` | Used for solid background colors when disabled. |
|
||||
| `--bui-bg-tint` | Used for tint background colors. |
|
||||
| `--bui-bg-tint-hover` | Used for tint background colors when hovered. |
|
||||
| `--bui-bg-tint-focus` | Used for tint background colors when active. |
|
||||
| `--bui-bg-tint-disabled` | Used for tint background colors when disabled. |
|
||||
| `--bui-bg-danger` | Used to show errors information. |
|
||||
| `--bui-bg-warning` | Used to show warnings information. |
|
||||
| `--bui-bg-success` | Used to show success information. |
|
||||
|
||||
#### Foreground colors
|
||||
|
||||
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.
|
||||
|
||||
| Token Name | Description |
|
||||
| ------------------------ | ----------------------------------------------------------------- |
|
||||
| `--bui-fg-primary` | It should be used on top of main background surfaces. |
|
||||
| `--bui-fg-secondary` | It should be used on top of main background surfaces. |
|
||||
| `--bui-fg-link` | It should be used on top of main background surfaces. |
|
||||
| `--bui-fg-link-hover` | It should be used on top of main background surfaces. |
|
||||
| `--bui-fg-disabled` | It should be used on top of main background surfaces. |
|
||||
| `--bui-fg-solid` | It should be used on top of solid background colors. |
|
||||
| `--bui-fg-tint` | It should be used on top of tint background colors. |
|
||||
| `--bui-fg-tint-disabled` | It should be used on top of tint background colors when disabled. |
|
||||
| `--bui-fg-danger` | It should be used on top of danger background colors. |
|
||||
| `--bui-fg-warning` | It should be used on top of warning background colors. |
|
||||
| `--bui-fg-success` | It should be used on top of success background colors. |
|
||||
|
||||
#### Border colors
|
||||
|
||||
These border colors are mostly meant to be used as borders on top of any components with low contrast to help as a separator with the different background colors.
|
||||
|
||||
| Token Name | Description |
|
||||
| ----------------------- | --------------------------------------------------- |
|
||||
| `--bui-border` | It should be used on top of `--bui-bg-surface-1`. |
|
||||
| `--bui-border-hover` | Used when the component is interactive and hovered. |
|
||||
| `--bui-border-pressed` | Used when the component is interactive and hovered. |
|
||||
| `--bui-border-disabled` | Used when the component is disabled. |
|
||||
| `--bui-border-danger` | It should be used on top of `--bui-bg-danger`. |
|
||||
| `--bui-border-warning` | It should be used on top of `--bui-bg-warning`. |
|
||||
| `--bui-border-success` | It should be used on top of `--bui-bg-success`. |
|
||||
|
||||
#### Special colors
|
||||
|
||||
These colors are used for special purposes like ring, scrollbar, ...
|
||||
|
||||
| Token Name | Description |
|
||||
| ----------------------- | --------------------------------- |
|
||||
| `--bui-ring` | The color of the ring. |
|
||||
| `--bui-scrollbar` | The color of the scrollbar. |
|
||||
| `--bui-scrollbar-thumb` | The color of the scrollbar thumb. |
|
||||
|
||||
#### Font families
|
||||
|
||||
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.
|
||||
|
||||
| Token Name | Description |
|
||||
| -------------------- | ---------------------------------- |
|
||||
| `--bui-font-regular` | The sans-serif font for the theme. |
|
||||
| `--bui-font-mono` | The monospace font for the theme. |
|
||||
|
||||
#### Font weights
|
||||
|
||||
We have two font weights that we use across Backstage UI. Regular or Bold.
|
||||
|
||||
| Token Name | Description |
|
||||
| --------------------------- | -------------------------------------- |
|
||||
| `--bui-font-weight-regular` | The regular font weight for the theme. |
|
||||
| `--bui-font-weight-bold` | The bold font weight for the theme. |
|
||||
|
||||
#### Spacing
|
||||
|
||||
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 `--bui-space` and it will apply to all spacing values.
|
||||
|
||||
`--bui-space` is not used directly in any components but serve as an easy way to calculate the other values.
|
||||
|
||||
| Token Name | Description |
|
||||
| ------------- | ----------------------------------------------------------------- |
|
||||
| `--bui-space` | The base unit for the spacing system. Default value is `0.25rem.` |
|
||||
|
||||
#### Radius
|
||||
|
||||
We use a radius system to make sure that the components have a consistent look and feel.
|
||||
|
||||
| Token Name | Description |
|
||||
| ------------------- | --------------------------------------------------------- |
|
||||
| `--bui-radius-1` | The radius of the component. Default value is `0.125rem`. |
|
||||
| `--bui-radius-2` | The radius of the component. Default value is `0.25rem`. |
|
||||
| `--bui-radius-3` | The radius of the component. Default value is `0.5rem`. |
|
||||
| `--bui-radius-4` | The radius of the component. Default value is `0.75rem`. |
|
||||
| `--bui-radius-5` | The radius of the component. Default value is `1rem`. |
|
||||
| `--bui-radius-6` | The radius of the component. Default value is `1.25rem`. |
|
||||
| `--bui-radius-full` | The radius of the component. Default value is `9999px`. |
|
||||
|
||||
</details>
|
||||
|
||||
### Component class names
|
||||
|
||||
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 `.bui-` followed by the component name. Component props are represented using the `data-` attribute. That way, class names are easily identifiable.
|
||||
|
||||
## Create a theme for MUI (Legacy)
|
||||
|
||||
To customize the appearance of your Backstage app using the legacy MUI theming system, you can define your own theme by extending the built-in light or dark themes. This is done using the createUnifiedTheme utility provided by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. This function allows you to override key aspects of the theme—such as color palette, typography, spacing, and shape—while preserving Backstage’s base configuration and component compatibility.
|
||||
|
||||
The example below shows how to create a new theme based on the default light theme:
|
||||
|
||||
```ts title="packages/app/src/themes.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const lightTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
}),
|
||||
fontFamily: 'Comic Sans MS',
|
||||
defaultPageTheme: 'home',
|
||||
});
|
||||
|
||||
export const darkTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.dark,
|
||||
}),
|
||||
fontFamily: 'Comic Sans MS',
|
||||
defaultPageTheme: 'home',
|
||||
});
|
||||
```
|
||||
|
||||
You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the
|
||||
[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done.
|
||||
|
||||
<details>
|
||||
<summary>Example of a custom MUI theme</summary>
|
||||
|
||||
For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io).
|
||||
|
||||
```ts title="packages/app/src/themes.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
genPageTheme,
|
||||
palettes,
|
||||
shapes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: {
|
||||
...palettes.light,
|
||||
primary: {
|
||||
main: '#343b58',
|
||||
},
|
||||
secondary: {
|
||||
main: '#565a6e',
|
||||
},
|
||||
error: {
|
||||
main: '#8c4351',
|
||||
},
|
||||
warning: {
|
||||
main: '#8f5e15',
|
||||
},
|
||||
info: {
|
||||
main: '#34548a',
|
||||
},
|
||||
success: {
|
||||
main: '#485e30',
|
||||
},
|
||||
background: {
|
||||
default: '#d5d6db',
|
||||
paper: '#d5d6db',
|
||||
},
|
||||
banner: {
|
||||
info: '#34548a',
|
||||
error: '#8c4351',
|
||||
text: '#343b58',
|
||||
link: '#565a6e',
|
||||
},
|
||||
errorBackground: '#8c4351',
|
||||
warningBackground: '#8f5e15',
|
||||
infoBackground: '#343b58',
|
||||
navigation: {
|
||||
background: '#343b58',
|
||||
indicator: '#8f5e15',
|
||||
color: '#d5d6db',
|
||||
selectedColor: '#ffffff',
|
||||
},
|
||||
},
|
||||
}),
|
||||
defaultPageTheme: 'home',
|
||||
fontFamily: 'Comic Sans MS',
|
||||
/* below drives the header colors */
|
||||
pageTheme: {
|
||||
home: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
documentation: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave2,
|
||||
}),
|
||||
tool: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.round }),
|
||||
service: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
website: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
library: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
other: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
app: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
apis: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Custom Typography</summary>
|
||||
|
||||
When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'Arial, sans-serif',
|
||||
h1: {
|
||||
fontSize: 54,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
},
|
||||
h2: {
|
||||
fontSize: 40,
|
||||
fontWeight: 700,
|
||||
marginBottom: 8,
|
||||
},
|
||||
h3: {
|
||||
fontSize: 32,
|
||||
fontWeight: 700,
|
||||
marginBottom: 6,
|
||||
},
|
||||
h4: {
|
||||
fontWeight: 700,
|
||||
fontSize: 28,
|
||||
marginBottom: 6,
|
||||
},
|
||||
h5: {
|
||||
fontWeight: 700,
|
||||
fontSize: 24,
|
||||
marginBottom: 4,
|
||||
},
|
||||
h6: {
|
||||
fontWeight: 700,
|
||||
fontSize: 20,
|
||||
marginBottom: 2,
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
defaultTypography,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
...defaultTypography,
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'Roboto, sans-serif',
|
||||
h1: {
|
||||
fontSize: 72,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Custom Fonts</summary>
|
||||
|
||||
To add custom fonts, you first need to store the font so that it can be imported. We suggest creating the `assets/fonts` directory in your front-end application `src` folder.
|
||||
|
||||
You can then declare the font style following the `@font-face` syntax from [Material UI Typography](https://mui.com/material-ui/customization/typography/).
|
||||
|
||||
After that you can then utilize the `styleOverrides` of `MuiCssBaseline` under components to add a font to the `@font-face` array.
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2';
|
||||
|
||||
const myCustomFont = {
|
||||
fontFamily: 'My-Custom-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Custom-Font'),
|
||||
url(${MyCustomFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
fontFamily: 'My-Custom-Font',
|
||||
palette: palettes.light,
|
||||
components: {
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: {
|
||||
'@font-face': [myCustomFont],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
If you want to utilize different or multiple fonts, then you can set the top level `fontFamily` to what you want for your body, and then override `fontFamily` in `typography` to control fonts for various headings.
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2';
|
||||
import myAwesomeFont from '../assets/fonts/My-Awesome-Font.woff2';
|
||||
|
||||
const myCustomFont = {
|
||||
fontFamily: 'My-Custom-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Custom-Font'),
|
||||
url(${MyCustomFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
const myAwesomeFont = {
|
||||
fontFamily: 'My-Awesome-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Awesome-Font'),
|
||||
url(${myAwesomeFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
fontFamily: 'My-Custom-Font',
|
||||
components: {
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: {
|
||||
'@font-face': [myCustomFont, myAwesomeFont],
|
||||
},
|
||||
},
|
||||
},
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
...defaultTypography,
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'My-Custom-Font',
|
||||
h1: {
|
||||
fontSize: 72,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
fontFamily: 'My-Awesome-Font',
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Overriding Backstage and Material UI components styles</summary>
|
||||
|
||||
When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this:
|
||||
|
||||
```tsx
|
||||
const useStyles = makeStyles<BackstageTheme>(
|
||||
theme => ({
|
||||
header: {
|
||||
padding: theme.spacing(3),
|
||||
boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)',
|
||||
backgroundImage: theme.page.backgroundImage,
|
||||
},
|
||||
}),
|
||||
{ name: 'BackstageHeader' },
|
||||
);
|
||||
```
|
||||
|
||||
Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override.
|
||||
|
||||
Here's how you would do that:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
}),
|
||||
fontFamily: 'Comic Sans MS',
|
||||
defaultPageTheme: 'home',
|
||||
components: {
|
||||
BackstageHeader: {
|
||||
styleOverrides: {
|
||||
header: ({ theme }) => ({
|
||||
width: 'auto',
|
||||
margin: '20px',
|
||||
boxShadow: 'none',
|
||||
borderBottom: `4px solid ${theme.palette.primary.main}`,
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
id: logo
|
||||
title: Customizing Your Logo
|
||||
sidebar_label: Logo
|
||||
description: Learn how to customize your logo.
|
||||
---
|
||||
|
||||
In addition to a custom theme, you can also customize the logo displayed at the far top left of the site.
|
||||
|
||||
In your frontend app, locate `src/components/Root/` folder. You'll find two components:
|
||||
|
||||
- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened.
|
||||
- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed.
|
||||
|
||||
To replace the images, you can simply replace the relevant code in those components with raw SVG definitions.
|
||||
|
||||
You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code:
|
||||
|
||||
```tsx
|
||||
import MyCustomLogoFull from './logo/my-company-logo.png';
|
||||
|
||||
const LogoFull = () => {
|
||||
return <img src={MyCustomLogoFull} />;
|
||||
};
|
||||
```
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
id: sidebar
|
||||
title: Customizing Your Sidebar
|
||||
sidebar_label: Sidebar
|
||||
description: Learn how to customize the look and feel of your Sidebar.
|
||||
---
|
||||
|
||||
As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar.
|
||||
|
||||
## Sidebar Sub-menu
|
||||
|
||||
For this example we'll show you how you can expand the sidebar with a sub-menu:
|
||||
|
||||
1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives
|
||||
2. Then we want to add the following import for `useApp`:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
import { useApp } from '@backstage/core-plugin-api';
|
||||
```
|
||||
|
||||
3. Then update the `@backstage/core-components` import like this:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
import {
|
||||
Sidebar,
|
||||
sidebarConfig,
|
||||
SidebarDivider,
|
||||
SidebarGroup,
|
||||
SidebarItem,
|
||||
SidebarPage,
|
||||
SidebarScrollWrapper,
|
||||
SidebarSpace,
|
||||
useSidebarOpenState,
|
||||
Link,
|
||||
/* highlight-add-start */
|
||||
GroupIcon,
|
||||
SidebarSubmenu,
|
||||
SidebarSubmenuItem,
|
||||
/* highlight-add-end */
|
||||
} from '@backstage/core-components';
|
||||
```
|
||||
|
||||
4. Finally replace `<SidebarItem icon={HomeIcon} to="catalog" text="Home" />` with this:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
<SidebarItem icon={HomeIcon} to="catalog" text="Home">
|
||||
<SidebarSubmenu title="Catalog">
|
||||
<SidebarSubmenuItem
|
||||
title="Domains"
|
||||
to="catalog?filters[kind]=domain"
|
||||
icon={useApp().getSystemIcon('kind:domain')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Systems"
|
||||
to="catalog?filters[kind]=system"
|
||||
icon={useApp().getSystemIcon('kind:system')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Components"
|
||||
to="catalog?filters[kind]=component"
|
||||
icon={useApp().getSystemIcon('kind:component')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="APIs"
|
||||
to="catalog?filters[kind]=api"
|
||||
icon={useApp().getSystemIcon('kind:api')}
|
||||
/>
|
||||
<SidebarDivider />
|
||||
<SidebarSubmenuItem
|
||||
title="Resources"
|
||||
to="catalog?filters[kind]=resource"
|
||||
icon={useApp().getSystemIcon('kind:resource')}
|
||||
/>
|
||||
<SidebarDivider />
|
||||
<SidebarSubmenuItem
|
||||
title="Groups"
|
||||
to="catalog?filters[kind]=group"
|
||||
icon={useApp().getSystemIcon('kind:group')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Users"
|
||||
to="catalog?filters[kind]=user"
|
||||
icon={useApp().getSystemIcon('kind:user')}
|
||||
/>
|
||||
</SidebarSubmenu>
|
||||
</SidebarItem>
|
||||
```
|
||||
|
||||
When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this:
|
||||
|
||||

|
||||
|
||||
You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar)
|
||||
@@ -103,6 +103,4 @@ accessibility.
|
||||
[7]: https://v4.mui.com/components/cards/
|
||||
[8]: https://v4.mui.com/customization/palette/#default-values
|
||||
[9]: https://v4.mui.com/customization/typography/
|
||||
[10]: https://backstage.io/docs/getting-started/app-custom-theme
|
||||
[11]: https://backstage.io/docs/getting-started/app-custom-theme#overriding-backstage-and-material-ui-components-styles
|
||||
[12]: https://v4.mui.com/customization/default-theme/#explore
|
||||
[10]: https://backstage.io/docs/conf/user-interface
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ your own plugin for Backstage.
|
||||
**[Discord](https://discord.gg/backstage-687207715902193673)** - all design questions should be
|
||||
directed to the _#design_ channel.
|
||||
|
||||
**[Customize Backstage's look and feel](https://backstage.io/docs/getting-started/app-custom-theme)** -
|
||||
**[Customizing Your App's UI](https://backstage.io/docs/conf/user-interface)** -
|
||||
How to customize the look and feel of your Backstage instance by extending the
|
||||
theme.
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ indexBuilder.addCollator({
|
||||
The default highlighting styling for matched terms in search results is your
|
||||
browsers default styles for the `<mark>` HTML tag. If you want to customize
|
||||
how highlighted terms look you can follow Backstage's guide on how to
|
||||
[Customize the look-and-feel of your App](https://backstage.io/docs/getting-started/app-custom-theme)
|
||||
[Customizing Your App's UI](https://backstage.io/docs/conf/user-interface)
|
||||
to create an override with your preferred styling.
|
||||
|
||||
For example, using the new MUI V4+V5 unified theming method, the following will result
|
||||
|
||||
@@ -571,10 +571,8 @@ Finally, entity predicates also support value operators that can be used in plac
|
||||
```json
|
||||
{
|
||||
"filter": {
|
||||
{
|
||||
"kind": "component",
|
||||
"spec.type": { "$in": ["service", "website"] }
|
||||
},
|
||||
"kind": "component",
|
||||
"spec.type": { "$in": ["service", "website"] }
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -695,6 +693,6 @@ filter:
|
||||
relations:
|
||||
$contains:
|
||||
type: ownedBy
|
||||
target:
|
||||
targetRef:
|
||||
$in: [group:default/admins, group:default/viewers]
|
||||
```
|
||||
|
||||
@@ -90,6 +90,35 @@ also write a _custom processor_ to convert between the existing system and
|
||||
Backstage's descriptor format. This is documented in
|
||||
[External Integrations](external-integrations.md).
|
||||
|
||||
### Processor configuration
|
||||
|
||||
You can configure processors under the `catalog.processorOptions` key. You can define
|
||||
options for each processor by its name. With the processor options you can disable
|
||||
a processor or set its priority.
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
processorOptions:
|
||||
processorName:
|
||||
disabled: false # Defaults to false
|
||||
priority: 100
|
||||
```
|
||||
|
||||
The priority is a number defining the order in which processors are executed. The lower the number,
|
||||
the higher the priority. The default priority is `20`.
|
||||
|
||||
## Provider configuration
|
||||
|
||||
It's possible to also disable entity providers using the config. You can configure providers
|
||||
under the `catalog.providerOptions` key. The key is the provider name.
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
providerOptions:
|
||||
providerName:
|
||||
disabled: true
|
||||
```
|
||||
|
||||
## Catalog Rules
|
||||
|
||||
By default, the catalog will only allow the ingestion of entities with the kind
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: addons
|
||||
id: addons--new
|
||||
title: TechDocs Addons
|
||||
description: How to find, use, or create TechDocs Addons.
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md) which is still in alpha and is only supported by a small number of plugins.
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md) which is still in alpha and is only supported by a small number of plugins. If you are on the [old frontend system](./getting-started.md#adding-techdocs-frontend-plugin) you may want to read [its own article](./addons.md) instead.
|
||||
:::
|
||||
|
||||
## Concepts
|
||||
|
||||
@@ -34,6 +34,14 @@ const examplePage = createExtension({
|
||||
});
|
||||
```
|
||||
|
||||
### `title`
|
||||
|
||||
| id | type |
|
||||
| :----------: | :------: |
|
||||
| `core.title` | `string` |
|
||||
|
||||
The `title` data reference can be used for defining the extension input/output of string titles.
|
||||
|
||||
### `routePath`
|
||||
|
||||
| id | type |
|
||||
|
||||
@@ -1,613 +0,0 @@
|
||||
---
|
||||
id: app-custom-theme
|
||||
title: Customize the look-and-feel of your App
|
||||
description: Documentation on Customizing look and feel of the App
|
||||
---
|
||||
|
||||
Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes.
|
||||
|
||||
## Creating a Custom Theme
|
||||
|
||||
The easiest way to create a new theme is to use the `createUnifiedTheme` function exported by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You can use it to override some basic parameters of the default theme such as the color palette and font.
|
||||
|
||||
For example, you can create a new theme based on the default light theme like this:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
}),
|
||||
fontFamily: 'Comic Sans MS',
|
||||
defaultPageTheme: 'home',
|
||||
});
|
||||
```
|
||||
|
||||
:::note Note
|
||||
|
||||
we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized.
|
||||
|
||||
:::
|
||||
|
||||
You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the
|
||||
[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done.
|
||||
|
||||
## Using your Custom Theme
|
||||
|
||||
To add a custom theme to your Backstage app, you pass it as configuration to `createApp`.
|
||||
|
||||
For example, adding the theme that we created in the previous section can be done like this:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { createApp } from '@backstage/app-defaults';
|
||||
import { ThemeProvider } from '@material-ui/core/styles';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import LightIcon from '@material-ui/icons/WbSunny';
|
||||
import { UnifiedThemeProvider} from '@backstage/theme';
|
||||
import { myTheme } from './themes/myTheme';
|
||||
|
||||
const app = createApp({
|
||||
apis: ...,
|
||||
plugins: ...,
|
||||
themes: [{
|
||||
id: 'my-theme',
|
||||
title: 'My Custom Theme',
|
||||
variant: 'light',
|
||||
icon: <LightIcon />,
|
||||
Provider: ({ children }) => (
|
||||
<UnifiedThemeProvider theme={myTheme} children={children} />
|
||||
),
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme).
|
||||
|
||||
## Example of a custom theme
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
genPageTheme,
|
||||
palettes,
|
||||
shapes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: {
|
||||
...palettes.light,
|
||||
primary: {
|
||||
main: '#343b58',
|
||||
},
|
||||
secondary: {
|
||||
main: '#565a6e',
|
||||
},
|
||||
error: {
|
||||
main: '#8c4351',
|
||||
},
|
||||
warning: {
|
||||
main: '#8f5e15',
|
||||
},
|
||||
info: {
|
||||
main: '#34548a',
|
||||
},
|
||||
success: {
|
||||
main: '#485e30',
|
||||
},
|
||||
background: {
|
||||
default: '#d5d6db',
|
||||
paper: '#d5d6db',
|
||||
},
|
||||
banner: {
|
||||
info: '#34548a',
|
||||
error: '#8c4351',
|
||||
text: '#343b58',
|
||||
link: '#565a6e',
|
||||
},
|
||||
errorBackground: '#8c4351',
|
||||
warningBackground: '#8f5e15',
|
||||
infoBackground: '#343b58',
|
||||
navigation: {
|
||||
background: '#343b58',
|
||||
indicator: '#8f5e15',
|
||||
color: '#d5d6db',
|
||||
selectedColor: '#ffffff',
|
||||
},
|
||||
},
|
||||
}),
|
||||
defaultPageTheme: 'home',
|
||||
fontFamily: 'Comic Sans MS',
|
||||
/* below drives the header colors */
|
||||
pageTheme: {
|
||||
home: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
documentation: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave2,
|
||||
}),
|
||||
tool: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.round }),
|
||||
service: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
website: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
library: genPageTheme({
|
||||
colors: ['#8c4351', '#343b58'],
|
||||
shape: shapes.wave,
|
||||
}),
|
||||
other: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
app: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
apis: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io).
|
||||
|
||||
## Custom Typography
|
||||
|
||||
When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'Arial, sans-serif',
|
||||
h1: {
|
||||
fontSize: 54,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
},
|
||||
h2: {
|
||||
fontSize: 40,
|
||||
fontWeight: 700,
|
||||
marginBottom: 8,
|
||||
},
|
||||
h3: {
|
||||
fontSize: 32,
|
||||
fontWeight: 700,
|
||||
marginBottom: 6,
|
||||
},
|
||||
h4: {
|
||||
fontWeight: 700,
|
||||
fontSize: 28,
|
||||
marginBottom: 6,
|
||||
},
|
||||
h5: {
|
||||
fontWeight: 700,
|
||||
fontSize: 24,
|
||||
marginBottom: 4,
|
||||
},
|
||||
h6: {
|
||||
fontWeight: 700,
|
||||
fontSize: 20,
|
||||
marginBottom: 2,
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
defaultTypography,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
...defaultTypography,
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'Roboto, sans-serif',
|
||||
h1: {
|
||||
fontSize: 72,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
## Custom Fonts
|
||||
|
||||
To add custom fonts, you first need to store the font so that it can be imported. We suggest creating the `assets/fonts` directory in your front-end application `src` folder.
|
||||
|
||||
You can then declare the font style following the `@font-face` syntax from [Material UI Typography](https://mui.com/material-ui/customization/typography/).
|
||||
|
||||
After that you can then utilize the `styleOverrides` of `MuiCssBaseline` under components to add a font to the `@font-face` array.
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2';
|
||||
|
||||
const myCustomFont = {
|
||||
fontFamily: 'My-Custom-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Custom-Font'),
|
||||
url(${MyCustomFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
fontFamily: 'My-Custom-Font',
|
||||
palette: palettes.light,
|
||||
components: {
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: {
|
||||
'@font-face': [myCustomFont],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
If you want to utilize different or multiple fonts, then you can set the top level `fontFamily` to what you want for your body, and then override `fontFamily` in `typography` to control fonts for various headings.
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2';
|
||||
import myAwesomeFont from '../assets/fonts/My-Awesome-Font.woff2';
|
||||
|
||||
const myCustomFont = {
|
||||
fontFamily: 'My-Custom-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Custom-Font'),
|
||||
url(${MyCustomFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
const myAwesomeFont = {
|
||||
fontFamily: 'My-Awesome-Font',
|
||||
fontStyle: 'normal',
|
||||
fontDisplay: 'swap',
|
||||
fontWeight: 300,
|
||||
src: `
|
||||
local('My-Awesome-Font'),
|
||||
url(${myAwesomeFont}) format('woff2'),
|
||||
`,
|
||||
};
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
fontFamily: 'My-Custom-Font',
|
||||
components: {
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: {
|
||||
'@font-face': [myCustomFont, myAwesomeFont],
|
||||
},
|
||||
},
|
||||
},
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
typography: {
|
||||
...defaultTypography,
|
||||
htmlFontSize: 16,
|
||||
fontFamily: 'My-Custom-Font',
|
||||
h1: {
|
||||
fontSize: 72,
|
||||
fontWeight: 700,
|
||||
marginBottom: 10,
|
||||
fontFamily: 'My-Awesome-Font',
|
||||
},
|
||||
},
|
||||
defaultPageTheme: 'home',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
## Overriding Backstage and Material UI components styles
|
||||
|
||||
When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this:
|
||||
|
||||
```tsx
|
||||
const useStyles = makeStyles<BackstageTheme>(
|
||||
theme => ({
|
||||
header: {
|
||||
padding: theme.spacing(3),
|
||||
boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)',
|
||||
backgroundImage: theme.page.backgroundImage,
|
||||
},
|
||||
}),
|
||||
{ name: 'BackstageHeader' },
|
||||
);
|
||||
```
|
||||
|
||||
Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override.
|
||||
|
||||
Here's how you would do that:
|
||||
|
||||
```ts title="packages/app/src/theme/myTheme.ts"
|
||||
import {
|
||||
createBaseThemeOptions,
|
||||
createUnifiedTheme,
|
||||
palettes,
|
||||
} from '@backstage/theme';
|
||||
|
||||
export const myTheme = createUnifiedTheme({
|
||||
...createBaseThemeOptions({
|
||||
palette: palettes.light,
|
||||
}),
|
||||
fontFamily: 'Comic Sans MS',
|
||||
defaultPageTheme: 'home',
|
||||
components: {
|
||||
BackstageHeader: {
|
||||
styleOverrides: {
|
||||
header: ({ theme }) => ({
|
||||
width: 'auto',
|
||||
margin: '20px',
|
||||
boxShadow: 'none',
|
||||
borderBottom: `4px solid ${theme.palette.primary.main}`,
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Custom Logo
|
||||
|
||||
In addition to a custom theme, you can also customize the logo displayed at the far top left of the site.
|
||||
|
||||
In your frontend app, locate `src/components/Root/` folder. You'll find two components:
|
||||
|
||||
- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened.
|
||||
- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed.
|
||||
|
||||
To replace the images, you can simply replace the relevant code in those components with raw SVG definitions.
|
||||
|
||||
You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code:
|
||||
|
||||
```tsx
|
||||
import MyCustomLogoFull from './logo/my-company-logo.png';
|
||||
|
||||
const LogoFull = () => {
|
||||
return <img src={MyCustomLogoFull} />;
|
||||
};
|
||||
```
|
||||
|
||||
## 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) => (
|
||||
<SvgIcon {...props} viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
width="1em"
|
||||
height="1em"
|
||||
display="inline-block"
|
||||
d="M11.6335 10.8398C11.6335 11.6563 12.065 12.9922 13.0863 12.9922C14.1075 12.9922 14.539 11.6563 14.539 10.8398C14.539 10.0234 14.1075 8.6875 13.0863 8.6875C12.065 8.6875 11.6335 10.0234 11.6335 10.8398V10.8398ZM2.38419e-07 8.86719C2.38419e-07 10.1133 0.126667 11.4336 0.692709 12.5781C2.19292 15.5703 6.3175 15.5 9.27042 15.5C12.2708 15.5 16.6408 15.6055 18.2004 12.5781C18.7783 11.4453 19 10.1133 19 8.86719C19 7.23047 18.4498 5.68359 17.3573 4.42969C17.5631 3.8125 17.6621 3.16406 17.6621 2.52344C17.6621 1.68359 17.4681 1.26172 17.0842 0.5C15.291 0.5 14.1431 0.851562 12.7775 1.90625C11.6296 1.63672 10.45 1.51562 9.26646 1.51562C8.19771 1.51562 7.12104 1.62891 6.08396 1.875C4.73813 0.832031 3.59021 0.5 1.81687 0.5C1.42896 1.26172 1.23896 1.68359 1.23896 2.52344C1.23896 3.16406 1.34188 3.80078 1.54375 4.40625C0.455209 5.67188 2.38419e-07 7.23047 2.38419e-07 8.86719V8.86719ZM2.54521 10.8398C2.54521 9.125 3.60208 7.61328 5.45458 7.61328C6.20271 7.61328 6.91917 7.74609 7.67125 7.84766C8.26104 7.9375 8.85083 7.97266 9.45646 7.97266C10.0581 7.97266 10.6479 7.9375 11.2417 7.84766C11.9819 7.74609 12.7063 7.61328 13.4583 7.61328C15.3108 7.61328 16.3677 9.125 16.3677 10.8398C16.3677 14.2695 13.1852 14.7969 10.4144 14.7969H8.50646C5.72375 14.7969 2.54521 14.2734 2.54521 10.8398V10.8398ZM5.81479 8.6875C6.83604 8.6875 7.2675 10.0234 7.2675 10.8398C7.2675 11.6563 6.83604 12.9922 5.81479 12.9922C4.79354 12.9922 4.36208 11.6563 4.36208 10.8398C4.36208 10.0234 4.79354 8.6875 5.81479 8.6875Z"
|
||||
/>
|
||||
</SvgIcon>
|
||||
);
|
||||
```
|
||||
|
||||
#### 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`
|
||||
|
||||
:::
|
||||
|
||||
## Custom Sidebar
|
||||
|
||||
As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar.
|
||||
|
||||
### Sidebar Sub-menu
|
||||
|
||||
For this example we'll show you how you can expand the sidebar with a sub-menu:
|
||||
|
||||
1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives
|
||||
2. Then we want to add the following import for `useApp`:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
import { useApp } from '@backstage/core-plugin-api';
|
||||
```
|
||||
|
||||
3. Then update the `@backstage/core-components` import like this:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
import {
|
||||
Sidebar,
|
||||
sidebarConfig,
|
||||
SidebarDivider,
|
||||
SidebarGroup,
|
||||
SidebarItem,
|
||||
SidebarPage,
|
||||
SidebarScrollWrapper,
|
||||
SidebarSpace,
|
||||
useSidebarOpenState,
|
||||
Link,
|
||||
/* highlight-add-start */
|
||||
GroupIcon,
|
||||
SidebarSubmenu,
|
||||
SidebarSubmenuItem,
|
||||
/* highlight-add-end */
|
||||
} from '@backstage/core-components';
|
||||
```
|
||||
|
||||
4. Finally replace `<SidebarItem icon={HomeIcon} to="catalog" text="Home" />` with this:
|
||||
|
||||
```tsx title="packages/app/src/components/Root/Root.tsx"
|
||||
<SidebarItem icon={HomeIcon} to="catalog" text="Home">
|
||||
<SidebarSubmenu title="Catalog">
|
||||
<SidebarSubmenuItem
|
||||
title="Domains"
|
||||
to="catalog?filters[kind]=domain"
|
||||
icon={useApp().getSystemIcon('kind:domain')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Systems"
|
||||
to="catalog?filters[kind]=system"
|
||||
icon={useApp().getSystemIcon('kind:system')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Components"
|
||||
to="catalog?filters[kind]=component"
|
||||
icon={useApp().getSystemIcon('kind:component')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="APIs"
|
||||
to="catalog?filters[kind]=api"
|
||||
icon={useApp().getSystemIcon('kind:api')}
|
||||
/>
|
||||
<SidebarDivider />
|
||||
<SidebarSubmenuItem
|
||||
title="Resources"
|
||||
to="catalog?filters[kind]=resource"
|
||||
icon={useApp().getSystemIcon('kind:resource')}
|
||||
/>
|
||||
<SidebarDivider />
|
||||
<SidebarSubmenuItem
|
||||
title="Groups"
|
||||
to="catalog?filters[kind]=group"
|
||||
icon={useApp().getSystemIcon('kind:group')}
|
||||
/>
|
||||
<SidebarSubmenuItem
|
||||
title="Users"
|
||||
to="catalog?filters[kind]=user"
|
||||
icon={useApp().getSystemIcon('kind:user')}
|
||||
/>
|
||||
</SidebarSubmenu>
|
||||
</SidebarItem>
|
||||
```
|
||||
|
||||
When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this:
|
||||
|
||||

|
||||
|
||||
You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar)
|
||||
|
||||
## Custom Homepage
|
||||
|
||||
In addition to a custom theme, a custom logo, you can also customize the
|
||||
homepage of your app. Read the full guide on the [next page](homepage.md).
|
||||
|
||||
## Migrating to Material UI v5
|
||||
|
||||
We now support Material UI v5 in Backstage. Check out our [migration guide](../tutorials/migrate-to-mui5.md) to get started.
|
||||
@@ -157,7 +157,7 @@ Choose the correct next steps for your user role, if you're likely to be deployi
|
||||
- Configuring Backstage
|
||||
|
||||
- [Adding plugins](./configure-app-with-plugins.md)
|
||||
- [Customizing the theme](./app-custom-theme.md)
|
||||
- [Customizing Your App's UI](../conf/user-interface/index.md)
|
||||
- [Populating the homepage](./homepage.md)
|
||||
|
||||
### Developer
|
||||
|
||||
@@ -27,7 +27,7 @@ yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-gitlab
|
||||
|
||||
Then add the following to your backend initialization:
|
||||
|
||||
```ts title="packages/backend/src/index.ts
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
// optional if you want HTTP endpoints to receive external events
|
||||
// backend.add(import('@backstage/plugin-events-backend'));
|
||||
// optional if you want to use AWS SQS instead of HTTP endpoints to receive external events
|
||||
@@ -49,7 +49,7 @@ Further documentation:
|
||||
- [Events Plugin](https://github.com/backstage/backstage/tree/master/plugins/events-backend/README.md)
|
||||
- [GitLab Module for the Events Plugin](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md)
|
||||
|
||||
### Installation with Legacy Backend System
|
||||
### Installation with Legacy Backend System (skip if you are using Backstage v1.31.0 or later)
|
||||
|
||||
#### Installation without Events Support
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ notifications:
|
||||
- token: xoxb-XXXXXXXXX
|
||||
broadcastChannels: # Optional, if you wish to support broadcast notifications.
|
||||
- C12345678
|
||||
username: 'Backstage Bot' # Optional, defaults to the name of the Slack App.
|
||||
```
|
||||
|
||||
Multiple instances can be added in the `slack` array, allowing you to have multiple configurations if you need to send
|
||||
|
||||
@@ -10,285 +10,232 @@ Backstage is organized into three main components, each catering to different gr
|
||||
|
||||
- Core - This includes the base functionality developed by core developers within the open-source project.
|
||||
- App - The app represents a deployed instance of a Backstage application, customized and maintained by app developers, typically a productivity team within an organization. It integrates core functionalities with additional plugins.
|
||||
- Plugins - These provide additional functionalities to enhance the usefulness of your Backstage app. Plugins can be company-specific or open-sourced and reusable. At Spotify, we have over 100 plugins created by more than 50 different teams, significantly enriching the unified developer experience by incorporating contributions from various infrastructure teams.
|
||||
- Plugins - These provide additional functionalities to enhance the usefulness of your Backstage app. Plugins can be company-specific or open-sourced and reusable.
|
||||
|
||||
## Overview
|
||||
|
||||
The following diagram shows how Backstage might look when deployed inside a
|
||||
company which uses the Tech Radar plugin, the Lighthouse plugin, the CircleCI
|
||||
plugin and the software catalog.
|
||||
The following diagram shows a high level view of the overall architecture of Backstage. Running this architecture in a real environment typically involves
|
||||
containerizing the components. Various commands are provided for accomplishing this.
|
||||
|
||||
There are 3 main components in this architecture:
|
||||
|
||||
1. The core Backstage UI
|
||||
2. The UI plugins and their backing services
|
||||
3. Databases
|
||||
- The [frontend](#frontend-building-blocks) includes the core Backstage [UI](#user-interface) which is an [extension](#extensions) that interacts directly with the user to present the information from the integrated core feature plugins, and other plugins added by a user.
|
||||
- The [backend](#backend-building-blocks) includes the backend plugins, [core services](https://backstage.io/docs/backend-system/core-services/index), and other services. This is the server-side part of Backstage that is responsible for wiring things together. You can deploy more than one backend, and more than one backend container, depending on your need to scale and isolate individual features.
|
||||
- Databases host your Backstage data.
|
||||
|
||||
Running this architecture in a real environment typically involves
|
||||
containerizing the components. Various commands are provided for accomplishing
|
||||
this.
|
||||

|
||||
|
||||

|
||||
## Frontend building blocks
|
||||
|
||||
## User Interface
|
||||
The architectural diagram provides an overview of the different building blocks and the other blocks that each of them interacts with.
|
||||
|
||||
The UI is a thin, client-side wrapper around a set of plugins. It provides some
|
||||
core UI components and libraries for shared activities such as config
|
||||
management. [[live demo](https://demo.backstage.io/catalog)]
|
||||
### App
|
||||
|
||||
This is the app instance itself that you create and use as the root of your Backstage frontend application. It does not have any direct functionality in and of itself, but is simply responsible for wiring things together.
|
||||
|
||||
### Extensions
|
||||
|
||||
[Extensions](../frontend-system/architecture/20-extensions.md) are the building blocks that build out both the visual and non-visual structure of the application. There are both built-in extensions provided by the app itself as well as extensions provided by plugins. Each extension is attached to a parent with which it shares data and can have any number of children of its own. It is up to the app to wire together all extensions into a single tree known as the app extension tree. It is from this structure that the entire app can then be instantiated and rendered.
|
||||
|
||||
#### User Interface
|
||||
|
||||
The UI is one of the extensions in the frontend. It is a thin, client-side wrapper around a set of plugins. It provides some core UI components and libraries for shared activities such as config management. [[live demo](https://demo.backstage.io/catalog)]
|
||||
|
||||

|
||||
|
||||
Each plugin typically makes itself available in the UI on a dedicated URL. For
|
||||
example, the Lighthouse plugin is registered with the UI on `/lighthouse`.
|
||||
[[learn more](https://backstage.io/blog/2020/04/06/lighthouse-plugin)]
|
||||
Each plugin typically makes itself available in the UI on a dedicated URL. For example, the Service Catalog plugin is registered with the UI on `/catalog`.
|
||||
|
||||

|
||||
### Frontend plugins
|
||||
|
||||
The CircleCI plugin is available on `/circleci`.
|
||||
Plugins provide the actual features inside an app. The size of a plugin can range from a tiny component to an entire new system in which other plugins can be composed and integrated. Plugins can be completely standalone or built on top of each other to extend existing plugins and augment their features. Plugins can communicate with each other by composing their extensions or by sharing Utility APIs and routes.
|
||||
|
||||

|
||||
Backstage includes the following set of core plugins:
|
||||
|
||||
## Plugins and plugin backends
|
||||
- [Software Catalog](../features/software-catalog/index.md) - A centralized system that contains metadata for all your software, such as services, websites, libraries, ML models, data pipelines, and so on. It can also contain metadata for the physical or virtual infrastructure needed to operate a piece of software. The software catalog can be viewed and searched through a UI.
|
||||
- [Software Templates](../features/software-templates/index.md) - A tool to help you create components inside Backstage. A template can load skeletons of code, include some variables, and then publish the template to a location, such as GitHub.
|
||||
- [TechDocs](https://backstage.io/docs/features/techdocs/) - A docs-like-code solution built into Backstage. Documentation is written in Markdown files which lives together with the code.
|
||||
- [Kubernetes](../features/kubernetes/index.md) - A tool that allows developers to check the health of their services whether it is on a local host or in production.
|
||||
- [Search](https://backstage.io/docs/features/search/) - Search for information in the Backstage ecosystem. You can customize the look and feel of each search result and use your own search engine.
|
||||
|
||||
Each plugin is a client side application which mounts itself on the UI. Plugins
|
||||
are written in TypeScript or JavaScript. They each live in their own directory
|
||||
in the `plugins` folder. For example, the source code for the catalog plugin
|
||||
is available at
|
||||
[plugins/catalog](https://github.com/backstage/backstage/tree/master/plugins/catalog).
|
||||
[Plugin architecture](#plugin-architecture) provides greater detail about the architecture of the plugins themselves.
|
||||
|
||||
### Installing plugins
|
||||
### Extension Overrides
|
||||
|
||||
Plugins are typically installed as React components in your Backstage
|
||||
application. For example,
|
||||
[here](https://github.com/backstage/backstage/blob/master/packages/app/src/App.tsx)
|
||||
is a file that imports many full-page plugins in the Backstage sample app.
|
||||
In addition to the built-in extensions and extensions provided by plugins, it is also possible to install [extension overrides](../frontend-system/architecture/25-extension-overrides.md). This is a collection of extensions with high priority that can replace existing extensions. They can for example be used to override an individual extension provided by a plugin, or install a completely new extension, such as a new app theme.
|
||||
|
||||
An example of one of these plugin components is the `CatalogIndexPage`, which is
|
||||
a full-page view that allows you to browse entities in the Backstage catalog. It
|
||||
is installed in the app by importing it and adding it as an element like this:
|
||||
### Utility APIs
|
||||
|
||||
```tsx
|
||||
import { CatalogIndexPage } from '@backstage/plugin-catalog';
|
||||
[Utility APIs](../api/utility-apis.md) provide functionality that makes it easier to build plugins, make it possible for plugins to share functionality with other plugins, as well as serve as a customization point for integrators to change the behaviour of the app. Each Utility API is defined by a TypeScript interface as well as a reference used to access the implementations. The implementations of Utility APIs are defined by extensions that are provided and can be overridden the same as any other extension.
|
||||
|
||||
...
|
||||
### Routes
|
||||
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
...
|
||||
<Route path="/catalog" element={<CatalogIndexPage />} />
|
||||
...
|
||||
</FlatRoutes>
|
||||
);
|
||||
```
|
||||
The [Backstage routing system](../frontend-system/architecture/36-routes.md) adds a layer of indirection that makes it possible for plugins to route to each other's extensions without explicit knowledge of what URL paths the extensions are rendered at or if they even exist at all. It makes it possible for plugins to share routes with each other and dynamically generate concrete links at runtime. It is the responsibility of the app to resolve these links to actual URLs, but it is also possible for integrators to define their own route bindings that decide how the links should be resolved. The routing system also lets plugins define internal routes, aiding in the linking to different content in the same plugin.
|
||||
|
||||
Note that we use `"/catalog"` as our path to this plugin page, but we can choose
|
||||
any route we want for the page, as long as it doesn't collide with the routes
|
||||
that we choose for the other plugins in the app.
|
||||
## Backend building blocks
|
||||
|
||||
These components that are exported from plugins are referred to as "Plugin
|
||||
Extension Components", or "Extension Components". They are regular React
|
||||
components, but in addition to being able to be rendered by React, they also
|
||||
contain various pieces of metadata that is used to wire together the entire app.
|
||||
Extension components are created using `create*Extension` methods, which you can
|
||||
read more about in the
|
||||
[composability documentation](../plugins/composability.md).
|
||||
The architectural diagram provides an overview of the different building blocks, and the other blocks that each of them interact with.
|
||||
|
||||
As of this moment, there is no config based install procedure for plugins. Some
|
||||
code changes are required.
|
||||
### Backend
|
||||
|
||||
### Plugin architecture
|
||||
This is the [backend instance](../backend-system/architecture/02-backends.md) itself, which you can think of as the unit of deployment. It does not have any functionality in and of itself, but is simply responsible for wiring things together.
|
||||
|
||||
It is up to you to decide how many different backends you want to deploy. You can have all features in a single one, or split things out into multiple smaller deployments, depending on your need to scale and isolate individual features.
|
||||
|
||||
### Backend plugins
|
||||
|
||||
[Plugins](../backend-system/architecture/04-plugins.md) provide the actual features. They operate completely independently of each other. If plugins want to communicate with each other, they must do so over the wire. There can be no direct communication between plugins through code. Because of this constraint, each plugin can be considered to be its own microservice.
|
||||
|
||||
[Plugin architecture](#plugin-architecture) provides greater detail about the architecture of the plugins themselves.
|
||||
|
||||
### Services
|
||||
|
||||
[Services](../backend-system/architecture/03-services.md) provide utilities to help make it simpler to implement plugins, so that each plugin doesn't need to implement everything from scratch. There are many built-in core services, such as the ones for logging, database access, and reading configuration, but you can also import third-party services, or create your own.
|
||||
|
||||
Services are also a customization point for individual backend installations. You can override services with your own implementations, as well as make smaller customizations to existing services.
|
||||
|
||||
### Extension Points
|
||||
|
||||
Many plugins have ways in which you can extend them, for example entity providers for the Catalog, or custom actions for the Scaffolder. These extension patterns are now encoded into Extension Points.
|
||||
|
||||
[Extension Points](../backend-system/architecture/05-extension-points.md) look a little bit like services, since you depend on them just like you would a service. A key difference is that extension points are registered and provided by plugins or modules themselves, based on what customizations each of them want to expose.
|
||||
|
||||
Extension Points are exported separately from the plugin or module instance itself, and it is possible to expose multiple different extension points at once. This makes it easier to evolve and deprecate individual Extension Points over time, rather than dealing with a single large API surface.
|
||||
|
||||
### Modules
|
||||
|
||||
[Modules](../backend-system/architecture/06-modules.md) use Extension Points to add new features to other plugins or modules. They might for example add an individual Catalog Entity Provider, or one or more Scaffolder Actions.
|
||||
|
||||
Each module may only use Extension Points that belong to a single plugin, and the module must be deployed together with that plugin in the same backend instance. Modules may only communicate with their plugin or other modules through the registered extension points.
|
||||
|
||||
Just like plugins, modules also have access to services and can depend on their own service implementations. They will however share services with the plugin that they extend - there are no module-specific service implementations.
|
||||
|
||||
## Databases
|
||||
|
||||
The databases host your Backstage data. The Backstage backend and its built-in plugins are based on the [Knex](http://knexjs.org/) library, and set up a separate logical database per plugin. This gives great isolation and lets them perform migrations and evolve separately from each other.
|
||||
|
||||
The Knex library supports a multitude of databases, but Backstage at this time of writing is tested primarily against two of them:
|
||||
|
||||
- SQLite, which is mainly used as an in-memory mock/test database
|
||||
- PostgreSQL, which is the preferred production database.
|
||||
|
||||
Other databases such as the MySQL variants are reported to work but [aren't fully tested](https://github.com/backstage/backstage/issues/2460) yet.
|
||||
|
||||
You can find instructions on setting up a PostgreSQL for your Backstage instance in [Database](../getting-started/config/database.md). [Configuring Plugin Databases](../tutorials/configuring-plugin-databases.md) provides information on how to configure a database for a plugin.
|
||||
|
||||
## Plugin architecture
|
||||
|
||||
Architecturally, plugins can take three forms:
|
||||
|
||||
1. Standalone
|
||||
2. Service backed
|
||||
3. Third-party backed
|
||||
- [Standalone](#standalone-plugins)
|
||||
- [Service backend](#service-backend-plugins)
|
||||
- [Third-party backend](#third-party-backend-plugins)
|
||||
|
||||
#### Standalone plugins
|
||||
### Standalone plugins
|
||||
|
||||
Standalone plugins run entirely in the browser.
|
||||
[The Tech Radar plugin](https://demo.backstage.io/tech-radar), for example,
|
||||
simply renders hard-coded information. It doesn't make any API requests to other
|
||||
services.
|
||||
Standalone plugins run entirely in the browser. [The Tech Radar plugin](https://demo.backstage.io/tech-radar), for example, simply renders hard-coded information. It doesn't make any API requests to other services.
|
||||
|
||||
The architecture of the Tech Radar installed into a Backstage app is very simple. You just need to add Tech Radar as a frontend plugin into your app, as shown in the following diagram.
|
||||
|
||||
> **NOTE:**
|
||||
> The following diagram does not show the detailed contents of the frontend and backend containers in order to highlight the changes that pertain to the addition of the specified plugin.
|
||||
|
||||

|
||||
|
||||
Once the plugin has been added, then you can view the Tech Radar information in the Backstage UI.
|
||||
|
||||

|
||||
|
||||
The architecture of the Tech Radar installed into a Backstage app is very
|
||||
simple.
|
||||
### Service backend plugins
|
||||
|
||||

|
||||
Service backend plugins make API requests to a service which is within the purview of the organization running Backstage.
|
||||
|
||||
#### Service backed plugins
|
||||
The Lighthouse plugin, for example, makes requests to the [lighthouse-audit-service](https://github.com/spotify/lighthouse-audit-service). The `lighthouse-audit-service` is a microservice which runs a copy of Google's [Lighthouse library](https://github.com/GoogleChrome/lighthouse/) and stores the results in a PostgreSQL database.
|
||||
|
||||
Service backed plugins make API requests to a service which is within the
|
||||
purview of the organisation running Backstage.
|
||||
The Lighthouse plugin is added to the frontend. The lighthouse-audit-service container is already publicly available in Docker Hub and can be downloaded and run with
|
||||
|
||||
The Lighthouse plugin, for example, makes requests to the
|
||||
[lighthouse-audit-service](https://github.com/spotify/lighthouse-audit-service).
|
||||
The `lighthouse-audit-service` is a microservice which runs a copy of Google's
|
||||
[Lighthouse library](https://github.com/GoogleChrome/lighthouse/) and stores the
|
||||
results in a PostgreSQL database.
|
||||
```bash
|
||||
docker run spotify/lighthouse-audit-service:latest
|
||||
```
|
||||
|
||||
Its architecture looks like this:
|
||||
> **NOTE:**
|
||||
> The following diagram does not show the detailed contents of the frontend and backend, in order to highlight the changes that pertain to the addition of the specified plugin.
|
||||
|
||||

|
||||

|
||||
|
||||
The software catalog in Backstage is another example of a service backed plugin.
|
||||
It retrieves a list of services, or "entities", from the Backstage Backend
|
||||
service and renders them in a table for the user.
|
||||
The software catalog in Backstage is another example of a service backend plugin. It retrieves a list of services, or "entities", from the Backstage Backend service and renders them in a table for the user.
|
||||
|
||||
### Third-party backed plugins
|
||||
### Third-party backend plugins
|
||||
|
||||
Third-party backed plugins are similar to service backed plugins. The main
|
||||
difference is that the service which backs the plugin is hosted outside of the
|
||||
ecosystem of the company hosting Backstage.
|
||||
Third-party backend plugins are similar to service backend plugins. The main difference is that the service which backs the plugin is hosted outside of the ecosystem of the company hosting Backstage.
|
||||
|
||||
The CircleCI plugin is an example of a third-party backed plugin. CircleCI is a
|
||||
SaaS service which can be used without any knowledge of Backstage. It has an API
|
||||
which a Backstage plugin consumes to display content.
|
||||
The CircleCI plugin is an example of a third-party backend plugin. CircleCI is a SaaS service which can be used without any knowledge of Backstage. It has an API which a Backstage plugin consumes to display content.
|
||||
|
||||
Requests going to CircleCI from the user's browser are passed through a proxy
|
||||
service that Backstage provides. Without this, the requests would be blocked by
|
||||
Cross Origin Resource Sharing policies which prevent a browser page served at
|
||||
[https://example.com](https://example.com) from serving resources hosted at
|
||||
https://circleci.com.
|
||||
Requests going to CircleCI from the user's browser are passed through a proxy service that Backstage provides. Without this, the requests would be blocked by Cross Origin Resource Sharing policies which prevent a browser page served at [https://example.com](https://example.com) from serving resources hosted at https://circleci.com.
|
||||
|
||||

|
||||
> **NOTE:**
|
||||
> The following diagram does not show the detailed contents of the frontend and backend, in order to highlight the changes that pertain to the addition of the specified plugin.
|
||||
|
||||

|
||||
|
||||
## Package Architecture
|
||||
|
||||
Backstage relies heavily on NPM packages, both for distribution of libraries,
|
||||
and structuring of code within projects. While the way you structure your
|
||||
Backstage project is up to you, there is a set of established patterns that we
|
||||
encourage you to follow. These patterns can help set up a sound project
|
||||
structure as well as provide familiarity between different Backstage projects.
|
||||
Backstage relies heavily on NPM packages, both for distribution of libraries, and structuring of code within projects. While the way you structure your Backstage project is up to you, there is a set of established patterns that we encourage you to follow. These patterns can help set up a sound project structure as well as provide familiarity between different Backstage projects.
|
||||
|
||||
The following diagram shows an overview of the package architecture of
|
||||
Backstage. It takes the point of view of an individual plugin and all of the
|
||||
packages that it may contain, indicated by the thicker border and italic text.
|
||||
Surrounding the plugin are different package groups which are the different
|
||||
possible interface points of the plugin. Note that not all library package lists
|
||||
are complete as packages have been omitted for brevity.
|
||||
The following diagram shows an overview of the package architecture of Backstage. It takes the point of view of an individual plugin and all of the packages that it may contain, indicated by the thicker border and italic text. Surrounding the plugin are different package groups which are the different possible interface points of the plugin. Note that not all library package lists are complete as packages have been omitted for brevity.
|
||||
|
||||

|
||||
|
||||
### Overview
|
||||
|
||||
The arrows in the diagram above indicate a runtime dependency on the code of the
|
||||
target package. This strict dependency graph only applies to runtime
|
||||
`dependencies`, and there may be `devDependencies` that break the rules of this
|
||||
table for the purpose of testing. While there are some arrows that show a
|
||||
dependency on a collection of frontend, backend and isomorphic packages, those
|
||||
still have to abide by important compatibility rules shown in the bottom left.
|
||||
The arrows in the diagram above indicate a runtime dependency on the code of the target package. This strict dependency graph only applies to runtime
|
||||
`dependencies`, and there may be `devDependencies` that break the rules of this table for the purpose of testing. While there are some arrows that show a dependency on a collection of frontend, backend and isomorphic packages, those still have to abide by important compatibility rules shown in the bottom left.
|
||||
|
||||
The `app` and `backend` packages are the entry points of a Backstage project.
|
||||
The `app` package is the frontend application that brings together a collection
|
||||
of frontend plugins and customizes them to fit an organization, while the
|
||||
`backend` package is the backend service that powers the Backstage application.
|
||||
Worth noting is that there can be more than one instance of each of these
|
||||
packages within a project. Particularly the `backend` packages can benefit from
|
||||
being split up into smaller deployment units that each serve their own purpose
|
||||
with a smaller collection of plugins.
|
||||
The `app` and `backend` packages are the entry points of a Backstage project. The `app` package is the frontend application that brings together a collection of frontend plugins and customizes them to fit an organization, while the `backend` package is the backend service that powers the Backstage application. Worth noting is that there can be more than one instance of each of these packages within a project. Particularly the `backend` packages can benefit from being split up into smaller deployment units that each serve their own purpose with a smaller collection of plugins.
|
||||
|
||||
### Plugin Packages
|
||||
|
||||
A typical plugin consists of up to five packages, two frontend ones, two
|
||||
backend, and one isomorphic package. All packages within the plugin must share a
|
||||
common prefix, typically of the form `@<scope>/plugin-<plugin-id>`, but
|
||||
alternatives like `backstage-plugin-<plugin-id>` or
|
||||
`@<scope>/backstage-plugin-<plugin-id>` are also valid. Along with this prefix,
|
||||
each of the packages have their own unique suffix that denotes their role. In
|
||||
addition to these five plugin packages it's also possible for a plugin to have
|
||||
additional frontend and backend modules that can be installed to enable optional
|
||||
features. For a full list of suffixes and their roles, see the
|
||||
[Plugin Package Structure ADR](../architecture-decisions/adr011-plugin-package-structure.md).
|
||||
A typical plugin consists of up to five packages, two frontend ones, two backend, and one isomorphic package. All packages within the plugin must share a common prefix, typically of the form `@<scope>/plugin-<plugin-id>`, but alternatives like `backstage-plugin-<plugin-id>` or `@<scope>/backstage-plugin-<plugin-id>` are also valid. Along with this prefix, each of the packages have their own unique suffix that denotes their role. In addition to these five plugin packages it's also possible for a plugin to have
|
||||
additional frontend and backend modules that can be installed to enable optional features. For a full list of suffixes and their roles, see the [Plugin Package Structure ADR](../architecture-decisions/adr011-plugin-package-structure.md).
|
||||
|
||||
The `-react`, `-common`, and `-node` plugin packages together form the external
|
||||
library of a plugin. The plugin library enables other plugins to build on top of
|
||||
and extend a plugin, and likewise allows the plugin to depend on and extend
|
||||
other plugins. Because of this, it is preferable that plugin library packages
|
||||
allow duplicate installations of themselves, as you may end up with a mix of
|
||||
versions being installed as dependencies of various plugins. It is also
|
||||
forbidden for plugins to directly import non-library packages from other
|
||||
plugins, all communication between plugins must be handled through libraries and
|
||||
the application itself.
|
||||
The `-react`, `-common`, and `-node` plugin packages together form the external library of a plugin. The plugin library enables other plugins to build on top of and extend a plugin, and likewise allows the plugin to depend on and extend other plugins. Because of this, it is preferable that plugin library packages allow duplicate installations of themselves, as you may end up with a mix of versions being installed as dependencies of various plugins. It is also forbidden for plugins to directly import non-library packages from other plugins, all communication between plugins must be handled through libraries and the application itself.
|
||||
|
||||
### Frontend Packages
|
||||
|
||||
The frontend packages are grouped into two main groups. The first one is
|
||||
"Frontend App Core", which is the set of packages that are only used by the
|
||||
`app` package itself. These packages help build up the core structure of the app
|
||||
as well as provide a foundation for the plugin libraries to rely upon.
|
||||
The frontend packages are grouped into two main groups. The first one is "Frontend App Core", which is the set of packages that are only used by the `app` package itself. These packages help build up the core structure of the app as well as provide a foundation for the plugin libraries to rely upon.
|
||||
|
||||
The second group is the rest of the shared packages, further divided into
|
||||
"Frontend Plugin Core" and "Frontend Libraries". The core packages are
|
||||
considered particularly stable and form the core of the frontend framework.
|
||||
Their most important role is to form the boundary around each plugin and provide
|
||||
a set of tools that helps you combine a collection of plugins into a running
|
||||
application. The rest of the frontend packages are more traditional libraries
|
||||
that serve as building blocks to create plugins.
|
||||
The second group is the rest of the shared packages, further divided into "Frontend Plugin Core" and "Frontend Libraries". The core packages are considered particularly stable and form the core of the frontend framework. Their most important role is to form the boundary around each plugin and provide a set of tools that helps you combine a collection of plugins into a running application. The rest of the frontend packages are more traditional libraries that serve as building blocks to create plugins.
|
||||
|
||||
### Backend Packages
|
||||
|
||||
The backend library packages do not currently share a similar plugin
|
||||
architecture as the frontend packages. They are instead simply a collection of
|
||||
building blocks and patterns that help you build backend services. This is
|
||||
however likely to change in the future.
|
||||
The backend library packages do not currently share a similar plugin architecture as the frontend packages. They are instead simply a collection of building blocks and patterns that help you build backend services. This is however likely to change in the future.
|
||||
|
||||
### Common Packages
|
||||
|
||||
The common packages are the packages effectively depended on by all other pages.
|
||||
This is a much smaller set of packages but they are also very pervasive. Because
|
||||
the common packages are isomorphic and must execute both in the frontend and
|
||||
backend, they are never allowed to depend on any of the frontend or backend
|
||||
packages.
|
||||
The common packages are the packages effectively depended on by all other pages. This is a much smaller set of packages but they are also very pervasive. Because the common packages are isomorphic and must execute both in the frontend and backend, they are never allowed to depend on any of the frontend or backend packages.
|
||||
|
||||
The Backstage CLI is in a category of its own and is depended on by virtually
|
||||
all other packages. It's not a library in itself though, and must always be a
|
||||
development dependency only.
|
||||
The Backstage CLI is in a category of its own and is depended on by virtually all other packages. It's not a library in itself though, and must always be a development dependency only.
|
||||
|
||||
### Deciding where you place your code
|
||||
|
||||
It can sometimes be difficult to decide where to place your plugin code. For example
|
||||
should it go directly in the `-backend` plugin package or in the `-node` package?
|
||||
As a general guideline you should try to keep the exposure of your code as low
|
||||
as possible. If it doesn't need to be public API, it's best to avoid. If you don't
|
||||
need it to be used by other plugins, then keep it directly in the plugin packages.
|
||||
It can sometimes be difficult to decide where to place your plugin code. For example, should it go directly in the `-backend` plugin package or in the `-node` package? As a general guideline you should try to keep the exposure of your code as low as possible. If it doesn't need to be public API, it's best to avoid. If you don't need it to be used by other plugins, then keep it directly in the plugin packages.
|
||||
|
||||
Below is a chart to help you decide where to place your code.
|
||||
|
||||

|
||||
|
||||
## Databases
|
||||
|
||||
As we have seen, both the `lighthouse-audit-service` and `catalog-backend`
|
||||
require a database to work with.
|
||||
|
||||
The Backstage backend and its built-in plugins are based on the
|
||||
[Knex](http://knexjs.org/) library, and set up a separate logical database per
|
||||
plugin. This gives great isolation and lets them perform migrations and evolve
|
||||
separately from each other.
|
||||
|
||||
The Knex library supports a multitude of databases, but Backstage at this time
|
||||
of writing is tested primarily against two of them: SQLite, which is mainly used as
|
||||
an in-memory mock/test database, and PostgreSQL, which is the preferred
|
||||
production database. Other databases such as the MySQL variants are reported to
|
||||
work but
|
||||
[aren't fully tested](https://github.com/backstage/backstage/issues/2460)
|
||||
yet.
|
||||
|
||||
## Cache
|
||||
|
||||
The Backstage backend and its built-in plugins are also able to leverage cache
|
||||
stores as a means of improving performance or reliability. Similar to how
|
||||
databases are supported, plugins receive logically separated cache connections,
|
||||
which are powered by [Keyv](https://github.com/lukechilds/keyv) under the hood.
|
||||
The Backstage backend and its built-in plugins are also able to leverage cache stores as a means of improving performance or reliability. Similar to how databases are supported, plugins receive logically separated cache connections, which are powered by [Keyv](https://github.com/lukechilds/keyv) under the hood.
|
||||
|
||||
At this time of writing, Backstage can be configured to use one of five cache
|
||||
stores: memory, which is mainly used for local testing, memcache, redis, valkey or infinispan,
|
||||
which are cache stores better suited for production deployment. The right cache
|
||||
store for your Backstage instance will depend on your own run-time constraints
|
||||
and those required of the plugins you're running.
|
||||
At this time of writing, Backstage can be configured to use one of five cache stores:
|
||||
|
||||
- `memory`
|
||||
- `memcache`
|
||||
- `redis`
|
||||
- `valkey`
|
||||
- `infinispan`
|
||||
|
||||
`memory` is primarily used for local development, for production deployments, we recommend using one of the other cache stores. The right cache store for your Backstage instance will depend on your own run-time constraints and those required of the plugins you're running.
|
||||
|
||||
### Use memory for cache
|
||||
|
||||
@@ -351,30 +298,3 @@ backend:
|
||||
```
|
||||
|
||||
Contributions supporting other cache stores are welcome!
|
||||
|
||||
## Containerization
|
||||
|
||||
The example Backstage architecture shown above would Dockerize into three
|
||||
separate Docker images.
|
||||
|
||||
1. The frontend container
|
||||
2. The backend container
|
||||
3. The Lighthouse audit service container
|
||||
|
||||

|
||||
|
||||
The backend container can be built by running the following command:
|
||||
|
||||
```bash
|
||||
yarn run build
|
||||
yarn run build-image
|
||||
```
|
||||
|
||||
This will create a container called `example-backend`.
|
||||
|
||||
The lighthouse-audit-service container is already publicly available in Docker
|
||||
Hub and can be downloaded and run with
|
||||
|
||||
```bash
|
||||
docker run spotify/lighthouse-audit-service:latest
|
||||
```
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
id: technical-overview
|
||||
title: Technical overview
|
||||
description: Technical overview of Backstage
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Backstage is an open source framework for building developer portals that was created at Spotify to simplify end-to-end software development. As Spotify grew, their infrastructure became more fragmented and teams couldn't find the APIs they were supposed to use, or who owned a service, or documentation on anything.
|
||||
|
||||
Backstage is powered by a centralized [software catalog](#software-catalog-system-model) and utilizes an abstraction layer that sits on top of all of your infrastructure and developer tooling, allowing you to manage all of your software, services, tooling, and testing in one place.
|
||||
|
||||
Backstage uses a [plugin-architecture](#plugin-architecture-overview) which allows you customize the functionality of your Backstage application using a wide variety of available plugins or you can write your own. It also includes automated templates that your teams can use to create new microservices, helping to ensure consistency and adherence to your best practices. Backstage also provides the ability to create, maintain, and find the documentation for all of your software.
|
||||
|
||||
Backstage is now a [CNCF incubation project](https://backstage.io/blog/2022/03/16/backstage-turns-two#out-of-the-sandbox-and-into-incubation).
|
||||
|
||||
## Benefits
|
||||
|
||||
- For _engineering managers_, it allows you to maintain standards and best practices across the organization, and can help you manage your whole tech ecosystem, from migrations to test certification.
|
||||
- For _end users_ (developers), it makes it fast and simple to build software components in a standardized way, and it provides a central place to manage all projects and documentation.
|
||||
- For _platform engineers_, it enables extensibility and scalability by letting you easily integrate new tools and services (via plugins), as well as extending the functionality of existing ones.
|
||||
- For _everyone_, it is a single, consistent experience that ties all of your infrastructure tooling, resources, standards, owners, contributors, and administrators together in one place.
|
||||
|
||||
If you have question or want support, please join our [Discord server](https://discord.gg/backstage-687207715902193673).
|
||||
|
||||
## Core Features
|
||||
|
||||
Backstage includes the following set of core features:
|
||||
|
||||
- [Authentication and Identity](../auth/index.md) - Sign-in and identification of users, and delegating access to third-party resources, using built-in authentication providers.
|
||||
- [Kubernetes](../features/kubernetes/index.md) - A tool that allows developers to check the health of their services whether it is on a local host or in production.
|
||||
- [Notifications](../notifications/index.md) - Provides a means for plugins and external services to send messages to either individual users or groups.
|
||||
- [Permissions](../permissions/overview.md) - Ability to enforce rules concerning the type of access a user is given to specific data, APIs, or interface actions.
|
||||
- [Search](https://backstage.io/docs/features/search/) - Search for information in the Backstage ecosystem. You can customize the look and feel of each search result and use your own search engine.
|
||||
- [Software Catalog](../features/software-catalog/index.md) - A centralized system that contains metadata for all your software, such as services, websites, libraries, ML models, data pipelines, and so on. It can also contain metadata for the physical or virtual infrastructure needed to operate a piece of software. The software catalog can be viewed and searched through a UI.
|
||||
- [Software Templates](../features/software-templates/index.md) - A tool to help you create components inside Backstage. A template can load skeletons of code, include some variables, and then publish the template to a location, such as GitHub.
|
||||
- [TechDocs](https://backstage.io/docs/features/techdocs/) - A docs-like-code solution built into Backstage. Documentation is written in Markdown files which lives together with the code.
|
||||
|
||||
## Plugin Architecture Overview
|
||||
|
||||
Plugins are client side applications which mount themselves on the Backstage UI. They allow you to incorporate a wide variety of infrastructure and software development tools into your Backstage application. Backstage uses a [plugin-architecture](../overview/architecture-overview.md#plugin-architecture) to provide a consistent user experience, in a single UI, around all of your plugins.
|
||||
|
||||
The Backstage architecture supports three types of plugins:
|
||||
|
||||
- Standalone - runs entirely in a browser and it does not make any API requests to other services.
|
||||
- Service backed - makes API requests to a service within the ecosystem of the organization running Backstage.
|
||||
- Third-party backed - similar to service-backed, but the service backing the plugin is hosted outside of the ecosystem of the company hosting Backstage.
|
||||
|
||||
Many of the features available in Backstage are provided by plugins. For example, the Software Catalog is a service backed plugin. When you view the catalog, it retrieves a set of services ("[entities](#software-catalog-system-model)") from the Backstage Backend service and renders them in a table in the UI for you.
|
||||
|
||||
## Software Catalog System Model
|
||||
|
||||
The system model behind the software catalog is based on [_entities_](../references/glossary.md#entity) and it models two main types:
|
||||
|
||||
- Core Entities
|
||||
- Organizational Entities
|
||||
|
||||
`Core Entities` include:
|
||||
|
||||
- `Components` - Individual pieces of software that can be tracked in source control and can implement APIs for other components to consume.
|
||||
- `APIs` - Implemented by components and form the boundaries between different components. The API can be either public, restricted, or private.
|
||||
- `Resources` - The physical or virtual infrastructure needed to operate a component.
|
||||
|
||||

|
||||
|
||||
`Organizational Entities` include:
|
||||
|
||||
- `User` - A person, such as an employee, contractor, or similar.
|
||||
- `Group` - An organizational entity, such as a team, business unit, and so on.
|
||||
|
||||
When you have a large catalogue of components, APIs, and resources, it can be difficult to understand how they work together. Ecosystem modeling allows you to organize a large catalog of core entities into:
|
||||
|
||||
- Systems - A collection of resources and components that cooperate to perform a function by exposing one or several public APIs. It hides the resources and private APIs between the components from the consumer.
|
||||
- Domains - A collection of systems that share terminology, domain models, metrics, KPIs, business purpose, or documentation.
|
||||
|
||||
There are three additional items that can be part of the system model:
|
||||
|
||||
- `Location` - A marker that references other places to look for catalog data.
|
||||
- `Type` - It has no set meaning. You can assign your own types and use them as desired.
|
||||
- `Template` - Describes both the parameters that are rendered in the frontend part of the scaffolding wizard, and the steps that are executed when scaffolding that component.
|
||||
|
||||
The following diagram illustrates an example of ecosystem modeling, and provides sample relationships between a domain, system, core entities, and organization entities.
|
||||
|
||||

|
||||
|
||||
The following shows an example of viewing all of the components, APIs, and resources that are managed by your group after setting up the relationships to create a group organizational entity.
|
||||
|
||||

|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
# Release v1.44.0-next.3
|
||||
|
||||
Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.44.0-next.3](https://backstage.github.io/upgrade-helper/?to=1.44.0-next.3)
|
||||
|
||||
## @backstage/backend-app-api@1.2.8-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- dd69cf6: 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.
|
||||
|
||||
## @backstage/cli@0.34.4-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f2cf564: 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.
|
||||
|
||||
- 024645e: Remove unused @octokit modules from cli package
|
||||
|
||||
- @octokit/graphql
|
||||
- @octokit/graphql-schema
|
||||
- @octokit/oauth-app
|
||||
|
||||
- d14ef24: 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.
|
||||
|
||||
## @backstage/core-components@0.18.2-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 431130c: Added `renderEdge` prop to `<DependencyGraph />` component in `@backstage/core-components` to allow custom rendering of graph edges.
|
||||
|
||||
## @backstage/create-app@0.7.5-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Bumped create-app version.
|
||||
|
||||
## @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8ed53eb: Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but available for use for other cases too.
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
|
||||
## @backstage/ui@0.7.2-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3c921c5: Making href mandatory in tabs that are part of a Header component
|
||||
- 5c21e45: Add react router for internal routing for ButtonLinks
|
||||
- 9781815: Remove auto selection of tabs for tabs that all have href defined
|
||||
- f6dff5b: Using react router for internal links in the Menu component
|
||||
|
||||
## @backstage/plugin-app-visualizer@0.1.24-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4406144: Ensure that the text rendering has react keys for all elements
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-aws@0.4.16-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-azure@0.3.10-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.4-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.4-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-gerrit@0.3.7-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-github@0.11.1-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-github-org@0.3.15-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-catalog-backend-module-github@0.11.1-next.2
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-gitlab@0.7.4-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0443119: Fixed an issue in `GitlabDiscoveryEntityProvider` where entity fetching could fail for projects with special characters or that had been renamed or moved.
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.14-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-catalog-backend-module-gitlab@0.7.4-next.2
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-msgraph@0.8.1-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-backend-module-puppetdb@0.2.15-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-catalog-graph@0.5.2-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 431130c: Added `renderEdge` prop to `<DependencyGraph />` component in `@backstage/core-components` to allow custom rendering of graph edges.
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-home@0.8.13-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e7d59d3: fix(home): correct `clearAll` logic to properly handle `deletable` flag
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-kubernetes@0.12.12-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-kubernetes-cluster@0.0.30-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 99fcf98: Removed unused dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
|
||||
## @backstage/plugin-notifications@0.5.10-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f5e0963: Removed unused dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-notifications-backend@0.5.11-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f5e0963: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-notifications-backend-module-email@0.3.14-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b8cf31a: chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7
|
||||
- f5e0963: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-scaffolder@1.34.2-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- d9aed74: Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
|
||||
## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.14-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f5e0963: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.6-next.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f5e0963: Removed unused dependencies
|
||||
|
||||
## @backstage/plugin-signals@0.0.24-next.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7b41d9d: Remove `app-root-element:signals/signals-display` which was not doing anything useful
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.18.2-next.3
|
||||
- @backstage/frontend-plugin-api@0.12.1-next.2
|
||||
@@ -177,11 +177,12 @@ Usage: backstage-cli package start [options]
|
||||
Start a package for local development
|
||||
|
||||
Options:
|
||||
--config <path> Config files to load instead of app-config.yaml (default: [])
|
||||
--role <name> Run the command with an explicit package role
|
||||
--check Enable type checking and linting if available
|
||||
--inspect Enable debugger in Node.js environments
|
||||
--inspect-brk Enable debugger in Node.js environments, breaking before code starts
|
||||
--config <path> Config files to load instead of app-config.yaml (default: [])
|
||||
--role <name> Run the command with an explicit package role
|
||||
--check Enable type checking and linting if available
|
||||
--inspect Enable debugger in Node.js environments
|
||||
--inspect-brk Enable debugger in Node.js environments, breaking before code starts
|
||||
--entrypoint <path> Entry directory path (uses index file) or entry file path (without extension). Defaults to "dev"
|
||||
```
|
||||
|
||||
## package build
|
||||
|
||||
@@ -147,3 +147,13 @@ The `role` property in the template yaml file is used to determine what input wi
|
||||
| `plugin-web-library` | `pluginId` | `plugins` | none |
|
||||
| `plugin-node-library` | `pluginId` | `plugins` | none |
|
||||
| `plugin-common-library` | `pluginId` | `plugins` | none |
|
||||
|
||||
## Dependency Versioning
|
||||
|
||||
The `yarn new` command automatically detects if the [Backstage Yarn plugin](https://github.com/backstage/backstage/tree/master/packages/yarn-plugin) is installed in your repository and adjusts dependency versioning accordingly.
|
||||
|
||||
When the Backstage Yarn plugin is installed (detected via `.yarnrc.yml`), `yarn new` will generate `backstage:^` ranges for all `@backstage/*` dependencies. This ensures that new packages use the same Backstage version as defined in your `backstage.json` file.
|
||||
|
||||
When the plugin is not installed, `yarn new` uses the standard npm version ranges (e.g., `^1.0.0`) for all dependencies, maintaining backward compatibility.
|
||||
|
||||
Regardless of plugin installation, `workspace:` ranges found in your `yarn.lock` file will always take precedence over both `backstage:^` and npm ranges. This ensures that packages within monorepos continue to use workspace linking when available.
|
||||
|
||||
@@ -96,6 +96,32 @@ This field can be generated by the `backstage-cli repo fix --publish` command. T
|
||||
|
||||
The presence of this field is checked by the `backstage-cli package prepack` command, which is used to prepare a package for publishing. You can read more about this requirement in the section on [metadata for published packages](#metadata-for-published-packages).
|
||||
|
||||
### `backstage.features`
|
||||
|
||||
This field declares where to find Backstage features exported from the package. It is a map of features export paths to their feature type, similar to the `exports` field.
|
||||
|
||||
```js title="Example usage of the backstage.features field"
|
||||
{
|
||||
"name": "@backstage/plugin-catalog",
|
||||
"backstage": {
|
||||
"features": {
|
||||
"./alpha": "@backstage/FrontendPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This field is automatically generated by the `backstage-cli package prepack` command when publishing a package and therefore does not need to be committed to the repository.
|
||||
|
||||
If you are using your own tooling to publish a package, you need to populate this field manually, using the following feature types:
|
||||
|
||||
- `@backstage/BackendFeature`
|
||||
- `@backstage/FrontendPlugin`
|
||||
- `@backstage/FrontendModule`
|
||||
- `@backstage/FrontendFeatureLoader`
|
||||
|
||||
You can read more about the feature types in the [backend system](../backend-system/architecture/01-index.md) and [frontend system](../frontend-system/architecture/00-index.md) documentation.
|
||||
|
||||
### `backstage.pluginPackages`
|
||||
|
||||
For any package that is part of a plugin, this field should be set to a list of all packages that are directly part of the same plugin. This includes frontend and backend plugin packages as well as related libraries, but not modules.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user