diff --git a/plugins/home-react/src/alpha.ts b/plugins/home-react/src/alpha.ts
index 88f318a3f8..2766ef83a9 100644
--- a/plugins/home-react/src/alpha.ts
+++ b/plugins/home-react/src/alpha.ts
@@ -26,7 +26,10 @@
export { homeReactTranslationRef } from './translation';
export {
HomepageWidgetBlueprint,
- widgetMetadataRef,
type HomepageWidgetBlueprintParams,
} from './alpha/blueprints/HomepageWidgetBlueprint';
+export {
+ homePageWidgetDataRef,
+ type HomePageWidgetData,
+} from './alpha/dataRefs';
export type { ComponentParts, CardLayout, CardSettings } from './extensions';
diff --git a/plugins/home-react/src/alpha/blueprints/HomepageWidgetBlueprint.tsx b/plugins/home-react/src/alpha/blueprints/HomepageWidgetBlueprint.tsx
index 553a6b3249..0cb898a5f8 100644
--- a/plugins/home-react/src/alpha/blueprints/HomepageWidgetBlueprint.tsx
+++ b/plugins/home-react/src/alpha/blueprints/HomepageWidgetBlueprint.tsx
@@ -17,9 +17,7 @@
import { lazy, ReactElement } from 'react';
import { compatWrapper } from '@backstage/core-compat-api';
import {
- coreExtensionData,
createExtensionBlueprint,
- createExtensionDataRef,
ExtensionBoundary,
} from '@backstage/frontend-plugin-api';
import {
@@ -29,6 +27,7 @@ import {
CardSettings,
ComponentParts,
} from '../../extensions';
+import { homePageWidgetDataRef } from '../dataRefs';
/** @alpha */
export interface HomepageWidgetBlueprintParams {
@@ -68,18 +67,6 @@ const DEFAULT_WIDGET_ATTACH_POINT = {
input: 'widgets',
} as const;
-/**
- * Extension data ref for widget metadata.
- * @alpha
- */
-export const widgetMetadataRef = createExtensionDataRef<{
- name?: string;
- title?: string;
- description?: string;
- layout?: CardLayout;
- settings?: CardSettings;
-}>().with({ id: 'home.widget.metadata' });
-
/**
* Creates widgets that can be installed into the home page grid.
*
@@ -88,7 +75,7 @@ export const widgetMetadataRef = createExtensionDataRef<{
export const HomepageWidgetBlueprint = createExtensionBlueprint({
kind: 'home-widget',
attachTo: DEFAULT_WIDGET_ATTACH_POINT,
- output: [coreExtensionData.reactElement, widgetMetadataRef],
+ output: [homePageWidgetDataRef],
*factory(params: HomepageWidgetBlueprintParams, { node }) {
const isCustomizable = params.settings?.schema !== undefined;
const LazyCard = lazy(() =>
@@ -113,11 +100,8 @@ export const HomepageWidgetBlueprint = createExtensionBlueprint({
,
);
- yield coreExtensionData.reactElement(
- ,
- );
-
- yield widgetMetadataRef({
+ yield homePageWidgetDataRef({
+ component: ,
name: params.name,
title: params.title,
description: params.description,
diff --git a/plugins/home-react/src/alpha/dataRefs.ts b/plugins/home-react/src/alpha/dataRefs.ts
new file mode 100644
index 0000000000..00b221994f
--- /dev/null
+++ b/plugins/home-react/src/alpha/dataRefs.ts
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2025 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 { createExtensionDataRef } from '@backstage/frontend-plugin-api';
+import { ReactElement } from 'react';
+import type { CardLayout, CardSettings } from '../extensions';
+
+/**
+ * Extension data for homepage widgets, bundling the rendered component
+ * with its metadata.
+ *
+ * @alpha
+ */
+export interface HomePageWidgetData {
+ /**
+ * The rendered widget component (typically a card with header, content, etc.)
+ */
+ component: ReactElement;
+ /**
+ * Optional name identifier for the widget
+ */
+ name?: string;
+ /**
+ * Optional title displayed in the widget header
+ */
+ title?: string;
+ /**
+ * Optional description shown in widget catalogs or configuration UIs
+ */
+ description?: string;
+ /**
+ * Optional layout hints for positioning and sizing
+ */
+ layout?: CardLayout;
+ /**
+ * Optional settings schema for widget configuration
+ */
+ settings?: CardSettings;
+}
+
+/**
+ * Extension data ref for homepage widgets.
+ *
+ * This follows the pattern from FormFieldBlueprint, bundling the component
+ * and metadata into a single comprehensive data ref rather than outputting
+ * them separately.
+ *
+ * @alpha
+ */
+export const homePageWidgetDataRef =
+ createExtensionDataRef().with({
+ id: 'home.widget.data',
+ });
diff --git a/plugins/home/src/alpha/HomepageBlueprint.tsx b/plugins/home/src/alpha/HomepageBlueprint.tsx
index 8eabae2153..b72ff4d587 100644
--- a/plugins/home/src/alpha/HomepageBlueprint.tsx
+++ b/plugins/home/src/alpha/HomepageBlueprint.tsx
@@ -25,6 +25,7 @@ import {
import { Fragment, type ReactElement, type ReactNode } from 'react';
import { CustomHomepageGrid } from '../components';
import type { CustomHomepageGridProps } from '../components';
+import { homePageWidgetDataRef } from '@backstage/plugin-home-react/alpha';
/**
* Arguments provided to the homepage renderer.
@@ -78,13 +79,13 @@ export const HomepageBlueprint = createExtensionBlueprint({
attachTo: DEFAULT_ATTACH_POINT,
output: [coreExtensionData.reactElement, coreExtensionData.title.optional()],
inputs: {
- widgets: createExtensionInput([coreExtensionData.reactElement]),
+ widgets: createExtensionInput([homePageWidgetDataRef]),
},
*factory(params: HomepageBlueprintParams = {}, { inputs, node }) {
const widgetOutputs = inputs.widgets ?? [];
const widgetElements = widgetOutputs.map((widget, index) => (
- {widget.get(coreExtensionData.reactElement)}
+ {widget.get(homePageWidgetDataRef).component}
));