diff --git a/packages/app/package.json b/packages/app/package.json
index c27540f63e..8ef8a54221 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -45,6 +45,7 @@
"@backstage/frontend-app-api": "workspace:^",
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-api-docs": "workspace:^",
+ "@backstage/plugin-app": "^0.0.0",
"@backstage/plugin-auth-react": "workspace:^",
"@backstage/plugin-catalog": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index ba556e8616..cc7512464a 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -82,6 +82,7 @@ import { customDevToolsPage } from './components/devtools/CustomDevToolsPage';
import { DevToolsPage } from '@backstage/plugin-devtools';
import { CatalogUnprocessedEntitiesPage } from '@backstage/plugin-catalog-unprocessed-entities';
import { NotificationsPage } from '@backstage/plugin-notifications';
+import { AppPage } from '@backstage/plugin-app';
const app = createApp({
apis,
@@ -208,6 +209,7 @@ const routes = (
{customDevToolsPage}
} />
+ } />
);
diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json
index b7fbef8b46..1a302aadc7 100644
--- a/plugins/app-backend/package.json
+++ b/plugins/app-backend/package.json
@@ -6,6 +6,7 @@
"role": "backend-plugin",
"pluginId": "app",
"pluginPackages": [
+ "@backstage/plugin-app",
"@backstage/plugin-app-backend",
"@backstage/plugin-app-node"
]
diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json
index 4e28a853ed..b8ee9dd437 100644
--- a/plugins/app-node/package.json
+++ b/plugins/app-node/package.json
@@ -6,6 +6,7 @@
"role": "node-library",
"pluginId": "app",
"pluginPackages": [
+ "@backstage/plugin-app",
"@backstage/plugin-app-backend",
"@backstage/plugin-app-node"
]
diff --git a/plugins/app/.eslintrc.js b/plugins/app/.eslintrc.js
new file mode 100644
index 0000000000..e2a53a6ad2
--- /dev/null
+++ b/plugins/app/.eslintrc.js
@@ -0,0 +1 @@
+module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
diff --git a/plugins/app/README.md b/plugins/app/README.md
new file mode 100644
index 0000000000..e258a1671a
--- /dev/null
+++ b/plugins/app/README.md
@@ -0,0 +1,13 @@
+# app
+
+Welcome to the app plugin!
+
+_This plugin was created through the Backstage CLI_
+
+## Getting started
+
+Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/app](http://localhost:3000/app).
+
+You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
+This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
+It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
diff --git a/plugins/app/catalog-info.yaml b/plugins/app/catalog-info.yaml
new file mode 100644
index 0000000000..5bae243ea7
--- /dev/null
+++ b/plugins/app/catalog-info.yaml
@@ -0,0 +1,9 @@
+apiVersion: backstage.io/v1alpha1
+kind: Component
+metadata:
+ name: backstage-plugin-app
+ title: '@backstage/plugin-app'
+spec:
+ lifecycle: experimental
+ type: backstage-frontend-plugin
+ owner: maintainers
diff --git a/plugins/app/package.json b/plugins/app/package.json
new file mode 100644
index 0000000000..72159d96f1
--- /dev/null
+++ b/plugins/app/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "@backstage/plugin-app",
+ "version": "0.0.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.esm.js",
+ "types": "dist/index.d.ts"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/backstage/backstage",
+ "directory": "plugins/app"
+ },
+ "backstage": {
+ "role": "frontend-plugin",
+ "pluginId": "app",
+ "pluginPackages": [
+ "@backstage/plugin-app",
+ "@backstage/plugin-app-backend",
+ "@backstage/plugin-app-node"
+ ]
+ },
+ "sideEffects": false,
+ "scripts": {
+ "start": "backstage-cli package start",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack"
+ },
+ "dependencies": {
+ "@backstage/core-components": "workspace:^",
+ "@backstage/frontend-plugin-api": "workspace:^",
+ "@backstage/theme": "workspace:^",
+ "@material-ui/core": "^4.9.13",
+ "@material-ui/icons": "^4.9.1",
+ "@material-ui/lab": "^4.0.0-alpha.61",
+ "react-use": "^17.2.4"
+ },
+ "peerDependencies": {
+ "react": "^16.13.1 || ^17.0.0 || ^18.0.0"
+ },
+ "devDependencies": {
+ "@backstage/cli": "workspace:^",
+ "@backstage/dev-utils": "workspace:^",
+ "@backstage/frontend-test-utils": "workspace:^",
+ "@testing-library/jest-dom": "^6.0.0",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.0.0",
+ "msw": "^1.0.0",
+ "react": "^16.13.1 || ^17.0.0 || ^18.0.0"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/app/src/index.ts b/plugins/app/src/index.ts
new file mode 100644
index 0000000000..24f65df618
--- /dev/null
+++ b/plugins/app/src/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2024 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.
+ */
+
+export { appPlugin as default } from './plugin';
diff --git a/plugins/app/src/plugin.test.ts b/plugins/app/src/plugin.test.ts
new file mode 100644
index 0000000000..80588710a5
--- /dev/null
+++ b/plugins/app/src/plugin.test.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 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 { appPlugin } from './plugin';
+
+describe('app', () => {
+ it('should export plugin', () => {
+ expect(appPlugin).toBeDefined();
+ });
+});
diff --git a/plugins/app/src/plugin.ts b/plugins/app/src/plugin.ts
new file mode 100644
index 0000000000..2c032bcb5e
--- /dev/null
+++ b/plugins/app/src/plugin.ts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 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 { createFrontendPlugin } from '@backstage/frontend-plugin-api';
+
+export const appPlugin = createFrontendPlugin({
+ id: 'app',
+ extensions: [],
+});
diff --git a/plugins/app/src/setupTests.ts b/plugins/app/src/setupTests.ts
new file mode 100644
index 0000000000..658016ffdd
--- /dev/null
+++ b/plugins/app/src/setupTests.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2024 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 '@testing-library/jest-dom';
diff --git a/yarn.lock b/yarn.lock
index ce072776c3..c745d980d3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4684,6 +4684,30 @@ __metadata:
languageName: unknown
linkType: soft
+"@backstage/plugin-app@^0.0.0, @backstage/plugin-app@workspace:plugins/app":
+ version: 0.0.0-use.local
+ resolution: "@backstage/plugin-app@workspace:plugins/app"
+ dependencies:
+ "@backstage/cli": "workspace:^"
+ "@backstage/core-components": "workspace:^"
+ "@backstage/dev-utils": "workspace:^"
+ "@backstage/frontend-plugin-api": "workspace:^"
+ "@backstage/frontend-test-utils": "workspace:^"
+ "@backstage/theme": "workspace:^"
+ "@material-ui/core": ^4.9.13
+ "@material-ui/icons": ^4.9.1
+ "@material-ui/lab": ^4.0.0-alpha.61
+ "@testing-library/jest-dom": ^6.0.0
+ "@testing-library/react": ^14.0.0
+ "@testing-library/user-event": ^14.0.0
+ msw: ^1.0.0
+ react: ^16.13.1 || ^17.0.0 || ^18.0.0
+ react-use: ^17.2.4
+ peerDependencies:
+ react: ^16.13.1 || ^17.0.0 || ^18.0.0
+ languageName: unknown
+ linkType: soft
+
"@backstage/plugin-auth-backend-module-atlassian-provider@workspace:^, @backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider":
version: 0.0.0-use.local
resolution: "@backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider"
@@ -16954,6 +16978,22 @@ __metadata:
languageName: node
linkType: hard
+"@testing-library/dom@npm:^9.0.0":
+ version: 9.3.4
+ resolution: "@testing-library/dom@npm:9.3.4"
+ dependencies:
+ "@babel/code-frame": ^7.10.4
+ "@babel/runtime": ^7.12.5
+ "@types/aria-query": ^5.0.1
+ aria-query: 5.1.3
+ chalk: ^4.1.0
+ dom-accessibility-api: ^0.5.9
+ lz-string: ^1.5.0
+ pretty-format: ^27.0.2
+ checksum: dfd6fb0d6c7b4dd716ba3c47309bc9541b4a55772cb61758b4f396b3785efe2dbc75dc63423545c039078c7ffcc5e4b8c67c2db1b6af4799580466036f70026f
+ languageName: node
+ linkType: hard
+
"@testing-library/jest-dom@npm:^6.0.0":
version: 6.4.2
resolution: "@testing-library/jest-dom@npm:6.4.2"
@@ -17009,6 +17049,20 @@ __metadata:
languageName: node
linkType: hard
+"@testing-library/react@npm:^14.0.0":
+ version: 14.3.1
+ resolution: "@testing-library/react@npm:14.3.1"
+ dependencies:
+ "@babel/runtime": ^7.12.5
+ "@testing-library/dom": ^9.0.0
+ "@types/react-dom": ^18.0.0
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ checksum: b057d4c9db5a523acfc24d7bc4665a924ab8d6f252c7f51eecf7dd30f1239413e1134925fd5cc9cbdef80496af64c04e6719b2081f89fe05ba87e8c6305bcc16
+ languageName: node
+ linkType: hard
+
"@testing-library/react@npm:^15.0.0":
version: 15.0.2
resolution: "@testing-library/react@npm:15.0.2"
@@ -20970,6 +21024,15 @@ __metadata:
languageName: node
linkType: hard
+"aria-query@npm:5.1.3":
+ version: 5.1.3
+ resolution: "aria-query@npm:5.1.3"
+ dependencies:
+ deep-equal: ^2.0.5
+ checksum: 929ff95f02857b650fb4cbcd2f41072eee2f46159a6605ea03bf63aa572e35ffdff43d69e815ddc462e16e07de8faba3978afc2813650b4448ee18c9895d982b
+ languageName: node
+ linkType: hard
+
"aria-query@npm:5.3.0, aria-query@npm:^5.0.0, aria-query@npm:^5.3.0":
version: 5.3.0
resolution: "aria-query@npm:5.3.0"
@@ -20986,7 +21049,7 @@ __metadata:
languageName: node
linkType: hard
-"array-buffer-byte-length@npm:^1.0.1":
+"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1":
version: 1.0.1
resolution: "array-buffer-byte-length@npm:1.0.1"
dependencies:
@@ -24695,6 +24758,32 @@ __metadata:
languageName: node
linkType: hard
+"deep-equal@npm:^2.0.5":
+ version: 2.2.3
+ resolution: "deep-equal@npm:2.2.3"
+ dependencies:
+ array-buffer-byte-length: ^1.0.0
+ call-bind: ^1.0.5
+ es-get-iterator: ^1.1.3
+ get-intrinsic: ^1.2.2
+ is-arguments: ^1.1.1
+ is-array-buffer: ^3.0.2
+ is-date-object: ^1.0.5
+ is-regex: ^1.1.4
+ is-shared-array-buffer: ^1.0.2
+ isarray: ^2.0.5
+ object-is: ^1.1.5
+ object-keys: ^1.1.1
+ object.assign: ^4.1.4
+ regexp.prototype.flags: ^1.5.1
+ side-channel: ^1.0.4
+ which-boxed-primitive: ^1.0.2
+ which-collection: ^1.0.1
+ which-typed-array: ^1.1.13
+ checksum: ee8852f23e4d20a5626c13b02f415ba443a1b30b4b3d39eaf366d59c4a85e6545d7ec917db44d476a85ae5a86064f7e5f7af7479f38f113995ba869f3a1ddc53
+ languageName: node
+ linkType: hard
+
"deep-equal@npm:~1.0.1":
version: 1.0.1
resolution: "deep-equal@npm:1.0.1"
@@ -25771,6 +25860,23 @@ __metadata:
languageName: node
linkType: hard
+"es-get-iterator@npm:^1.1.3":
+ version: 1.1.3
+ resolution: "es-get-iterator@npm:1.1.3"
+ dependencies:
+ call-bind: ^1.0.2
+ get-intrinsic: ^1.1.3
+ has-symbols: ^1.0.3
+ is-arguments: ^1.1.1
+ is-map: ^2.0.2
+ is-set: ^2.0.2
+ is-string: ^1.0.7
+ isarray: ^2.0.5
+ stop-iteration-iterator: ^1.0.0
+ checksum: 8fa118da42667a01a7c7529f8a8cca514feeff243feec1ce0bb73baaa3514560bd09d2b3438873cf8a5aaec5d52da248131de153b28e2638a061b6e4df13267d
+ languageName: node
+ linkType: hard
+
"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.19":
version: 1.0.19
resolution: "es-iterator-helpers@npm:1.0.19"
@@ -26812,6 +26918,7 @@ __metadata:
"@backstage/frontend-app-api": "workspace:^"
"@backstage/integration-react": "workspace:^"
"@backstage/plugin-api-docs": "workspace:^"
+ "@backstage/plugin-app": ^0.0.0
"@backstage/plugin-auth-react": "workspace:^"
"@backstage/plugin-catalog": "workspace:^"
"@backstage/plugin-catalog-common": "workspace:^"
@@ -28215,7 +28322,7 @@ __metadata:
languageName: node
linkType: hard
-"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
+"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
version: 1.2.4
resolution: "get-intrinsic@npm:1.2.4"
dependencies:
@@ -29878,7 +29985,7 @@ __metadata:
languageName: node
linkType: hard
-"internal-slot@npm:^1.0.7":
+"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7":
version: 1.0.7
resolution: "internal-slot@npm:1.0.7"
dependencies:
@@ -30017,7 +30124,7 @@ __metadata:
languageName: node
linkType: hard
-"is-arguments@npm:^1.0.4":
+"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1":
version: 1.1.1
resolution: "is-arguments@npm:1.1.1"
dependencies:
@@ -30027,7 +30134,7 @@ __metadata:
languageName: node
linkType: hard
-"is-array-buffer@npm:^3.0.4":
+"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4":
version: 3.0.4
resolution: "is-array-buffer@npm:3.0.4"
dependencies:
@@ -30325,10 +30432,10 @@ __metadata:
languageName: node
linkType: hard
-"is-map@npm:^2.0.1":
- version: 2.0.2
- resolution: "is-map@npm:2.0.2"
- checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728
+"is-map@npm:^2.0.1, is-map@npm:^2.0.2":
+ version: 2.0.3
+ resolution: "is-map@npm:2.0.3"
+ checksum: e6ce5f6380f32b141b3153e6ba9074892bbbbd655e92e7ba5ff195239777e767a976dcd4e22f864accaf30e53ebf961ab1995424aef91af68788f0591b7396cc
languageName: node
linkType: hard
@@ -30542,10 +30649,10 @@ __metadata:
languageName: node
linkType: hard
-"is-set@npm:^2.0.1":
- version: 2.0.2
- resolution: "is-set@npm:2.0.2"
- checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57
+"is-set@npm:^2.0.1, is-set@npm:^2.0.2":
+ version: 2.0.3
+ resolution: "is-set@npm:2.0.3"
+ checksum: 36e3f8c44bdbe9496c9689762cc4110f6a6a12b767c5d74c0398176aa2678d4467e3bf07595556f2dba897751bde1422480212b97d973c7b08a343100b0c0dfe
languageName: node
linkType: hard
@@ -35646,13 +35753,13 @@ __metadata:
languageName: node
linkType: hard
-"object-is@npm:^1.0.1":
- version: 1.1.5
- resolution: "object-is@npm:1.1.5"
+"object-is@npm:^1.0.1, object-is@npm:^1.1.5":
+ version: 1.1.6
+ resolution: "object-is@npm:1.1.6"
dependencies:
- call-bind: ^1.0.2
- define-properties: ^1.1.3
- checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe
+ call-bind: ^1.0.7
+ define-properties: ^1.2.1
+ checksum: 3ea22759967e6f2380a2cbbd0f737b42dc9ddb2dfefdb159a1b927fea57335e1b058b564bfa94417db8ad58cddab33621a035de6f5e5ad56d89f2dd03e66c6a1
languageName: node
linkType: hard
@@ -39046,7 +39153,7 @@ __metadata:
languageName: node
linkType: hard
-"react@npm:^18.0.2":
+"react@npm:^16.13.1 || ^17.0.0 || ^18.0.0, react@npm:^18.0.2":
version: 18.3.1
resolution: "react@npm:18.3.1"
dependencies:
@@ -39359,7 +39466,7 @@ __metadata:
languageName: node
linkType: hard
-"regexp.prototype.flags@npm:^1.5.2":
+"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2":
version: 1.5.2
resolution: "regexp.prototype.flags@npm:1.5.2"
dependencies:
@@ -41411,6 +41518,15 @@ __metadata:
languageName: node
linkType: hard
+"stop-iteration-iterator@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "stop-iteration-iterator@npm:1.0.0"
+ dependencies:
+ internal-slot: ^1.0.4
+ checksum: d04173690b2efa40e24ab70e5e51a3ff31d56d699550cfad084104ab3381390daccb36652b25755e420245f3b0737de66c1879eaa2a8d4fc0a78f9bf892fcb42
+ languageName: node
+ linkType: hard
+
"stoppable@npm:^1.1.0":
version: 1.1.0
resolution: "stoppable@npm:1.1.0"
@@ -44686,7 +44802,7 @@ __metadata:
languageName: node
linkType: hard
-"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9":
+"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9":
version: 1.1.15
resolution: "which-typed-array@npm:1.1.15"
dependencies: