Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions workspaces/homepage/.changeset/home-plugin-overrides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-homepage': minor
---

Export `homePagePlugin` (upstream `@backstage/plugin-home` with homepage layout and widgets via `withOverrides`) as the alpha default so Module Federation / dynamic NFS installs register `page:home` without a separate `@backstage/plugin-home` dependency. Keep `homePageModule` for hosts that already register `homePlugin`.
3 changes: 1 addition & 2 deletions workspaces/homepage/packages/app/knip-report.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Knip report

## Unused dependencies (17)
## Unused dependencies (16)

| Name | Location | Severity |
| :----------------------------------------------- | :---------------- | :------- |
Expand All @@ -18,7 +18,6 @@
| @backstage/plugin-techdocs | package.json:43:6 | error |
| @backstage/plugin-catalog | package.json:33:6 | error |
| @backstage/plugin-signals | package.json:42:6 | error |
| @backstage/plugin-home | package.json:36:6 | error |
| @backstage/plugin-org | package.json:39:6 | error |
| react-router | package.json:53:6 | error |

Expand Down
1 change: 0 additions & 1 deletion workspaces/homepage/packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
"@backstage/plugin-catalog": "^2.0.6",
"@backstage/plugin-catalog-graph": "^0.6.5",
"@backstage/plugin-catalog-import": "^0.13.14",
"@backstage/plugin-home": "^0.9.7",
"@backstage/plugin-kubernetes": "^0.12.20",
"@backstage/plugin-notifications": "^0.5.18",
"@backstage/plugin-org": "^0.7.5",
Expand Down
4 changes: 2 additions & 2 deletions workspaces/homepage/packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { createApp } from '@backstage/frontend-defaults';
import { navModule } from './modules/nav';
import { signInModule } from './modules/signIn';
import {
homePageModule,
homePagePlugin,
homepageTranslationsModule,
} from '@red-hat-developer-hub/backstage-plugin-homepage/alpha';
import { rhdhThemeModule } from '@red-hat-developer-hub/backstage-plugin-theme/alpha';
Expand All @@ -28,7 +28,7 @@ export default createApp({
rhdhThemeModule,
navModule,
signInModule,
homePageModule,
homePagePlugin,
homepageTranslationsModule,
],
});
22 changes: 13 additions & 9 deletions workspaces/homepage/plugins/homepage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ If you're using Backstage's new frontend system, add the plugin to your app:
// packages/app/src/App.tsx
import { createApp } from '@backstage/frontend-defaults';
import {
homePageDevModule,
homePagePlugin,
homepageTranslationsModule,
} from '@red-hat-developer-hub/backstage-plugin-homepage/alpha';

export default createApp({
features: [
// ... other plugins (nav, signIn, etc.)
homePageDevModule,
// Embeds @backstage/plugin-home (page:home) + homepage widgets/layout
homePagePlugin,
homepageTranslationsModule,
],
});
```

Do **not** also register `@backstage/plugin-home` (or discover it via `app.packages`) when using `homePagePlugin` — that would load the `home` plugin twice. If your app already loads upstream `homePlugin`, use `homePageModule` instead of `homePagePlugin`.

The plugin will automatically provide:

- A homepage at `/home` (or the path configured via `page:home`)
Expand Down Expand Up @@ -68,18 +71,19 @@ app:
# ...
```

### Modules
### Modules / plugins

The following modules are available from the alpha export:
The following features are available from the alpha export:

| Module | Description |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `homePageDevModule` | Home page layout and widgets (Onboarding, Entity, Templates, Quick Access, Search, Recently Visited, Top Visited, etc.) |
| `homepageTranslationsModule` | i18n translations (en, de, es, fr, it, ja) |
| Export | Type | Description |
| ---------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------ |
| `homePagePlugin` (default) | `FrontendPlugin` | Upstream `@backstage/plugin-home` with custom layout and widgets (`withOverrides`). Use this for dynamic installs. |
| `homePageModule` | `FrontendModule` | Same extensions as a module — only if the host already registers `homePlugin`. |
| `homepageTranslationsModule` | `FrontendModule` | i18n translations (en, de, es, fr, it, ja) |

### Extensions

The `homePageDevModule` extends the `home` plugin (`@backstage/plugin-home`) with:
`homePagePlugin` / `homePageModule` extend the `home` plugin (`@backstage/plugin-home`) with:

