Catalog Graph adds a visual map to your Backstage catalog. It shows how your entities connect across ownership, APIs, groups, and dependencies. You get a quick read on what touches what, so you can reason about impact and trace responsibility without leaving your portal.
The plugin offers two main views. There is a card on each entity that surfaces direct neighbors for fast context. There is a full page that lets you explore the wider graph. You can filter by kind or relation, change layout direction, set max depth, and choose how edges render. This keeps large catalogs readable while you zoom or step through the model.
Engineers use it to answer common questions during everyday work. What services consume this API. Who owns that job. What systems this change could affect. It helps with onboarding since new teammates can see the landscape in minutes. It supports discovery work too, like finding unknown dependencies before a migration or audit. The UI builds on the catalog’s relation model, so it fits naturally with how Backstage stores and queries data.
If you already run Backstage with a populated catalog, Catalog Graph gives you a clear picture of your ecosystem with low ceremony. It is simple to adopt in stages. Start with the entity card for quick wins, then open the page view when you need deeper exploration.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
What you get
This plugin is frontend only. There is no backend package to install.
You can use it in two frontend setups
- legacy app system
- new frontend system
Follow the section that matches your app. You can install both safely. The plugin will work in either setup.
Legacy app system
-
Add the dependency to your app
yarn --cwd packages/app add @backstage/plugin-catalog-graph
-
Add the Catalog Graph page route in packages/app/src/App.tsx
// packages/app/src/App.tsx import React from 'react'; import { createApp } from '@backstage/app-defaults'; import { FlatRoutes } from '@backstage/core-app-api'; import { Route } from 'react-router-dom'; import { CatalogGraphPage, catalogGraphPlugin } from '@backstage/plugin-catalog-graph'; import { catalogPlugin } from '@backstage/plugin-catalog'; const app = createApp({ bindRoutes({ bind }) { bind(catalogGraphPlugin.externalRoutes, { catalogEntity: catalogPlugin.routes.catalogEntity, }); }, }); const AppProvider = app.getProvider(); const AppRouter = app.getRouter(); export const App = () => ( <AppProvider> <AppRouter> <FlatRoutes> {/* other routes */} <Route path="/catalog-graph" element={<CatalogGraphPage />} /> </FlatRoutes> </AppRouter> </AppProvider> );
Optional initial filters
<Route path="/catalog-graph" element={ <CatalogGraphPage initialState={{ selectedKinds: ['component', 'domain', 'system', 'api', 'group'], }} /> } />
-
Add the graph card to your entity page so users can see relations on each entity
// packages/app/src/components/catalog/EntityPage.tsx import React from 'react'; import Grid from '@material-ui/core/Grid'; import { EntityCatalogGraphCard } from '@backstage/plugin-catalog-graph'; export const OverviewContent = () => ( <Grid container spacing={3}> {/* other cards */} <Grid item md={6} xs={12}> <EntityCatalogGraphCard variant="gridItem" height={400} /> </Grid> </Grid> );
Optional arrow heads for edges
<EntityCatalogGraphCard variant="gridItem" height={400} showArrowHeads />
-
Optional custom relations
Register the default API with your own relation list in packages/app/src/apis.ts// packages/app/src/apis.ts import { createApiFactory } from '@backstage/core-plugin-api'; import { ALL_RELATIONS, ALL_RELATION_PAIRS, catalogGraphApiRef, DefaultCatalogGraphApi, } from '@backstage/plugin-catalog-graph'; export const apis = [ createApiFactory({ api: catalogGraphApiRef, deps: {}, factory: () => new DefaultCatalogGraphApi({ knownRelations: [...ALL_RELATIONS, 'myRelationOf', 'myRelationFor'], knownRelationPairs: [ ...ALL_RELATION_PAIRS, ['myRelationOf', 'myRelationFor'], ], defaultRelationTypes: { exclude: ['myRelationOf', 'myRelationFor'], }, }), }), // other APIs ];
-
Optional custom node rendering on the page
// packages/app/src/App.tsx import { CatalogGraphPage } from '@backstage/plugin-catalog-graph'; import { MyCustomRenderNode } from './components/MyCustomRenderNode'; <Route path="/catalog-graph" element={<CatalogGraphPage renderNode={MyCustomRenderNode} />} />
-
Optional custom node rendering on the card
// packages/app/src/components/catalog/EntityPage.tsx import { EntityCatalogGraphCard } from '@backstage/plugin-catalog-graph'; import { MyCustomRenderNode } from '../MyCustomRenderNode'; <EntityCatalogGraphCard variant="gridItem" height={400} renderNode={MyCustomRenderNode} />
-
Optional direct use of the lower level component if you need a fully custom view
// any component file import React from 'react'; import { EntityRelationsGraph, Direction } from '@backstage/plugin-catalog-graph'; export const MyGraph = () => ( <EntityRelationsGraph rootEntityNames={{ kind: 'Component', namespace: 'default', name: 'my-service' }} maxDepth={2} direction={Direction.LEFT_RIGHT} mergeRelations unidirectional /> );
New frontend system
-
Add the dependency to your app
yarn --cwd packages/app add @backstage/plugin-catalog-graph
-
Enable the entity relations card in app-config.yaml
The card is not enabled by default# app-config.yaml app: packages: all extensions: - entity-card:catalog-graph/relations
Optional card config
# app-config.yaml app: extensions: - entity-card:catalog-graph/relations: config: title: 'Entities Relations Graph' height: 400 maxDepth: 1 unidirectional: true mergeRelations: true direction: LR zoom: enabled
-
The graph page is enabled by default
You can change the path# app-config.yaml app: extensions: - page:catalog-graph: config: path: '/entity-graph'
Optional initial filters on the page
# app-config.yaml app: extensions: - page:catalog-graph: config: initialState: selectedKinds: ['component', 'domain', 'system', 'api', 'group'] maxDepth: 2 unidirectional: true mergeRelations: true direction: LR curve: curveStepBefore
-
Optional route bindings in config
Bind the external entity page reference if your app uses a non default entity route
Or point another plugin route to the catalog graph page# app-config.yaml app: routes: bindings: catalog-graph.catalogEntity: catalog.catalogEntity some-plugin.some-external-route: catalog-graph.catalogGraph
-
Optional feature discovery rules per environment
# app-config.production.yaml app: packages: include: - '@backstage/plugin-catalog-graph'
# app-config.local.yaml app: packages: exclude: - '@backstage/plugin-catalog-graph'
-
Optional direct use of exported components in custom code
// you can still import and render the page or card in custom modules import { CatalogGraphPage, EntityCatalogGraphCard } from '@backstage/plugin-catalog-graph';
Things to Know
Features
The plugin comes with these features:
-
EntityCatalogGraphCard: A card that displays the directly related entities to the current entity. This card is for use on the entity page. The card can be customized, for example filtering for specific relations.
-
CatalogGraphPage: A standalone page that can be added to your application providing a viewer for your entities and their relations. The viewer can be used to navigate through the entities and filter for specific relations. You can access it from the EntityCatalogGraphCard. NB: you will need to supply props to this component to tell it what root Entity to display when it renders like so:
{
"initialState": {
"rootEntityRefs": [
"domain:customers",
"domain:employees"
],
"maxDepth": 1,
"selectedRelations": [
"dependsOn"
]
}
}
- EntityRelationsGraph: A react component that can be used to build own customized entity relation graphs.
Prerequisites
The plugin will only display relationship that have already been set up between entities. You will need to define these
yourself for services, api’s etc… in the catalog.yaml
files.
i.e.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: wayback-search
description: Search of the wayback machine
spec:
type: service
lifecycle: production
owner: team-a
providesApis:
- wayback-search
consumesApis:
- wayback-archive
For more, please check out this post on how to model software in Backstage.
Changelog
This changelog is produced from commits made to the Catalog Graph plugin since 3 months 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
- Add an API to customize which catalog relations the graph supports and shows by default. The UI now autocompletes custom relations. Default behavior stays the same. #30889 20 days ago
- Add i18n support to the catalog graph plugin. You can localize labels and messages. #30074 3 months ago
Bug fixes
- Fix graph sizing issues in DependencyGraph. Stop indefinite rerender that spiked CPU. The graph now measures size correctly. The Fullscreen button now floats without taking layout space. Contained fit now sizes the inner svg correctly. #31168 13 days ago
- Fix crash in NFS apps due to a missing catalog graph API implementation. Provide a default implementation so the plugin works in NFS again. #31201 16 days ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.