diff --git a/docs/frontend-system/building-apps/02-configuring-extensions.md b/docs/frontend-system/building-apps/02-configuring-extensions.md index 57a2110da6..2fd4ce69fc 100644 --- a/docs/frontend-system/building-apps/02-configuring-extensions.md +++ b/docs/frontend-system/building-apps/02-configuring-extensions.md @@ -6,92 +6,4 @@ sidebar_label: Configuring Extensions description: Documentation for how to configure extensions in a Backstage app --- -All extensions in a Backstage app can be configured through static configuration. This configuration is all done under a the `app.extensions` configuration key. For more general information on how to write configuration for Backstage, see the section on [writing configuration](../../conf/writing.md). - -## Extension Configuration Schema - -This section focuses on the format of the `app.extensions` configuration and the various shorthands that are available. - -The most complete and verbose format for configuring an individual extensions is as follows: - -```yaml -app: - extensions: - - : - attachTo: - id: - input: - disabled: - config: -``` - -All of the top-level fields are optional: `attachTo`, `disabled`, and `config`. Every extension implementation must provide defaults for all of these fields that will be used if they are not provided in the configuration. - -Note that `app.extensions` is always an array rather than an object. For example, the following is invalid: - -```yaml title="INVALID" -app: - extensions: - : # Invalid, this should be an array item, `app.extensions` is now an object - config: ... -``` - -In addition to this schema, there are a number of shorthands available: - -Rather than a full object, you can specify just the ID of the extension as a string. This is equivalent to setting `disabled` to `false`: - -```yaml -app: - extensions: - - ‘’ -``` - -You can enable/disable individual extension by ID, in this case the value is a boolean: - -```yaml -extensions: - - : -``` - -You can override the implementation of an extension by ID, in this case the value is a string: - -```yaml -extensions: - - : ‘’ -``` - -You can **create a new extension instance with a generated ID** by including an input name in the key: - -```yaml -extensions: - - /: - extension: - config: -``` - -This syntax is only for use in the app configuration itself, every extension provided by default from a plugin must have an explicit ID. For example, the following two configurations are equivalent, except that the former does not have an explicit instance ID: - -```yaml -extensions: - # Generated ID - - core.router/routes: - extension: '@backstage/plugin-tech-radar#TechRadarPage' - # Explicit ID - - tech-radar.page: - at: core.router/routes - extension: '@backstage/plugin-tech-radar#TechRadarPage' -``` - -Lastly, if you do not need to provide additional configuration, you can combine the key input format with the implementation value format as a shorthand for creating a new extension instance with a generated ID and no configuration: - -```yaml -extensions: - - /: ‘’ -``` - -For example: - -```yaml -extensions: - - core.router/routes: '@backstage/plugin-tech-radar#TechRadarPage' -``` +TODO diff --git a/docs/frontend-system/building-apps/08-migrating.md b/docs/frontend-system/building-apps/08-migrating.md index 2018fecc8a..98d8b3bab8 100644 --- a/docs/frontend-system/building-apps/08-migrating.md +++ b/docs/frontend-system/building-apps/08-migrating.md @@ -74,7 +74,7 @@ export default app.createRoot(); We've taken all the elements that were previously passed to `app.createRoot(...)`, and instead passed them to `convertLegacyApp(...)`. We then pass the features returned by `convertLegacyApp` and forward them to the `features` option of the new `createApp`. -There is one more detail that we need to deal with before moving on. The `app.createRoot()` function now returns a React element rather and a component, so we need to update our app `index.tsx` as follows: +There is one more detail that we need to deal with before moving on. The `app.createRoot()` function now returns a React element rather than a component, so we need to update our app `index.tsx` as follows: ```tsx title="in packages/app/src/index.tsx" import '@backstage/cli/asset-types'; @@ -161,7 +161,7 @@ Many app components are now installed as extensions instead using `createCompone The `Router` component is now a built-in extension that you can override using `createRouterExtension`. -The Sign-in page is now installed as an extension using the `createSignInPageExtension` instead. See the section on [configuring the sign-in page](./index.md#TODO) for more information. +The Sign-in page is now installed as an extension using the `createSignInPageExtension` instead. For example, the following sign-in page configuration: @@ -204,7 +204,7 @@ const signInPage = createSignInPageExtension({ ### `themes` -Themes are now installed as extensions instead using `createThemeExtension`. See the section on [configuring themes](./index.md#TODO) for more information. +Themes are now installed as extensions, using `createThemeExtension`. For example, the following theme configuration: @@ -216,7 +216,9 @@ const app = createApp({ title: 'Light', variant: 'light', Provider: ({ children }) => ( - + + {children} + ), }, ], @@ -273,11 +275,11 @@ const app = createApp({ ### `__experimentalTranslations` -Translations are now installed as extensions instead using `createTranslationExtension`. See the section on [configuring translations](./index.md#TODO) for more information. +Translations are now installed as extensions, using `createTranslationExtension`. ## Gradual Migration -After updating all `createApp` options as well as using `convertLegacyApp` to use our existing app structure, you should be able to start up the app and see that it still works. If that is not the case, make sure you read any errors messages that you may see in the app as they can provide hints on what you need to fix. If you are still stuck, you can check if anyone else ran into the same issue in our [GitHub issues](https://github.com/backstage/backstage/issues), or ask for help in our [community Discord](https://discord.gg/backstage-687207715902193673). +After updating all `createApp` options as well as using `convertLegacyApp` to use your existing app structure, you should be able to start up the app and see that it still works. If that is not the case, make sure you read any error messages that you may see in the app as they can provide hints on what you need to fix. If you are still stuck, you can check if anyone else ran into the same issue in our [GitHub issues](https://github.com/backstage/backstage/issues), or ask for help in our [community Discord](https://discord.gg/backstage-687207715902193673). Assuming your app is now working, let's continue by migrating the rest of the app element tree to use the new system. @@ -303,7 +305,7 @@ const legacyFeatures = convertLegacyApp(routes); This will remove many extension overrides that `convertLegacyApp` put in place, and switch over the shell of the app to the new system. This includes the root layout of the app along with the elements, router, and sidebar. The app will likely not look the same as before, and you'll need to refer to the [sidebar](#sidebar), [app root elements](#app-root-elements) and [app root wrappers](#app-root-wrappers) sections below for information on how to migrate those. -Once that step is complete the work that remains is to migrate all of the [routes](#top-level-routes) and [entity pages](#entity-pages) in the app, including any plugins that do not yet support the new system. For information on how to migrate your own internal plugins, refer to the [plugin migration guide](../plugins/08-migrating.md). For external plugins you will need to check the migration status of each plugin and potentially contribute to the effort. +Once that step is complete the work that remains is to migrate all of the [routes](#top-level-routes) and [entity pages](#entity-pages) in the app, including any plugins that do not yet support the new system. For information on how to migrate your own internal plugins, refer to the [plugin migration guide](../building-plugins/05-migrating.md). For external plugins you will need to check the migration status of each plugin and potentially contribute to the effort. Once these migrations are complete you should be left with an empty `convertLegacyApp(...)` call that you can now remove, and your app should be fully migrated to the new system! 🎉 @@ -330,7 +332,7 @@ const routes = ( ); ``` -Each of these routes need to be migrated to the new system. You can do it as gradually as you want, with the only restriction being that **all routes from a single plugin must be migrated at once**. This is because plugins discovered from these legacy routes will override any plugin that are installed in your app. If you for example only migrate one of the two routes defined by a plugin, the other route will remain and still override any plugin with the same ID, and you're left with a partial and likely broken plugin. +Each of these routes needs to be migrated to the new system. You can do it as gradually as you want, with the only restriction being that **all routes from a single plugin must be migrated at once**. This is because plugins discovered from these legacy routes will override any plugins that are installed in your app. If you for example only migrate one of the two routes defined by a plugin, the other route will remain and still override any plugin with the same ID, and you're left with a partial and likely broken plugin. To migrate a route, you need to remove it from your list of routes and instead install the new version of the plugin in your app. Before doing this you should make sure that the plugin supports the new system. Let's remove the scaffolder route as an example: @@ -354,7 +356,7 @@ const routes = ( ); ``` -If you are using [app feature discovery](../architecture/02-app.md#feature-discovery) the installation step is simple, it's already done! The new version of the scaffolder plugin was already discovered and present in the app, it was simply disabled because the plugin created from the legacy route had higher priority. If you do not use feature discovery, you will instead need to manually installed the new scaffolder plugin in your app through the `features` option of `createApp`. +If you are using [app feature discovery](../architecture/02-app.md#feature-discovery) the installation step is simple, it's already done! The new version of the scaffolder plugin was already discovered and present in the app, it was simply disabled because the plugin created from the legacy route had higher priority. If you do not use feature discovery, you will instead need to manually install the new scaffolder plugin in your app through the `features` option of `createApp`. Continue this process for each of your legacy routes until you have migrated all of them. For any plugin with additional extensions installed as children of the `Route`, refer to the plugin READMEs for more detailed instructions. For the entity pages, refer to the [separate section](#entity-pages). @@ -408,7 +410,7 @@ export default app.createRoot( ); ``` -The `AlertDisplay` and `OAuthRequestDialog` are already provided as built-in extensions, and so will `VisitListener`. But, if you have your own custom root elements you will need to migrate them be extensions that you install in the app instead. Use `createAppRootElementExtension` to create said extension and then install it in the app. +The `AlertDisplay` and `OAuthRequestDialog` are already provided as built-in extensions, and so will `VisitListener`. But, if you have your own custom root elements you will need to migrate them to be extensions that you install in the app instead. Use `createAppRootElementExtension` to create said extension and then install it in the app. Whether the element used to be rendered as a child of the `AppRouter` or not doesn't matter. All new root app elements will be rendered as a child of the app router. @@ -432,4 +434,4 @@ export default app.createRoot( ); ``` -Any app root wrapper needs to be migrated to be an extension instead, using `createAppRootWrapperExtension`. Note that if you have multiple wrappers they must be completely independent of each other, the order in which the appear in the React tree should not matter. If that is not the case then you should group them into a single wrapper. +Any app root wrapper needs to be migrated to be an extension, using `createAppRootWrapperExtension`. Note that if you have multiple wrappers they must be completely independent of each other, i.e. the order in which they the appear in the React tree should not matter. If that is not the case then you should group them into a single wrapper.