Skip to main content
Version: Next

Usage

Notifications Backend

The Notifications backend plugin provides an API to create notifications, list notifications per logged-in user, and search based on parameters.

The plugin uses a relational database for persistence; no specifics are introduced in this context.

No additional configuration in the app-config is needed, except for optional additional modules for processors.

Notifications Frontend

The recipients of notifications have to be entities in the catalog, e.g., of the User or Group kind.

Otherwise, no specific configuration is needed for the front-end notifications plugin.

All parametrization is done through component properties, such as the NotificationsSidebarItem, which can be used as an active left-side menu item in the front-end.

Notifications Page

In the packages/app/src/components/Root/Root.tsx, tweak the properties of the <NotificationsSidebarItem /> per specific needs.

Usage

New notifications can be sent either by a backend plugin or an external service through the REST API.

Backend

Regardless of technical feasibility, a backend plugin should avoid directly accessing the notifications REST API. Instead, it should integrate with the @backstage/plugin-notifications-node to send (create) a new notification.

The reasons for this approach include the propagation of authorization in the API request and improved maintenance and backward compatibility in the future.

import { notificationService } from '@backstage/plugin-notifications-node';

export const myPlugin = createBackendPlugin({
pluginId: 'myPlugin',
register(env) {
env.registerInit({
deps: {
// ...
notificationService: notificationService,
},
async init({
// ...
notificationService,
}) {
httpRouter.use(
await createRouter({
// ...
notificationService,
}),
);
},
});
},
});

To emit a new notification:

await notificationService.send({
recipients /* of the broadcast or entity type */,
payload /* actual message */,
});

Refer the API documentation for further details.

External Services

When the emitter of a notification is a Backstage backend plugin, it is mandatory to use the integration via @backstage/plugin-notifications-node as described above.

If the emitter is a service external to Backstage, an HTTP POST request can be issued directly to the API, assuming that authentication is properly configured. Refer to the service-to-service auth documentation for more details, focusing on the Static Tokens section for the simplest setup option.

An example request for creating a broadcast notification might look like:

curl -X POST https://[BACKSTAGE_BACKEND]/api/notifications -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_BASE64_SHARED_KEY_TOKEN" -d '{"recipients":{"type":"broadcast"},"payload": {"title": "Title of broadcast message","link": "http://foo.com/bar","severity": "high","topic": "The topic"}}'

Scaffolder Templates

You can use the @backstage/plugin-scaffolder-backend-module-notifications to send notifications when scaffolder templates are run. To install the module, add it to your backend plugin:

yarn workspace backend add @backstage/plugin-scaffolder-backend-module-notifications

Then, add the module to your backend:

const backend = createBackend();
// ...
backend.add(
import('@backstage/plugin-scaffolder-backend-module-notifications'),
);

In your template you can now use notification:send action as part of the steps:

steps:
- id: notify
name: Notify
action: notification:send
input:
recipients: entity
entityRefs:
- component:default/backstage
title: 'Template executed'
info: 'Your template has been executed'
severity: 'info'
link: https://backstage.io

Signals

The use of signals with notifications is optional but generally enhances user experience and performance.

When a notification is created, a new signal is emitted to a general-purpose message bus to announce it to subscribed listeners.

The frontend maintains a persistent connection (WebSocket) to receive these announcements from the notifications channel. The specific details of the updated or created notification should be retrieved via a request to the notifications API, except for new notifications, where the payload is included in the signal for performance reasons.

In a frontend plugin, to subscribe to notifications' signals:

import { useSignal } from '@backstage/plugin-signals-react';

const { lastSignal } = useSignal<NotificationSignal>('notifications');

React.useEffect(() => {
/* ... */
}, [lastSignal, notificationsApi]);

Using signals in your own plugin

It's possible to use signals in your own plugin to deliver data from the backend to the frontend in near real-time.

To use signals in your own frontend plugin, you need to add the useSignal hook from @backstage/plugin-signals-react from @backstage/plugin-notifications-common with optional generic type of the signal.

// To use the same type of signal in the backend, this should be placed in a shared common package
export type MySignalType = {
user: string;
data: string;
// ....
};

const { lastSignal } = useSignal<MySignalType>('my-plugin');

useEffect(() => {
if (lastSignal) {
// Do something with the signal
}
}, [lastSignal]);

To send signals from the backend plugin, you must add the signalsServiceRef to your plugin or module as a dependency.

import { signalsServiceRef } from '@backstage/plugin-signals-node';
export const myPlugin = createBackendPlugin({
pluginId: 'my',
register(env) {
env.registerInit({
deps: {
httpRouter: coreServices.httpRouter,
signals: signalsServiceRef,
},
async init({ httpRouter, signals }) {
httpRouter.use(
await createRouter({
signals,
}),
);
},
});
},
});

To send the signal using the service, you can use the publish method.

signals.publish<MySignalType>({ user: 'user', data: 'test' });

Consuming Notifications

In a front-end plugin, the simplest way to query a notification is by its ID:

import { useApi } from '@backstage/core-plugin-api';
import { notificationsApiRef } from '@backstage/plugin-notifications';

const notificationsApi = useApi(notificationsApiRef);

notificationsApi.getNotification(yourId);

// or with connection to signals:
notificationsApi.getNotification(lastSignal.notification_id);