diff --git a/.changeset/endoflife-new-frontend-system.md b/.changeset/endoflife-new-frontend-system.md
new file mode 100644
index 0000000..b0ee404
--- /dev/null
+++ b/.changeset/endoflife-new-frontend-system.md
@@ -0,0 +1,13 @@
+---
+'@dweber019/backstage-plugin-endoflife': minor
+---
+
+Added support for the new frontend system.
+
+A new `/alpha` entry point is now available that exports the plugin as a default export compatible with `createFrontendPlugin`. This includes:
+
+- `ApiBlueprint` for the End of Life API
+- `EntityCardBlueprint` for the End of Life card, filtered to entities carrying one of the end of life annotations
+- `EntityContentBlueprint` for an optional End of Life tab, disabled by default
+
+The existing entry point (`/`) remains unchanged for backward compatibility.
diff --git a/plugins/endoflife/README.md b/plugins/endoflife/README.md
index c98e4c8..e190379 100644
--- a/plugins/endoflife/README.md
+++ b/plugins/endoflife/README.md
@@ -143,6 +143,40 @@ const resourcePage = (
or if you have API entities you could use the annotation `endoflife.date/source-location`
to make version lifecycles visible to consumers.
+### New Frontend System
+
+The section above applies to the old frontend system. If your app runs on the
+[new frontend system](https://backstage.io/docs/frontend-system/), the plugin is picked up
+automatically by package discovery, and there is nothing to add to your `EntityPage`. To install it
+explicitly instead, import the `/alpha` entry point:
+
+```ts
+// packages/app/src/App.tsx
+
+import endOfLifePlugin from '@dweber019/backstage-plugin-endoflife/alpha';
+
+export default createApp({
+ features: [endOfLifePlugin],
+}).createRoot();
+```
+
+The plugin provides the following extensions:
+
+| Extension | Default | Description |
+| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| `api:endoflife` | enabled | The end of life API, the same one exported as `endOfLifeApiRef` from the main entry point. |
+| `entity-card:endoflife` | enabled | The end of life card, on the overview of entities carrying one of the annotations above. |
+| `entity-content:endoflife` | disabled | The same card on an `/endoflife` tab of its own, for apps that prefer a dedicated tab over a card on the overview. |
+
+Enable the tab, or disable the card, through `app-config.yaml`:
+
+```yaml
+app:
+ extensions:
+ - entity-content:endoflife: true
+ - entity-card:endoflife: false
+```
+
### Help text
You can customize the help text in the right upper corner by using the following configuration in `app-config.yaml`
diff --git a/plugins/endoflife/package.json b/plugins/endoflife/package.json
index 335d6a3..be6e7eb 100644
--- a/plugins/endoflife/package.json
+++ b/plugins/endoflife/package.json
@@ -10,6 +10,21 @@
"version": "0.1.2",
"main": "src/index.ts",
"types": "src/index.ts",
+ "exports": {
+ ".": "./src/index.ts",
+ "./alpha": "./src/alpha.tsx",
+ "./package.json": "./package.json"
+ },
+ "typesVersions": {
+ "*": {
+ "alpha": [
+ "src/alpha.tsx"
+ ],
+ "package.json": [
+ "package.json"
+ ]
+ }
+ },
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
@@ -38,6 +53,7 @@
"@backstage/core-components": "^0.18.4",
"@backstage/core-plugin-api": "^1.12.1",
"@backstage/errors": "^1.2.7",
+ "@backstage/frontend-plugin-api": "^0.13.2",
"@backstage/integration-react": "^1.2.13",
"@backstage/plugin-catalog-react": "^1.21.4",
"@egjs/hammerjs": "^2.0.17",
diff --git a/plugins/endoflife/src/alpha.test.tsx b/plugins/endoflife/src/alpha.test.tsx
new file mode 100644
index 0000000..8db9e74
--- /dev/null
+++ b/plugins/endoflife/src/alpha.test.tsx
@@ -0,0 +1,7 @@
+import plugin from './alpha';
+
+describe('EndOfLife new frontend system', () => {
+ it('should export the plugin as default', () => {
+ expect(plugin).toBeDefined();
+ });
+});
diff --git a/plugins/endoflife/src/alpha.tsx b/plugins/endoflife/src/alpha.tsx
new file mode 100644
index 0000000..ab1d229
--- /dev/null
+++ b/plugins/endoflife/src/alpha.tsx
@@ -0,0 +1,86 @@
+import {
+ ApiBlueprint,
+ configApiRef,
+ createFrontendPlugin,
+ discoveryApiRef,
+ fetchApiRef,
+ identityApiRef,
+} from '@backstage/frontend-plugin-api';
+import {
+ EntityCardBlueprint,
+ EntityContentBlueprint,
+} from '@backstage/plugin-catalog-react/alpha';
+import { endOfLifeApiRef, EndOfLifeClient } from './api';
+import { isEndOfLifeAvailable } from './conditions';
+
+/**
+ * Provides the end of life API as an extension.
+ * @alpha
+ */
+const endOfLifeApi = ApiBlueprint.make({
+ params: defineParams =>
+ defineParams({
+ api: endOfLifeApiRef,
+ deps: {
+ discoveryApi: discoveryApiRef,
+ fetchApi: fetchApiRef,
+ identityApi: identityApiRef,
+ configApi: configApiRef,
+ },
+ factory: ({ discoveryApi, fetchApi, identityApi, configApi }) =>
+ new EndOfLifeClient({
+ baseUrl:
+ configApi.getOptionalString('endOfLife.baseUrl') ??
+ 'https://endoflife.date',
+ discoveryApi,
+ fetchApi,
+ identityApi,
+ }),
+ }),
+});
+
+/**
+ * Entity card that renders the end of life timeline, on entities carrying one
+ * of the end of life annotations.
+ * @alpha
+ */
+const endOfLifeCard = EntityCardBlueprint.make({
+ params: {
+ type: 'content',
+ filter: isEndOfLifeAvailable,
+ loader: () =>
+ import('./components/EntityEndOfLifeCard').then(m => (
+
+ )),
+ },
+});
+
+/**
+ * Entity content that renders the end of life timeline on a tab of its own.
+ *
+ * Disabled by default, since the card above already covers the setup described
+ * in the plugin README. Apps that prefer a dedicated tab enable it through
+ * `app.extensions`.
+ * @alpha
+ */
+const endOfLifeContent = EntityContentBlueprint.make({
+ disabled: true,
+ params: {
+ path: '/endoflife',
+ title: 'End of life',
+ filter: isEndOfLifeAvailable,
+ loader: () =>
+ import('./components/EntityEndOfLifeCard').then(m => (
+
+ )),
+ },
+});
+
+/**
+ * The end of life plugin, for use with the new frontend system.
+ * @alpha
+ */
+export default createFrontendPlugin({
+ pluginId: 'endoflife',
+ extensions: [endOfLifeApi, endOfLifeCard, endOfLifeContent],
+});
diff --git a/yarn.lock b/yarn.lock
index ba92bee..af3912b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4957,6 +4957,7 @@ __metadata:
"@backstage/core-plugin-api": "npm:^1.12.1"
"@backstage/dev-utils": "npm:^1.1.18"
"@backstage/errors": "npm:^1.2.7"
+ "@backstage/frontend-plugin-api": "npm:^0.13.2"
"@backstage/integration": "npm:^1.19.0"
"@backstage/integration-react": "npm:^1.2.13"
"@backstage/plugin-catalog-react": "npm:^1.21.4"