diff --git a/.changeset/mighty-crews-attack.md b/.changeset/mighty-crews-attack.md
new file mode 100644
index 0000000000..c0b8587fe0
--- /dev/null
+++ b/.changeset/mighty-crews-attack.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Initial entity page implementation for new frontend system at `/alpha`, with an overview page enabled by default and the about card available as an optional card.
diff --git a/.changeset/nice-apes-kneel.md b/.changeset/nice-apes-kneel.md
new file mode 100644
index 0000000000..1ecff9d223
--- /dev/null
+++ b/.changeset/nice-apes-kneel.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Added entity page content for the new plugin exported via `/alpha`.
diff --git a/.changeset/old-apricots-taste.md b/.changeset/old-apricots-taste.md
new file mode 100644
index 0000000000..544ba11536
--- /dev/null
+++ b/.changeset/old-apricots-taste.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Added new APIs at the `/alpha` subpath for creating entity page cards and content for the new frontend system.
diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml
index 6f6081fece..0c75e1c96c 100644
--- a/packages/app-next/app-config.yaml
+++ b/packages/app-next/app-config.yaml
@@ -4,12 +4,17 @@ app:
routes:
bindings:
plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX
- # waiting for https://github.com/backstage/backstage/pull/20605
- # catalog.externalRoutes.viewTechDoc: techdocs.routes.docRoot
+ plugin.catalog.externalRoutes.viewTechDoc: plugin.techdocs.routes.docRoot
extensions:
- apis.plugin.graphiql.browse.gitlab: true
+ # Entity page cards
+ - 'entity.cards.about'
+
+ # Entity page content
+ - 'entity.content.techdocs'
+
# scmAuthExtension: >-
# createScmAuthExtension({
# id: 'apis.scmAuth.addons.ghe',
diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx
index 7ff47a3e89..1275722da4 100644
--- a/packages/app-next/src/App.tsx
+++ b/packages/app-next/src/App.tsx
@@ -17,7 +17,6 @@
import React from 'react';
import { createApp } from '@backstage/frontend-app-api';
import { pagesPlugin } from './examples/pagesPlugin';
-import { entityPagePlugins } from './examples/entityPages';
import graphiqlPlugin from '@backstage/plugin-graphiql/alpha';
import techRadarPlugin from '@backstage/plugin-tech-radar/alpha';
import userSettingsPlugin from '@backstage/plugin-user-settings/alpha';
@@ -30,11 +29,8 @@ import {
createExtension,
createApiExtension,
createExtensionOverrides,
- createPageExtension,
} from '@backstage/frontend-plugin-api';
-import { entityRouteRef } from '@backstage/plugin-catalog-react';
import techdocsPlugin from '@backstage/plugin-techdocs/alpha';
-import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha';
import { homePage } from './HomePage';
import { collectLegacyRoutes } from '@backstage/core-compat-api';
import { FlatRoutes } from '@backstage/core-app-api';
@@ -76,13 +72,6 @@ TODO:
/* app.tsx */
-const entityPageExtension = createPageExtension({
- id: 'catalog:entity',
- defaultPath: '/catalog/:namespace/:kind/:name',
- routeRef: convertLegacyRouteRef(entityRouteRef),
- loader: async () =>
Just a temporary mocked entity page
,
-});
-
const homePageExtension = createExtension({
id: 'myhomepage',
attachTo: { id: 'home', input: 'props' },
@@ -121,15 +110,9 @@ const app = createApp({
techdocsPlugin,
userSettingsPlugin,
homePlugin,
- ...entityPagePlugins,
...collectedLegacyPlugins,
createExtensionOverrides({
- extensions: [
- entityPageExtension,
- homePageExtension,
- scmAuthExtension,
- scmIntegrationApi,
- ],
+ extensions: [homePageExtension, scmAuthExtension, scmIntegrationApi],
}),
],
/* Handled through config instead */
diff --git a/packages/app-next/src/examples/entityPages.tsx b/packages/app-next/src/examples/entityPages.tsx
deleted file mode 100644
index 3b5b4cceb7..0000000000
--- a/packages/app-next/src/examples/entityPages.tsx
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2023 The Backstage Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React, { useEffect } from 'react';
-import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha';
-import {
- AnyExtensionInputMap,
- Extension,
- ExtensionBoundary,
- ExtensionInputValues,
- PortableSchema,
- RouteRef,
- coreExtensionData,
- createExtension,
- createExtensionDataRef,
- createExtensionInput,
- createPageExtension,
- createPlugin,
- createSchemaFromZod,
-} from '@backstage/frontend-plugin-api';
-import {
- AsyncEntityProvider,
- EntityLoadingStatus,
- catalogApiRef,
- entityRouteRef,
-} from '@backstage/plugin-catalog-react';
-// eslint-disable-next-line @backstage/no-relative-monorepo-imports
-import { Expand } from '../../../frontend-plugin-api/src/types';
-import { EntityAboutCard, EntityLayout } from '@backstage/plugin-catalog';
-import {
- useApi,
- errorApiRef,
- useRouteRefParams,
-} from '@backstage/core-plugin-api';
-import { useNavigate } from 'react-router';
-import useAsyncRetry from 'react-use/lib/useAsyncRetry';
-import Grid from '@material-ui/core/Grid';
-
-export const useEntityFromUrl = (): EntityLoadingStatus => {
- const { kind, namespace, name } = useRouteRefParams(entityRouteRef);
- const navigate = useNavigate();
- const errorApi = useApi(errorApiRef);
- const catalogApi = useApi(catalogApiRef);
-
- const {
- value: entity,
- error,
- loading,
- retry: refresh,
- } = useAsyncRetry(
- () => catalogApi.getEntityByRef({ kind, namespace, name }),
- [catalogApi, kind, namespace, name],
- );
-
- useEffect(() => {
- if (!name) {
- errorApi.post(new Error('No name provided!'));
- navigate('/');
- }
- }, [errorApi, navigate, error, loading, entity, name]);
-
- return { entity, loading, error, refresh };
-};
-
-export const titleExtensionDataRef = createExtensionDataRef(
- 'plugin.catalog.entity.content.title',
-);
-
-const CatalogEntityPage = createPageExtension({
- id: 'plugin.catalog.page.entity',
- defaultPath: '/catalog/:namespace/:kind/:name',
- routeRef: convertLegacyRouteRef(entityRouteRef),
- inputs: {
- contents: createExtensionInput({
- element: coreExtensionData.reactElement,
- path: coreExtensionData.routePath,
- routeRef: coreExtensionData.routeRef.optional(),
- title: titleExtensionDataRef,
- }),
- },
- loader: async ({ inputs }) => {
- const Component = () => {
- return (
-
-
- {inputs.contents.map(content => (
-
- {content.element}
-
- ))}
-
-
- );
- };
- return ;
- },
-});
-
-export function createEntityCardExtension<
- TConfig,
- TInputs extends AnyExtensionInputMap,
->(options: {
- id: string;
- attachTo?: { id: string; input: string };
- disabled?: boolean;
- inputs?: TInputs;
- configSchema?: PortableSchema;
- loader: (options: {
- config: TConfig;
- inputs: Expand>;
- }) => Promise;
-}): Extension {
- return createExtension({
- id: `entity.content.${options.id}`,
- attachTo: options.attachTo ?? {
- id: 'entity.content.overview',
- input: 'cards',
- },
- disabled: options.disabled ?? true,
- output: {
- element: coreExtensionData.reactElement,
- },
- inputs: options.inputs,
- configSchema: options.configSchema,
- factory({ bind, config, inputs, source }) {
- const LazyComponent = React.lazy(() =>
- options
- .loader({ config, inputs })
- .then(element => ({ default: () => element })),
- );
-
- bind({
- element: (
-
-
-
-
-
- ),
- });
- },
- });
-}
-
-export function createEntityContentExtension<
- TConfig extends { path: string; title: string },
- TInputs extends AnyExtensionInputMap,
->(
- options: (
- | {
- defaultPath: string;
- defaultTitle: string;
- }
- | {
- configSchema: PortableSchema;
- }
- ) & {
- id: string;
- attachTo?: { id: string; input: string };
- disabled?: boolean;
- inputs?: TInputs;
- routeRef?: RouteRef;
- loader: (options: {
- config: TConfig;
- inputs: Expand>;
- }) => Promise;
- },
-): Extension {
- const configSchema =
- 'configSchema' in options
- ? options.configSchema
- : (createSchemaFromZod(z =>
- z.object({
- path: z.string().default(options.defaultPath),
- title: z.string().default(options.defaultTitle),
- }),
- ) as PortableSchema);
-
- return createExtension({
- id: `entity.content.${options.id}`,
- attachTo: options.attachTo ?? {
- id: 'plugin.catalog.page.entity',
- input: 'contents',
- },
- disabled: options.disabled ?? true,
- output: {
- element: coreExtensionData.reactElement,
- path: coreExtensionData.routePath,
- routeRef: coreExtensionData.routeRef.optional(),
- title: titleExtensionDataRef,
- },
- inputs: options.inputs,
- configSchema,
- factory({ bind, config, inputs, source }) {
- const LazyComponent = React.lazy(() =>
- options
- .loader({ config, inputs })
- .then(element => ({ default: () => element })),
- );
-
- bind({
- path: config.path,
- element: (
-
-
-
-
-
- ),
- routeRef: options.routeRef,
- title: config.title,
- });
- },
- });
-}
-
-const entityAboutCardExtension = createEntityCardExtension({
- id: 'about',
- disabled: false,
- loader: async () => ,
- // entityFilter: isDerp,
-});
-
-const overviewContentExtension = createEntityContentExtension({
- id: 'overview',
- defaultPath: '/',
- defaultTitle: 'Overview',
- disabled: false,
- inputs: {
- cards: createExtensionInput({
- element: coreExtensionData.reactElement,
- }),
- },
- loader: async ({ inputs }) => (
-
- {inputs.cards.map(card => (
-
- {card.element}
-
- ))}
-
- ),
-});
-
-const bonusTechdocsPlugin = createPlugin({
- id: 'techdocs-entity',
- extensions: [
- createEntityContentExtension({
- id: 'techdocs',
- defaultPath: 'docs',
- defaultTitle: 'TechDocs',
- disabled: false,
- loader: () =>
- import('@backstage/plugin-techdocs').then(m => (
-
- )),
- // entityFilter: isPullRequestsAvailable,
- }),
- ],
-});
-
-export const entityPagePlugins = [
- createPlugin({
- id: 'entity-pages',
- extensions: [
- CatalogEntityPage,
- overviewContentExtension,
- entityAboutCardExtension,
- ],
- }),
- bonusTechdocsPlugin,
- // deploymentsPlugin,
-];
diff --git a/plugins/catalog-react/alpha-api-report.md b/plugins/catalog-react/alpha-api-report.md
index f9b740c07c..120e162c84 100644
--- a/plugins/catalog-react/alpha-api-report.md
+++ b/plugins/catalog-react/alpha-api-report.md
@@ -3,8 +3,73 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
+///
+
+import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api';
+import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Entity } from '@backstage/catalog-model';
+import { Extension } from '@backstage/frontend-plugin-api';
+import { ExtensionInputValues } from '@backstage/frontend-plugin-api';
+import { PortableSchema } from '@backstage/frontend-plugin-api';
import { ResourcePermission } from '@backstage/plugin-permission-common';
+import { RouteRef } from '@backstage/frontend-plugin-api';
+
+// @alpha (undocumented)
+export function createEntityCardExtension<
+ TConfig,
+ TInputs extends AnyExtensionInputMap,
+>(options: {
+ id: string;
+ attachTo?: {
+ id: string;
+ input: string;
+ };
+ disabled?: boolean;
+ inputs?: TInputs;
+ configSchema?: PortableSchema;
+ loader: (options: {
+ config: TConfig;
+ inputs: Expand>;
+ }) => Promise;
+}): Extension;
+
+// @alpha (undocumented)
+export function createEntityContentExtension<
+ TConfig extends {
+ path: string;
+ title: string;
+ },
+ TInputs extends AnyExtensionInputMap,
+>(
+ options: (
+ | {
+ defaultPath: string;
+ defaultTitle: string;
+ }
+ | {
+ configSchema: PortableSchema;
+ }
+ ) & {
+ id: string;
+ attachTo?: {
+ id: string;
+ input: string;
+ };
+ disabled?: boolean;
+ inputs?: TInputs;
+ routeRef?: RouteRef;
+ loader: (options: {
+ config: TConfig;
+ inputs: Expand>;
+ }) => Promise;
+ },
+): Extension;
+
+// @alpha (undocumented)
+export const entityContentTitleExtensionDataRef: ConfigurableExtensionDataRef<
+ string,
+ {}
+>;
// @alpha
export function isOwnerOf(owner: Entity, entity: Entity): boolean;
diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json
index bb18160595..70fa5e9614 100644
--- a/plugins/catalog-react/package.json
+++ b/plugins/catalog-react/package.json
@@ -10,13 +10,13 @@
},
"exports": {
".": "./src/index.ts",
- "./alpha": "./src/alpha.ts",
+ "./alpha": "./src/alpha.tsx",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"alpha": [
- "src/alpha.ts"
+ "src/alpha.tsx"
],
"package.json": [
"package.json"
@@ -51,6 +51,7 @@
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/errors": "workspace:^",
+ "@backstage/frontend-plugin-api": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
diff --git a/plugins/catalog-react/src/alpha.tsx b/plugins/catalog-react/src/alpha.tsx
new file mode 100644
index 0000000000..d2eeb8f5f3
--- /dev/null
+++ b/plugins/catalog-react/src/alpha.tsx
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2023 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import {
+ AnyExtensionInputMap,
+ Extension,
+ ExtensionBoundary,
+ ExtensionInputValues,
+ PortableSchema,
+ RouteRef,
+ coreExtensionData,
+ createExtension,
+ createExtensionDataRef,
+ createSchemaFromZod,
+} from '@backstage/frontend-plugin-api';
+// eslint-disable-next-line @backstage/no-relative-monorepo-imports
+import { Expand } from '../../../packages/frontend-plugin-api/src/types';
+
+export { isOwnerOf } from './utils';
+export { useEntityPermission } from './hooks/useEntityPermission';
+
+/** @alpha */
+export const entityContentTitleExtensionDataRef =
+ createExtensionDataRef('plugin.catalog.entity.content.title');
+
+/** @alpha */
+export function createEntityCardExtension<
+ TConfig,
+ TInputs extends AnyExtensionInputMap,
+>(options: {
+ id: string;
+ attachTo?: { id: string; input: string };
+ disabled?: boolean;
+ inputs?: TInputs;
+ configSchema?: PortableSchema;
+ loader: (options: {
+ config: TConfig;
+ inputs: Expand>;
+ }) => Promise;
+}): Extension {
+ const id = `entity.cards.${options.id}`;
+
+ return createExtension({
+ id,
+ attachTo: options.attachTo ?? {
+ id: 'entity.content.overview',
+ input: 'cards',
+ },
+ disabled: options.disabled ?? true,
+ output: {
+ element: coreExtensionData.reactElement,
+ },
+ inputs: options.inputs,
+ configSchema: options.configSchema,
+ factory({ bind, config, inputs, source }) {
+ const ExtensionComponent = React.lazy(() =>
+ options
+ .loader({ config, inputs })
+ .then(element => ({ default: () => element })),
+ );
+
+ bind({
+ element: (
+
+
+
+ ),
+ });
+ },
+ });
+}
+
+/** @alpha */
+export function createEntityContentExtension<
+ TConfig extends { path: string; title: string },
+ TInputs extends AnyExtensionInputMap,
+>(
+ options: (
+ | {
+ defaultPath: string;
+ defaultTitle: string;
+ }
+ | {
+ configSchema: PortableSchema;
+ }
+ ) & {
+ id: string;
+ attachTo?: { id: string; input: string };
+ disabled?: boolean;
+ inputs?: TInputs;
+ routeRef?: RouteRef;
+ loader: (options: {
+ config: TConfig;
+ inputs: Expand>;
+ }) => Promise;
+ },
+): Extension {
+ const id = `entity.content.${options.id}`;
+
+ const configSchema =
+ 'configSchema' in options
+ ? options.configSchema
+ : (createSchemaFromZod(z =>
+ z.object({
+ path: z.string().default(options.defaultPath),
+ title: z.string().default(options.defaultTitle),
+ }),
+ ) as PortableSchema);
+
+ return createExtension({
+ id,
+ attachTo: options.attachTo ?? {
+ id: 'plugin.catalog.page.entity',
+ input: 'contents',
+ },
+ disabled: options.disabled ?? true,
+ output: {
+ element: coreExtensionData.reactElement,
+ path: coreExtensionData.routePath,
+ routeRef: coreExtensionData.routeRef.optional(),
+ title: entityContentTitleExtensionDataRef,
+ },
+ inputs: options.inputs,
+ configSchema,
+ factory({ bind, config, inputs, source }) {
+ const LazyComponent = React.lazy(() =>
+ options
+ .loader({ config, inputs })
+ .then(element => ({ default: () => element })),
+ );
+
+ bind({
+ path: config.path,
+ element: (
+
+
+
+ ),
+ routeRef: options.routeRef,
+ title: config.title,
+ });
+ },
+ });
+}
diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md
index aba33fc092..43e589bdc3 100644
--- a/plugins/catalog/alpha-api-report.md
+++ b/plugins/catalog/alpha-api-report.md
@@ -12,14 +12,6 @@ import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
import { PortableSchema } from '@backstage/frontend-plugin-api';
import { RouteRef } from '@backstage/frontend-plugin-api';
-// @alpha (undocumented)
-export const CatalogApi: Extension<{}>;
-
-// @alpha (undocumented)
-export const CatalogSearchResultListItemExtension: Extension<{
- noTrack?: boolean | undefined;
-}>;
-
// @alpha (undocumented)
export function createCatalogFilterExtension<
TInputs extends AnyExtensionInputMap,
@@ -62,8 +54,5 @@ const _default: BackstagePlugin<
>;
export default _default;
-// @alpha (undocumented)
-export const StarredEntitiesApi: Extension<{}>;
-
// (No @packageDocumentation comment for this package)
```
diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json
index 214795e73c..9b879e3c50 100644
--- a/plugins/catalog/package.json
+++ b/plugins/catalog/package.json
@@ -10,13 +10,13 @@
},
"exports": {
".": "./src/index.ts",
- "./alpha": "./src/alpha/index.ts",
+ "./alpha": "./src/alpha.ts",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"alpha": [
- "src/alpha/index.ts"
+ "src/alpha.ts"
],
"package.json": [
"package.json"
diff --git a/plugins/catalog-react/src/alpha.ts b/plugins/catalog/src/alpha.ts
similarity index 85%
rename from plugins/catalog-react/src/alpha.ts
rename to plugins/catalog/src/alpha.ts
index e8ff21609e..e80f131817 100644
--- a/plugins/catalog-react/src/alpha.ts
+++ b/plugins/catalog/src/alpha.ts
@@ -14,5 +14,5 @@
* limitations under the License.
*/
-export { isOwnerOf } from './utils';
-export { useEntityPermission } from './hooks/useEntityPermission';
+export * from './alpha/index';
+export { default } from './alpha/index';
diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx
index 1716b85a81..d9d2878213 100644
--- a/plugins/catalog/src/alpha/plugin.tsx
+++ b/plugins/catalog/src/alpha/plugin.tsx
@@ -38,6 +38,11 @@ import {
entityRouteRef,
starredEntitiesApiRef,
} from '@backstage/plugin-catalog-react';
+import {
+ createEntityContentExtension,
+ createEntityCardExtension,
+ entityContentTitleExtensionDataRef,
+} from '@backstage/plugin-catalog-react/alpha';
import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha';
import { DefaultStarredEntitiesApi } from '../apis';
import {
@@ -48,6 +53,7 @@ import {
} from '../routes';
import { builtInFilterExtensions } from './builtInFilterExtensions';
import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';
+import Grid from '@material-ui/core/Grid';
/** @alpha */
export const CatalogApi = createApiExtension({
@@ -102,11 +108,30 @@ const CatalogEntityPage = createPageExtension({
id: 'plugin.catalog.page.entity',
defaultPath: '/catalog/:namespace/:kind/:name',
routeRef: convertLegacyRouteRef(entityRouteRef),
- loader: async () => {
+ inputs: {
+ contents: createExtensionInput({
+ element: coreExtensionData.reactElement,
+ path: coreExtensionData.routePath,
+ routeRef: coreExtensionData.routeRef.optional(),
+ title: entityContentTitleExtensionDataRef,
+ }),
+ },
+ loader: async ({ inputs }) => {
+ const { EntityLayout } = await import('../components/EntityLayout');
const Component = () => {
return (
- 🚧 Work In Progress
+
+ {inputs.contents.map(content => (
+
+ {content.element}
+
+ ))}
+
);
};
@@ -114,6 +139,35 @@ const CatalogEntityPage = createPageExtension({
},
});
+const EntityAboutCard = createEntityCardExtension({
+ id: 'about',
+ loader: async () =>
+ import('../components/AboutCard').then(m => (
+
+ )),
+});
+
+const OverviewEntityContent = createEntityContentExtension({
+ id: 'overview',
+ defaultPath: '/',
+ defaultTitle: 'Overview',
+ disabled: false,
+ inputs: {
+ cards: createExtensionInput({
+ element: coreExtensionData.reactElement,
+ }),
+ },
+ loader: async ({ inputs }) => (
+
+ {inputs.cards.map(card => (
+
+ {card.element}
+
+ ))}
+
+ ),
+});
+
const CatalogNavItem = createNavItemExtension({
id: 'catalog.nav.index',
routeRef: convertLegacyRouteRef(rootRouteRef),
@@ -140,6 +194,8 @@ export default createPlugin({
CatalogIndexPage,
CatalogEntityPage,
CatalogNavItem,
+ OverviewEntityContent,
+ EntityAboutCard,
...builtInFilterExtensions,
],
});
diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx
index b7ccb0b12c..ceb5f47364 100644
--- a/plugins/techdocs/src/alpha.tsx
+++ b/plugins/techdocs/src/alpha.tsx
@@ -42,6 +42,7 @@ import {
rootDocsRouteRef,
rootRouteRef,
} from './routes';
+import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha';
/** @alpha */
const techDocsStorage = createApiExtension({
@@ -141,6 +142,18 @@ const TechDocsReaderPage = createPageExtension({
)),
});
+/**
+ * Component responsible for rendering techdocs on entity pages
+ *
+ * @alpha
+ */
+const TechDocsEntityContent = createEntityContentExtension({
+ id: 'techdocs',
+ defaultPath: 'docs',
+ defaultTitle: 'TechDocs',
+ loader: () => import('./Router').then(m => ),
+});
+
/** @alpha */
const TechDocsNavItem = createNavItemExtension({
id: 'plugin.techdocs.nav.index',
@@ -158,6 +171,7 @@ export default createPlugin({
TechDocsNavItem,
TechDocsIndexPage,
TechDocsReaderPage,
+ TechDocsEntityContent,
TechDocsSearchResultListItemExtension,
],
routes: {
diff --git a/yarn.lock b/yarn.lock
index 059c18d859..3075745d85 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5837,6 +5837,7 @@ __metadata:
"@backstage/core-components": "workspace:^"
"@backstage/core-plugin-api": "workspace:^"
"@backstage/errors": "workspace:^"
+ "@backstage/frontend-plugin-api": "workspace:^"
"@backstage/integration": "workspace:^"
"@backstage/plugin-catalog-common": "workspace:^"
"@backstage/plugin-permission-common": "workspace:^"