System scoring gives you a clear way to track the health and maturity of your software. It looks at the things that matter in day to day work. Code quality. Test coverage. Operations readiness. Documentation. Security. The goal is not a perfect score. The goal is to show where to focus next and to make progress visible over time.
The System scoring Backstage plugin brings those scores into your portal. It works with any catalog entity. You get a score board to scan many entities at once. You get a table view that is easy to sort or filter. On each entity page you can open a detailed card. It shows the total score and the pieces that make it up. It explains why a rule passed or failed. It can point the team to a simple todo so action is clear.
Common use cases are production readiness checks and audit prep. Teams use it to keep standards in view during migrations. Leaders use it to spot risk across a large catalog. The data model is simple. Scores come from JSON that your pipeline or process updates on a schedule. The plugin reads that data and renders it in Backstage.
If you run a self hosted Backstage, this plugin turns your standards into a living view that teams will actually use.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the package
# from your Backstage root directory
yarn add --cwd packages/app @oriflame/backstage-plugin-score-card
Add the Score board page route
Edit packages/app/src/App.tsx
import React from 'react';
import { Route } from 'react-router-dom';
import { FlatRoutes } from '@backstage/core-app-api';
import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card';
export const AppRoutes = () => (
<FlatRoutes>
{/* your existing routes */}
<Route path="/score-board" element={<ScoreBoardPage />} />
</FlatRoutes>
);
Add a sidebar link
Edit packages/app/src/components/Root/Root.tsx
import React, { PropsWithChildren } from 'react';
import { SidebarPage, Sidebar, SidebarGroup, SidebarItem, SidebarScrollWrapper } from '@backstage/core-components';
import MenuIcon from '@material-ui/icons/Menu';
import Score from '@material-ui/icons/Score';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarGroup label="Menu" icon={<MenuIcon />}>
<SidebarScrollWrapper>
{/* your existing items */}
<SidebarItem icon={Score} to="score-board" text="Score board" />
</SidebarScrollWrapper>
</SidebarGroup>
</Sidebar>
{children}
</SidebarPage>
);
Add a Score tab on the Entity page
This shows a score view for the current entity.
Edit packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntityScoreCardContent } from '@oriflame/backstage-plugin-score-card';
export const serviceEntityPage = (
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
{/* your overview content */}
</EntityLayout.Route>
<EntityLayout.Route path="/score" title="Score">
<Grid container spacing={3} alignItems="stretch">
<Grid item xs={12}>
<EntityScoreCardContent />
</Grid>
</Grid>
</EntityLayout.Route>
</EntityLayout>
);
Optional table view inside an entity
If you want a table of scores for child entities under a parent entity like a system
import React from 'react';
import Grid from '@material-ui/core/Grid';
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntityScoreCardTable } from '@oriflame/backstage-plugin-score-card';
export const systemEntityPage = (
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
{/* your overview content */}
</EntityLayout.Route>
<EntityLayout.Route path="/score" title="Score">
<Grid container spacing={3} alignItems="stretch">
<Grid item xs={12}>
<EntityScoreCardTable />
</Grid>
</Grid>
</EntityLayout.Route>
</EntityLayout>
);
Configure where the plugin reads JSON data
You can set a single source for all entities or set it per entity with annotations.
App level config
Edit app-config.yaml
scorecards:
jsonDataUrl: https://raw.githubusercontent.com/Oriflame/backstage-plugins/main/plugins/score-card/sample-data/
backend:
csp:
default-src: ["'self'", 'raw.githubusercontent.com']
Your data server must return the Access-Control-Allow-Origin header that allows your Backstage web origin.
Per entity config with annotations
Add this to your entity yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
github.com/project-slug: my-org/my-repo
scorecard/jsonDataUrl: https://github.com/oriflame/backstage-plugins/blob/master/results.json
spec:
type: service
owner: my-team
lifecycle: production
If you point to a private GitHub repo then set up GitHub auth in your Backstage app. The user token will be used to fetch the file.
Data files layout
The client loads JSON files from the url you set.
Per entity files follow this pattern
{jsonDataUrl}/{namespace}/{kind}/{name}.json
Example path
https://example.com/score-data/default/component/my-service.json
You can keep a file with all entities if you need it
{jsonDataUrl}/all.json
Optional config flags
Edit app-config.yaml to tune behavior
scorecards:
# set true to load all entities first then filter them in memory
fetchAllEntities: true
# customize a link in the detail view using fields from the score entry
wikiLinkTemplate: "https://company/wiki/{id}"
Changelog
This changelog is produced from commits made to the System scoring 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.
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.