Statuspage.io logo

Backstage Statuspage.io Plugin

Created by AxisCommunications

Statuspage.io Plugin brings your Statuspage status into Backstage. It lets you show components, groups, and a full status view inside your portal. You can add a small card to a service page to track the health of specific components. You can add a full page that mirrors your Statuspage for broad awareness.

This helps teams see outages and planned maintenance where they already work. Common uses include watching internal services, tracking third party dependencies, and giving product teams a quick signal during incidents. Less context switching. Faster decisions.

The plugin ships a simple frontend for cards and pages. It talks to a backend that reads data from the Statuspage API. It can fetch components and component groups. It can provide a link to your public status page when you want to send users there.

Axis Communications builds and shares this plugin. They run their own Backstage instance, and wrote about open-sourcing their Backstage plugins on their engineering blog.

If you are considering adding it to your self hosted Backstage, the value is simple. Put live status next to your catalog and docs. Keep engineers focused.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

Copy
yarn --cwd packages/app add @axis-backstage/plugin-statuspage

Register the API client

Add this to your app apis file.

Copy
// packages/app/src/apis.ts
import { createApiFactory, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
import { statuspageApiRef, StatuspageClient } from '@axis-backstage/plugin-statuspage';

// add to the list of apis
createApiFactory({
  api: statuspageApiRef,
  deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
  factory: ({ discoveryApi, fetchApi }) =>
    new StatuspageClient({ discoveryApi, fetchApi }),
});

Configure your instances

Add one or more instances. Use a secure env var for the token.

Copy
# app-config.yaml
statuspage:
  - name: mystatuspageinstance
    pageid: abc123foo456
    token: ${STATUSPAGE_TOKEN}
    link: https://yourcompany.statuspage.io

You can set the env var in your local config.

Copy
# app-config.local.yaml
statuspage:
  - name: mystatuspageinstance
    pageid: abc123foo456
    token: ${STATUSPAGE_TOKEN}
    link: https://yourcompany.statuspage.io

Set the env var before starting the app.

Copy
export STATUSPAGE_TOKEN=your_token_here

Add the entity card to the catalog entity page

Import the card and the availability helper. Then render the card within your entity page switch.

Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@mui/material/Grid';
import { EntitySwitch } from '@backstage/plugin-catalog';
import { StatuspageEntityCard, isStatuspageAvailable } from '@axis-backstage/plugin-statuspage';

// inside your default entity page layout
const defaultEntityPage = (
  <EntitySwitch>
    <EntitySwitch.Case if={isStatuspageAvailable}>
      <Grid item xs={12}>
        <StatuspageEntityCard />
      </Grid>
    </EntitySwitch.Case>
  </EntitySwitch>
);

Set the catalog annotation on entities that should show the card

Use the instance name from your config. List one or more component ids or group ids separated by commas.

Copy
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: myservice
  annotations:
    statuspage.io/components: mystatuspageinstance:comp_123,grp_456
spec:
  type: service
  owner: team-a
  lifecycle: production

Add a full Statuspage view as a route

This view does not depend on entity context. Pass the instance name from your config.

Copy
// packages/app/src/App.tsx
import React from 'react';
import { Route } from 'react-router';
import { StatuspagePage } from '@axis-backstage/plugin-statuspage';

<Route path="/statuspage" element={<StatuspagePage name="mystatuspageinstance" />} />

Add a link in your sidebar so users can find it.

Copy
// packages/app/src/components/Root/Root.tsx or similar
import { SidebarItem } from '@backstage/core-components';
import AssessmentIcon from '@mui/icons-material/Assessment';

<SidebarItem icon={AssessmentIcon} to="statuspage" text="Statuspage" />

Install the backend for the old backend system

Install the backend package.

Copy
yarn --cwd packages/backend add @axis-backstage/plugin-statuspage-backend

Create a router file.

Copy
// packages/backend/src/plugins/statuspage.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@axis-backstage/plugin-statuspage-backend';

export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
    discovery: env.discovery,
    tokenManager: env.tokenManager,
  });
}

Wire the router in your backend index. Mount it at the expected path.

Copy
// packages/backend/src/index.ts
import statuspage from './plugins/statuspage';

// inside the main bootstrap function
app.use('/api/statuspage', await statuspage(env));

The backend will read the same statuspage config you added in app config. Keep the token in an env var.

Install the backend for the new backend system

Install the backend package.

Copy
yarn --cwd packages/backend add @axis-backstage/plugin-statuspage-backend

Option A. The package provides a backend module export. Add it to your backend.

Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { statuspageModule } from '@axis-backstage/plugin-statuspage-backend';

const backend = createBackend();
backend.add(statuspageModule());
backend.start();

Option B. The package exposes only a router factory. Mount it using the http router service.

Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';
import { createRouter } from '@axis-backstage/plugin-statuspage-backend';

const statuspagePlugin = createBackendPlugin({
  pluginId: 'statuspage',
  register(env) {
    env.registerInit({
      deps: {
        http: coreServices.httpRouter,
        logger: coreServices.logger,
        config: coreServices.rootConfig,
        discovery: coreServices.discovery,
        tokenManager: coreServices.tokenManager,
      },
      async init({ http, logger, config, discovery, tokenManager }) {
        const router = await createRouter({ logger, config, discovery, tokenManager });
        http.use(router);
      },
    });
  },
});

const backend = createBackend();
backend.add(statuspagePlugin);
backend.start();

Both options mount the service under the standard plugin path. The frontend client discovers it through the service discovery api.

Summary of what shows up in the app

  • The entity card appears on entities that have the statuspage io annotation with matching instance and components
  • The full page route shows a dashboard for the instance you pass in the StatuspagePage component
  • The backend reads the statuspage config and uses the token to call the Statuspage io API

Changelog

This changelog is produced from commits made to the Statuspage.io plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Compatibility

  • Update compatibility to Backstage 1.42 for the Statuspage plugin #319 merged 1 month ago
  • Update compatibility to Backstage 1.40 #295 merged 2 months ago
  • Update compatibility to Backstage 1.36.1 #259 merged 7 months ago

Dependencies

  • Fix missing peer deps and bump packages which reduces install warnings #267 merged 7 months ago

Breaking changes

  • None

Set up Backstage in minutes with Roadie