- `home-page-layout:home/dynamic-homepage-layout` – Custom layout with config-driven widget arrangement and priority
- `home-page-widget:home/rhdh-onboarding-section` – Onboarding section
Expand Down
4 changes: 2 additions & 2 deletions workspaces/homepage/plugins/homepage/dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
starredEntitiesApiRef,
} from '@backstage/plugin-catalog-react';
import {
homePageModule,
homePagePlugin,
homepageTranslationsModule,
} from '@red-hat-developer-hub/backstage-plugin-homepage/alpha';
import { rhdhThemeModule } from '@red-hat-developer-hub/backstage-plugin-theme/alpha';
Expand Down Expand Up @@ -153,7 +153,7 @@ const app = createApp({
devNavModule,
catalogPlugin,
searchPlugin,
homePageModule,
homePagePlugin,
homepageTranslationsModule,
homepageApiMocksModule,
catalogDevModule,
Expand Down
184 changes: 181 additions & 3 deletions workspaces/homepage/plugins/homepage/report-alpha.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,192 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts
import { AnyApiFactory } from '@backstage/frontend-plugin-api';
import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ApiFactory } from '@backstage/frontend-plugin-api';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api';
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
import { ExtensionInput } from '@backstage/frontend-plugin-api';
import { FrontendModule } from '@backstage/frontend-plugin-api';
import { HomePageLayoutProps } from '@backstage/plugin-home-react/alpha';
import { HomePageWidgetBlueprintParams } from '@backstage/plugin-home-react/alpha';
import { HomePageWidgetData } from '@backstage/plugin-home-react/alpha';
import { IconElement } from '@backstage/frontend-plugin-api';
import { JSX as JSX_2 } from 'react';
import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api';
import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api';
import { RouteRef } from '@backstage/frontend-plugin-api';
import { TranslationRef } from '@backstage/frontend-plugin-api';
import { TranslationResource } from '@backstage/frontend-plugin-api';

// @alpha
const homePageModule: FrontendModule;
export default homePageModule;
export { homePageModule };
export const homePageModule: FrontendModule;

// @alpha
const homePagePlugin: OverridableFrontendPlugin<
{
root: RouteRef<undefined>;
},
{},
{
'api:home/visits': OverridableExtensionDefinition<{
kind: 'api';
name: 'visits';
config: {};
configInput: {};
output: ExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>;
inputs: {};
params: <
TApi,
TImpl extends TApi,
TDeps extends { [name in string]: unknown },
>(
params: ApiFactory<TApi, TImpl, TDeps>,
) => ExtensionBlueprintParams<AnyApiFactory>;
}>;
'app-root-element:home/visit-listener': OverridableExtensionDefinition<{
kind: 'app-root-element';
name: 'visit-listener';
config: {};
configInput: {};
output: ExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>;
inputs: {};
params: {
element: JSX.Element;
};
}>;
'home-page-widget:home/random-joke': OverridableExtensionDefinition<{
kind: 'home-page-widget';
name: 'random-joke';
config: {};
configInput: {};
output: ExtensionDataRef<HomePageWidgetData, 'home.widget.data', {}>;
inputs: {};
params: HomePageWidgetBlueprintParams;
}>;
'home-page-widget:home/starred-entities': OverridableExtensionDefinition<{
kind: 'home-page-widget';
name: 'starred-entities';
config: {};
configInput: {};
output: ExtensionDataRef<HomePageWidgetData, 'home.widget.data', {}>;
inputs: {};
params: HomePageWidgetBlueprintParams;
}>;
'home-page-widget:home/toolkit': OverridableExtensionDefinition<{
kind: 'home-page-widget';
name: 'toolkit';
config: {};
configInput: {};
output: ExtensionDataRef<HomePageWidgetData, 'home.widget.data', {}>;
inputs: {};
params: HomePageWidgetBlueprintParams;
}>;
'page:home': OverridableExtensionDefinition<{
config: {
path: string | undefined;
title: string | undefined;
};
configInput: {
path?: string | undefined;
title?: string | undefined;
};
output:
| ExtensionDataRef<string, 'core.routing.path', {}>
| ExtensionDataRef<
RouteRef<AnyRouteRefParams>,
'core.routing.ref',
{
optional: true;
}
>
| ExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
| ExtensionDataRef<
string,
'core.title',
{
optional: true;
}
>
| ExtensionDataRef<
IconElement,
'core.icon',
{
optional: true;
}
>;
inputs: {
pages: ExtensionInput<
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
| ConfigurableExtensionDataRef<
RouteRef<AnyRouteRefParams>,
'core.routing.ref',
{
optional: true;
}
>
| ConfigurableExtensionDataRef<
string,
'core.title',
{
optional: true;
}
>
| ConfigurableExtensionDataRef<
IconElement,
'core.icon',
{
optional: true;
}
>,
{
singleton: false;
optional: false;
internal: false;
}
>;
widgets: ExtensionInput<
ConfigurableExtensionDataRef<
HomePageWidgetData,
'home.widget.data',
{}
>,
{
singleton: false;
optional: false;
internal: false;
}
>;
layout: ExtensionInput<
ConfigurableExtensionDataRef<
(props: HomePageLayoutProps) => JSX_2.Element,
'home.layout.component',
{}
>,
{
singleton: true;
optional: true;
internal: true;
}
>;
};
kind: 'page';
name: undefined;
params: {
path: string;
title?: string;
icon?: IconElement;
loader?: () => Promise<JSX_2.Element>;
routeRef?: RouteRef;
noHeader?: boolean;
};
}>;
}
>;
export default homePagePlugin;
export { homePagePlugin };

// @public
export const homepageTranslationRef: TranslationRef<
Expand Down
15 changes: 13 additions & 2 deletions workspaces/homepage/plugins/homepage/src/alpha/alpha.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
* limitations under the License.
*/

import { homepageTranslationsModule, homePageModule } from '.';
import homepageAlpha, {
homepageTranslationsModule,
homePageModule,
homePagePlugin,
} from '.';
import { homepageTranslationRef, homepageTranslations } from '../translations';
import { homePageLayoutExtension } from './extensions/homePageLayoutExtension';
import {
Expand All @@ -34,7 +38,14 @@ import { quickAccessApi } from './extensions/apis';

describe('Dynamic Home Page plugin Alpha (NFS)', () => {
describe('Modules', () => {
it('should export homePageDevModule with correct structure', () => {
it('should export homePagePlugin with correct structure', () => {
expect(homePagePlugin).toBeDefined();
expect(homePagePlugin.$$type).toBe('@backstage/FrontendPlugin');
expect(homePagePlugin.id).toBe('home');
expect(homepageAlpha).toBe(homePagePlugin);
});

it('should export homePageModule with correct structure', () => {
expect(homePageModule).toBeDefined();
expect(homePageModule.$$type).toBe('@backstage/FrontendModule');
expect(homePageModule.pluginId).toBe('home');
Expand Down
Loading
Loading