Badges logo

Backstage Badges Plugin

Created by Andreas Stenius

Badges adds tiny status images for your Backstage catalog. They show facts like owner, lifecycle, docs, and component name. You place them outside Backstage. For example in a repository readme or a docs site. Each badge links back to the right entity page so people can jump into the catalog fast.

The plugin adds a Badges item to the entity page menu. Open it to see all badges for that entity. Copy the markdown it gives you. Paste it where you want the badge to show. The images are rendered from catalog data, so they stay current as your metadata changes.

Common uses are simple. Mark the owner on every repo. Show lifecycle on the main readme. Prove docs exist on a service page. Give a quick path back to your portal from external docs. Signal standards or maturity across teams without extra work.

You can choose which badges exist in your setup. The backend decides the set of badges and how they look. There is support for obfuscation when badges are public. That helps reduce the risk of people guessing entity names while still keeping badges visible.

If you run Backstage yourself, Badges helps spread clear signals across your codebase. It turns catalog facts into small links people actually see and use.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

  1. From your Backstage root run
    Copy
    yarn --cwd packages/app add @backstage-community/plugin-badges

Register the frontend plugin

  1. If you already use a plugins file add the import there

    Copy
    // packages/app/src/plugins.ts
    import { badgesPlugin } from '@backstage-community/plugin-badges';

    Then make sure your App uses that plugins file

    Copy
    // packages/app/src/App.tsx
    + import * as plugins from './plugins';
    
    const app = createApp({
      apis,
    + plugins: Object.values(plugins),
      bindRoutes({ bind }) {
        /* ... */
      },
    });
  2. If you do not use a plugins file you can register the plugin in App directly

    Copy
    // packages/app/src/App.tsx
    + import { badgesPlugin } from '@backstage-community/plugin-badges';
    
    const app = createApp({
      apis,
    + plugins: [badgesPlugin],
      bindRoutes({ bind }) {
        /* ... */
      },
    });

Add the badges menu to your entity page

  1. Open your entity page component

    Copy
    packages/app/src/components/catalog/EntityPage.tsx
  2. Add the imports

    Copy
    import { EntityBadgesDialog } from '@backstage-community/plugin-badges';
    import BadgeIcon from '@material-ui/icons/CallToAction';
  3. Update the React import to include the needed hooks

    Copy
    - import React from 'react';
    + import React, { ReactNode, useMemo, useState } from 'react';
  4. Add the layout wrapper right after the imports

    Copy
    const EntityLayoutWrapper = (props: { children?: ReactNode }) => {
      const [badgesDialogOpen, setBadgesDialogOpen] = useState(false);
    
      const extraMenuItems = useMemo(() => {
        return [
          {
            title: 'Badges',
            Icon: BadgeIcon,
            onClick: () => setBadgesDialogOpen(true),
          },
        ];
      }, []);
    
      return (
        <>
          <EntityLayout UNSTABLE_extraContextMenuItems={extraMenuItems}>
            {props.children}
          </EntityLayout>
          <EntityBadgesDialog
            open={badgesDialogOpen}
            onClose={() => setBadgesDialogOpen(false)}
          />
        </>
      );
    };
  5. Wrap your entity routes with the wrapper

    Copy
    const defaultEntityPage = (
    +  <EntityLayoutWrapper>
        <EntityLayout.Route path="/" title="Overview">
          {overviewContent}
        </EntityLayout.Route>
    
        <EntityLayout.Route path="/docs" title="Docs">
          <EntityTechdocsContent />
        </EntityLayout.Route>
    
        <EntityLayout.Route path="/todos" title="TODOs">
          <EntityTodoContent />
        </EntityLayout.Route>
    +  </EntityLayoutWrapper>
    );

Optional badge URL obfuscation in the frontend

  1. Add the setting in app config

    Copy
    # app-config.yaml
    app:
      badges:
        obfuscate: true
  2. Expose the config to the frontend

    Copy
    // packages/app/src/config.d.ts
    export interface Config {
      app: {
        badges: {
          /**
           * badges obfuscate
           * @visibility frontend
           */
          obfuscate?: string;
        };
      };
    }
  3. Make sure your app package includes the schema

    Copy
    // packages/app/package.json
    {
      "files": [
        "dist",
        "config.d.ts"
      ],
      "configSchema": "config.d.ts"
    }
  4. The backend must be configured to support obfuscation Match your backend config with this setting

Install the backend plugin new backend system

  1. Add the backend package

    Copy
    yarn --cwd packages/backend add @backstage-community/plugin-badges-backend
  2. Register the plugin in your backend entry point

    Copy
    // packages/backend/src/index.ts
    import { createBackend } from '@backstage/backend-defaults';
    import { badgesPlugin } from '@backstage-community/plugin-badges-backend';
    
    const backend = createBackend();
    
    backend.add(badgesPlugin());
    
    backend.start();
  3. The service exposes routes under the badges path Your app will serve them under api badges

  4. If you use obfuscation add the related backend config as required by the plugin

Install the backend plugin legacy backend system

  1. Add the backend package

    Copy
    yarn --cwd packages/backend add @backstage-community/plugin-badges-backend
  2. Create the plugin router

    Copy
    // packages/backend/src/plugins/badges.ts
    import { Router } from 'express';
    import { createRouter } from '@backstage-community/plugin-badges-backend';
    import type { PluginEnvironment } from '../types';
    import { CatalogClient } from '@backstage/catalog-client';
    
    export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
      const catalogClient = new CatalogClient({ discoveryApi: env.discovery });
    
      return await createRouter({
        logger: env.logger,
        config: env.config,
        catalogClient,
      });
    }
  3. Mount the router in the backend

    Copy
    // packages/backend/src/index.ts
    import Router from 'express-promise-router';
    import { ServerTokenManager } from '@backstage/backend-common';
    import type { PluginEnvironment } from './types';
    import catalog from './plugins/catalog';
    + import badges from './plugins/badges';
    
    async function main() {
      const logger = getRootLogger();
      const config = await loadBackendConfig();
      const tokenManager = ServerTokenManager.noop();
    
      const env: PluginEnvironment = await createEnv({ logger, config, tokenManager });
    
      const apiRouter = Router();
      apiRouter.use('/catalog', await catalog(env));
    +  apiRouter.use('/badges', await badges(env));
    
      const service = createServiceBuilder(module)
        .setPort(7007)
        .addRouter('/api', apiRouter);
    
      await service.start();
    }
  4. Your app will serve the badges under api badges

  5. If you use obfuscation add the related backend config as required by the plugin

Where to see the plugin in the UI

  1. Open any entity page in your Backstage app
  2. Use the three dots menu on the top right
  3. Click Badges to open the dialog
  4. Copy the markdown for the badges you want and put it in your repository readme or docs

Changelog

This changelog is produced from commits made to the Badges 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.

Features

  • Support style and color query params in obfuscated mode. Badge style selection now works when obfuscation is on #5139 merged 1 month ago

Deprecations

  • Deprecate the legacy badges backend. Migrate to the new backend API soon #2044 merged 10 months ago

Documentation

  • Update README links to point to the community plugins repo #3931 merged 5 months ago

Maintenance

  • Remove usage of the backend common package in badges code #2479 merged 7 months ago
  • Remove unused canvas dev dependency #3565 merged 6 months ago
  • Reduce knip false positives by updating repo tools config #3018 merged 7 months ago
  • Update types uuid dev dependency to v10 #2233 merged 8 months ago

Set up Backstage in minutes with Roadie