diff --git a/plugins/bui-themer/package.json b/plugins/bui-themer/package.json
index c0d49b0879..f6f5faffd4 100644
--- a/plugins/bui-themer/package.json
+++ b/plugins/bui-themer/package.json
@@ -25,8 +25,10 @@
"postpack": "backstage-cli package postpack"
},
"dependencies": {
+ "@backstage/core-compat-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
+ "@backstage/frontend-plugin-api": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.9.1",
diff --git a/plugins/bui-themer/src/components/ExampleFetchComponent/index.ts b/plugins/bui-themer/src/components/BuiThemerPage/BuiThemerPage.tsx
similarity index 90%
rename from plugins/bui-themer/src/components/ExampleFetchComponent/index.ts
rename to plugins/bui-themer/src/components/BuiThemerPage/BuiThemerPage.tsx
index b0be0a2a71..0328a3e6d6 100644
--- a/plugins/bui-themer/src/components/ExampleFetchComponent/index.ts
+++ b/plugins/bui-themer/src/components/BuiThemerPage/BuiThemerPage.tsx
@@ -13,4 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-export { ExampleFetchComponent } from './ExampleFetchComponent';
+
+export function BuiThemerPage() {
+ return
TODO
;
+}
diff --git a/plugins/bui-themer/src/components/ExampleComponent/index.ts b/plugins/bui-themer/src/components/BuiThemerPage/index.ts
similarity index 91%
rename from plugins/bui-themer/src/components/ExampleComponent/index.ts
rename to plugins/bui-themer/src/components/BuiThemerPage/index.ts
index 66b3fc6c97..3d32f11259 100644
--- a/plugins/bui-themer/src/components/ExampleComponent/index.ts
+++ b/plugins/bui-themer/src/components/BuiThemerPage/index.ts
@@ -13,4 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-export { ExampleComponent } from './ExampleComponent';
+
+export { BuiThemerPage } from './BuiThemerPage';
diff --git a/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.test.tsx b/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.test.tsx
deleted file mode 100644
index f5f7f185c5..0000000000
--- a/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.test.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 { ExampleComponent } from './ExampleComponent';
-import { rest } from 'msw';
-import { setupServer } from 'msw/node';
-import { screen } from '@testing-library/react';
-import { registerMswTestHooks, renderInTestApp } from '@backstage/test-utils';
-
-describe('ExampleComponent', () => {
- const server = setupServer();
- // Enable sane handlers for network requests
- registerMswTestHooks(server);
-
- // setup mock response
- beforeEach(() => {
- server.use(
- rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))),
- );
- });
-
- it('should render', async () => {
- await renderInTestApp();
- expect(screen.getByText('Welcome to bui-themer!')).toBeInTheDocument();
- });
-});
diff --git a/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.tsx b/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.tsx
deleted file mode 100644
index 3a04bd7562..0000000000
--- a/plugins/bui-themer/src/components/ExampleComponent/ExampleComponent.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 { Typography, Grid } from '@material-ui/core';
-import {
- InfoCard,
- Header,
- Page,
- Content,
- ContentHeader,
- HeaderLabel,
- SupportButton,
-} from '@backstage/core-components';
-import { ExampleFetchComponent } from '../ExampleFetchComponent';
-
-export const ExampleComponent = () => (
-
-
-
-
- A description of your plugin goes here.
-
-
-
-
-
- All content should be wrapped in a card like this.
-
-
-
-
-
-
-
-
-
-);
diff --git a/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx b/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx
deleted file mode 100644
index a3085e3dcb..0000000000
--- a/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 { renderInTestApp } from '@backstage/test-utils';
-import { ExampleFetchComponent } from './ExampleFetchComponent';
-
-describe('ExampleFetchComponent', () => {
- it('renders the user table', async () => {
- const { getAllByText, getByAltText, getByText, findByRole } =
- await renderInTestApp();
-
- // Wait for the table to render
- const table = await findByRole('table');
- const nationality = getAllByText('GB');
- // Assert that the table contains the expected user data
- expect(table).toBeInTheDocument();
- expect(getByAltText('Carolyn')).toBeInTheDocument();
- expect(getByText('Carolyn Moore')).toBeInTheDocument();
- expect(getByText('carolyn.moore@example.com')).toBeInTheDocument();
- expect(nationality[0]).toBeInTheDocument();
- });
-});
diff --git a/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx b/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx
deleted file mode 100644
index 6c9e77094d..0000000000
--- a/plugins/bui-themer/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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 { makeStyles } from '@material-ui/core/styles';
-import {
- Table,
- TableColumn,
- Progress,
- ResponseErrorPanel,
-} from '@backstage/core-components';
-import useAsync from 'react-use/lib/useAsync';
-
-export const exampleUsers = {
- results: [
- {
- gender: 'female',
- name: {
- title: 'Miss',
- first: 'Carolyn',
- last: 'Moore',
- },
- email: 'carolyn.moore@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Carolyn',
- nat: 'GB',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Esma',
- last: 'Berberoğlu',
- },
- email: 'esma.berberoglu@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Esma',
- nat: 'TR',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Isabella',
- last: 'Rhodes',
- },
- email: 'isabella.rhodes@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella',
- nat: 'GB',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Derrick',
- last: 'Carter',
- },
- email: 'derrick.carter@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Derrick',
- nat: 'IE',
- },
- {
- gender: 'female',
- name: {
- title: 'Miss',
- first: 'Mattie',
- last: 'Lambert',
- },
- email: 'mattie.lambert@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mattie',
- nat: 'AU',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Mijat',
- last: 'Rakić',
- },
- email: 'mijat.rakic@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mijat',
- nat: 'RS',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Javier',
- last: 'Reid',
- },
- email: 'javier.reid@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Javier',
- nat: 'US',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Isabella',
- last: 'Li',
- },
- email: 'isabella.li@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella',
- nat: 'CA',
- },
- {
- gender: 'female',
- name: {
- title: 'Mrs',
- first: 'Stephanie',
- last: 'Garrett',
- },
- email: 'stephanie.garrett@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Stephanie',
- nat: 'AU',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Antonia',
- last: 'Núñez',
- },
- email: 'antonia.nunez@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Antonia',
- nat: 'ES',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Donald',
- last: 'Young',
- },
- email: 'donald.young@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Donald',
- nat: 'US',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Iegor',
- last: 'Holodovskiy',
- },
- email: 'iegor.holodovskiy@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Iegor',
- nat: 'UA',
- },
- {
- gender: 'female',
- name: {
- title: 'Madame',
- first: 'Jessica',
- last: 'David',
- },
- email: 'jessica.david@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Jessica',
- nat: 'CH',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Eve',
- last: 'Martinez',
- },
- email: 'eve.martinez@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Eve',
- nat: 'FR',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Caleb',
- last: 'Silva',
- },
- email: 'caleb.silva@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Caleb',
- nat: 'US',
- },
- {
- gender: 'female',
- name: {
- title: 'Miss',
- first: 'Marcia',
- last: 'Jenkins',
- },
- email: 'marcia.jenkins@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Marcia',
- nat: 'US',
- },
- {
- gender: 'female',
- name: {
- title: 'Mrs',
- first: 'Mackenzie',
- last: 'Jones',
- },
- email: 'mackenzie.jones@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Mackenzie',
- nat: 'NZ',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Jeremiah',
- last: 'Gutierrez',
- },
- email: 'jeremiah.gutierrez@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Jeremiah',
- nat: 'AU',
- },
- {
- gender: 'female',
- name: {
- title: 'Ms',
- first: 'Luciara',
- last: 'Souza',
- },
- email: 'luciara.souza@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Luciara',
- nat: 'BR',
- },
- {
- gender: 'male',
- name: {
- title: 'Mr',
- first: 'Valgi',
- last: 'da Cunha',
- },
- email: 'valgi.dacunha@example.com',
- picture: 'https://api.dicebear.com/6.x/open-peeps/svg?seed=Valgi',
- nat: 'BR',
- },
- ],
-};
-
-const useStyles = makeStyles({
- avatar: {
- height: 32,
- width: 32,
- borderRadius: '50%',
- },
-});
-
-type User = {
- gender: string; // "male"
- name: {
- title: string; // "Mr",
- first: string; // "Duane",
- last: string; // "Reed"
- };
- email: string; // "duane.reed@example.com"
- picture: string; // "https://api.dicebear.com/6.x/open-peeps/svg?seed=Duane"
- nat: string; // "AU"
-};
-
-type DenseTableProps = {
- users: User[];
-};
-
-export const DenseTable = ({ users }: DenseTableProps) => {
- const classes = useStyles();
-
- const columns: TableColumn[] = [
- { title: 'Avatar', field: 'avatar' },
- { title: 'Name', field: 'name' },
- { title: 'Email', field: 'email' },
- { title: 'Nationality', field: 'nationality' },
- ];
-
- const data = users.map(user => {
- return {
- avatar: (
-
- ),
- name: `${user.name.first} ${user.name.last}`,
- email: user.email,
- nationality: user.nat,
- };
- });
-
- return (
-
- );
-};
-
-export const ExampleFetchComponent = () => {
- const { value, loading, error } = useAsync(async (): Promise => {
- // Would use fetch in a real world example
- return exampleUsers.results;
- }, []);
-
- if (loading) {
- return ;
- } else if (error) {
- return ;
- }
-
- return ;
-};
diff --git a/plugins/bui-themer/src/index.ts b/plugins/bui-themer/src/index.ts
index 26bc35ebb1..4cf05a7f23 100644
--- a/plugins/bui-themer/src/index.ts
+++ b/plugins/bui-themer/src/index.ts
@@ -13,4 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
export { buiThemerPlugin, BuiThemerPage } from './plugin';
+export { default } from './plugin';
diff --git a/plugins/bui-themer/src/plugin.ts b/plugins/bui-themer/src/plugin.tsx
similarity index 59%
rename from plugins/bui-themer/src/plugin.ts
rename to plugins/bui-themer/src/plugin.tsx
index d87d035b12..78d3196126 100644
--- a/plugins/bui-themer/src/plugin.ts
+++ b/plugins/bui-themer/src/plugin.tsx
@@ -13,13 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import {
+ convertLegacyRouteRef,
+ convertLegacyRouteRefs,
+} from '@backstage/core-compat-api';
import {
createPlugin,
createRoutableExtension,
} from '@backstage/core-plugin-api';
-
+import {
+ createFrontendPlugin,
+ PageBlueprint,
+} from '@backstage/frontend-plugin-api';
import { rootRouteRef } from './routes';
+// Old system
export const buiThemerPlugin = createPlugin({
id: 'bui-themer',
routes: {
@@ -31,7 +40,25 @@ export const BuiThemerPage = buiThemerPlugin.provide(
createRoutableExtension({
name: 'BuiThemerPage',
component: () =>
- import('./components/ExampleComponent').then(m => m.ExampleComponent),
+ import('./components/BuiThemerPage').then(m => m.BuiThemerPage),
mountPoint: rootRouteRef,
}),
);
+
+// New system
+export default createFrontendPlugin({
+ pluginId: 'bui-themer',
+ extensions: [
+ PageBlueprint.make({
+ params: {
+ path: '/bui-themer',
+ loader: () =>
+ import('./components/BuiThemerPage').then(m => ),
+ routeRef: convertLegacyRouteRef(rootRouteRef),
+ },
+ }),
+ ],
+ routes: convertLegacyRouteRefs({
+ root: rootRouteRef,
+ }),
+});
diff --git a/yarn.lock b/yarn.lock
index cb9a75fa61..f22d88ee20 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4329,9 +4329,11 @@ __metadata:
dependencies:
"@backstage/cli": "workspace:^"
"@backstage/core-app-api": "workspace:^"
+ "@backstage/core-compat-api": "workspace:^"
"@backstage/core-components": "workspace:^"
"@backstage/core-plugin-api": "workspace:^"
"@backstage/dev-utils": "workspace:^"
+ "@backstage/frontend-plugin-api": "workspace:^"
"@backstage/test-utils": "workspace:^"
"@backstage/theme": "workspace:^"
"@material-ui/core": "npm:^4.9.13"