Each covered repository has a catalog-info.yaml file at its root. The file uses the Backstage descriptor format. The DevHub taxonomy page describes the entity kinds. DevHub reads the file. Tools such as the engineering graph (#proj-engineering-graph) can also read it. A person or an agent can then find the owner of a repository, how it runs, and where its documents are.
- The file is in the repository. It changes in the same pull request as the code it describes.
CODEOWNERSis the source of truth for review ownership.spec.ownernames the same team. See code ownership.- One file can hold more than one entity. Put
---between the entities. If a repository deploys more than one unit, declare oneComponentfor each unit. - Check the file with the DevHub entity validator before you merge it.
Choose a field in this order
Before you add a field, look for an existing field for the value. Stop at the first step that has one.
Backstage
backstage.io/ prefix.DevHub
spec.kraken.New
Do not use a key that Backstage, DevHub, or this page does not define. Well-known annotations, such as github.com/project-slug, are allowed because they belong to the Backstage step. A new key goes in spec.kraken by default. DevHub asks teams to put custom data there, and its Kraken Spec card shows that object. An annotation is a string, so it cannot hold structured data.
Take hosting as an example. Backstage has no field for the place where a component runs. DevHub has no key for it. The spec.kraken keys in DevHub describe Kraken platform resources, for example nomad_job. So hosting is a new key.
Metadata fields
Use these fields in every Component. The table notes each exception. Backstage defines every field except four. DevHub defines spec.scmdb_ids. The PagerDuty Backstage plugin defines pagerduty.com/service-id. This page defines spec.kraken.hosting and spec.kraken.release.
| Field | Value | Example |
|---|---|---|
apiVersion |
Always backstage.io/v1alpha1. |
backstage.io/v1alpha1 |
kind |
Always Component. |
Component |
metadata.name |
The repository name. | example-web-app |
metadata.description |
One sentence that tells what the component does. | Customer web app for the example trading tools. |
metadata.annotations.github.com/project-slug |
<org>/<repository>. |
NT-NinjaTrader/example-web-app |
metadata.annotations.pagerduty.com/service-id |
The ID of the PagerDuty service that pages for the component. Required when spec.type is service and spec.lifecycle is production. |
P123ABC |
metadata.links |
A link to the repository with icon: github. A link to the repository documents with icon: docs. The environment and on-call links. See Links. |
{ url: https://github.com/NT-NinjaTrader/example-web-app, title: GitHub Repository, icon: github, type: repository } |
spec.type |
service, website, or library. Use documentation when the repository only builds documents. Use ui for a mobile app, because Backstage has no value for it and the DevHub taxonomy does. |
website |
spec.lifecycle |
experimental, production, or deprecated. |
production |
spec.owner |
The first owner of the CODEOWNERS rule that matches catalog-info.yaml, without the @<org>/ prefix. The Backstage community CODEOWNERS module sets the same value. |
nt-web |
spec.scmdb_ids |
A list of SC-<number> IDs from SCMDB. DevHub requires it when type is service and lifecycle is production. |
[SC-12345] |
spec.kraken.hosting |
The platform that serves the component. Required unless spec.type is library. See Hosting. |
cloudflare-pages |
spec.kraken.release |
The event that deploys a change to production. Required unless spec.type is library. See Release. |
manual-dispatch-gated |
Do not put the link to the repository documents in an annotation. Put it in metadata.links.
DevHub links spec.owner to a group only when a DevHub group has the same reference. A team in CODEOWNERS can have no DevHub group. The file is still valid. Workday teams get a DevHub group automatically. For any other team, use the DevHub template Add a new Group of people. The template adds the group in a namespace that equals its type, for example sub-team. Then write the full reference in spec.owner, for example group:sub-team/nt-web.
Links
metadata.links holds the places that a person needs during an incident or on the first day in a repository. Set type to a value from this table, so that a tool can find a link without the title.
type |
Target | icon |
Rule |
|---|---|---|---|
repository |
The repository. | github |
Required. |
documentation |
The repository documents. | docs |
Required. |
production |
The production URL. | externalLink |
Required when the component has a URL in production. |
staging |
The staging URL. | externalLink |
Optional. |
development |
The development URL. | externalLink |
Optional. |
runbook |
The runbook for the component. | docs |
Optional. |
slack |
The Slack channel for questions and escalation. | chat |
Optional. |
To find who gets paged, open the PagerDuty service. Its escalation policy names the rotation and the escalation steps. Do not add a field for the on-call team. spec.owner names the owning team, and the escalation policy names the rotation.
Do not put pagerduty.com/integration-key in the file. It is the Events API routing key. A person who can read the repository can use it to open an incident.
Custom fields
All custom fields are keys of spec.kraken. This page defines only the keys in this section.
Hosting
spec.kraken.hosting names the platform that serves the component. Use one value.
| Value | Meaning |
|---|---|
cloudflare-pages |
Cloudflare Pages. |
cloudflare-worker |
A Cloudflare Worker. |
cloud-run |
Cloud Run. |
gke-core-services |
Kubernetes on GKE, core-services. |
gke-front-end |
Kubernetes on GKE, front-end. |
fern |
Documents that Fern publishes. |
app-store |
A mobile app that an app store distributes. |
standalone-web-server |
A web server outside Cloudflare and GKE. |
Release
spec.kraken.release names the event that deploys a change to production. Use one value. A value that ends in -gated means that a person must approve the deploy first, for example in a GitHub environment.
| Value | Meaning |
|---|---|
push-main |
A merge to the default branch deploys. |
push-main-gated |
A merge to the default branch deploys after approval. |
release-branch |
A push to an r-* release branch deploys. |
release-branch-gated |
A push to an r-* release branch deploys after approval. |
manual-dispatch |
A person starts the deploy workflow. |
manual-dispatch-gated |
A person starts the deploy workflow. The deploy needs approval. |
release-console |
A person starts the deploy from the release console. |
tag |
A version tag or a tag bump starts the build. |
manual-sync |
A person copies the files to the server. |
To add a value to a key, open a pull request that changes this page. An Engineering Navigator must approve it.
Propose a new key
Use this process for a new spec.kraken key or a new annotation. An annotation needs a reason. Name the Backstage or DevHub plugin that reads it. No key is approved until this page defines it.
Check the order
Open an issue
NT-NinjaTrader/engineering-standards. Name the key and say where it goes. List the allowed values or the format, and give one example. Say why no Backstage or DevHub field fits. Name the repositories that need the key and the team that keeps its values correct.Get a review
Open a pull request
Approve and merge
Examples
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: example-web-app
description: Customer web app for the example trading tools.
annotations:
github.com/project-slug: NT-NinjaTrader/example-web-app
links:
- url: https://github.com/NT-NinjaTrader/example-web-app
title: GitHub Repository
icon: github
type: repository
- url: https://ninjatrader.atlassian.net/wiki/spaces/DSE/pages/<page-id>
title: Documentation
icon: docs
type: documentation
- url: https://example-web-app.ninjatrader.com
title: Production
icon: externalLink
type: production
spec:
type: website
lifecycle: production
owner: nt-web
kraken:
hosting: cloudflare-pages
release: manual-dispatch-gatedapiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: example-api
description: HTTP API for the example trading tools.
annotations:
github.com/project-slug: NT-NinjaTrader/example-api
pagerduty.com/service-id: P123ABC
links:
- url: https://github.com/NT-NinjaTrader/example-api
title: GitHub Repository
icon: github
type: repository
- url: https://ninjatrader.atlassian.net/wiki/spaces/DSE/pages/<page-id>
title: Documentation
icon: docs
type: documentation
- url: https://example-api.ninjatrader.com
title: Production
icon: externalLink
type: production
- url: https://example-api.staging.ninjatrader.dev
title: Staging
icon: externalLink
type: staging
- url: https://ninjatrader.atlassian.net/wiki/spaces/DSE/pages/<runbook-page-id>
title: Runbook
icon: docs
type: runbook
- url: https://payward.enterprise.slack.com/archives/<channel-id>
title: "#example-api"
icon: chat
type: slack
spec:
type: service
lifecycle: production
owner: nt-web-backend
scmdb_ids:
- SC-12345
kraken:
hosting: gke-core-services
release: push-main-gatedGenerate the file
In Claude Code, the engineering-standards plugin writes the file. Use plugin version 0.3.0 or later. The skill reads this page, so its field rules match the rules here. Codex, Cursor, and OpenCode have no equivalent plugin. For these agents, give the agent the prompt in its tab. The agent reads this page and asks you for the values that the repository does not show.
/plugin marketplace add NT-NinjaTrader/skills
/plugin install engineering-standards@skills
/engineering-standards:filling-catalog-infoWrite catalog-info.yaml at the repository root. Follow
https://engineering-standards.ninjatrader.dev/repository-metadata/index.md.
Ask me for the owner, the lifecycle, and each value that the repository does not show.
Do not guess a value. Do not commit the file.Write catalog-info.yaml at the repository root. Follow
https://engineering-standards.ninjatrader.dev/repository-metadata/index.md.
Ask me for the owner, the lifecycle, and each value that the repository does not show.
Do not guess a value. Do not commit the file.Write catalog-info.yaml at the repository root. Follow
https://engineering-standards.ninjatrader.dev/repository-metadata/index.md.
Ask me for the owner, the lifecycle, and each value that the repository does not show.
Do not guess a value. Do not commit the file.The skill does these things:
- It reads the repository and asks you for each value that the repository does not show. These values include
spec.owner,spec.lifecycle,spec.kraken.hosting,spec.kraken.release, andspec.scmdb_ids. - It checks the file against the Backstage schema.
- It writes
catalog-info.yamland does not commit it. Commit the file on a branch and open a pull request.
The plugin documentation lists the tools and secrets that the skill needs: engineering-standards plugin. An agent that reads this page needs a Cloudflare Access session. See Consult the standards. Check the result with the DevHub entity validator.
Keep the file correct
The owning team keeps the file correct. Change spec.kraken.hosting and spec.kraken.release in the same pull request that changes how the component deploys. When the owning team changes, change the CODEOWNERS rule and spec.owner in the same pull request. When a URL, a runbook, a Slack channel, or the PagerDuty service changes outside the repository, change its entry in the next pull request.
Open questions
References
- DevHub taxonomy: the entity kinds, the component types, and the fields of a
Component. - DevHub conventions: the well-known annotations,
spec.kraken,spec.scmdb_ids, and groups. - DevHub: register a service: how DevHub finds and reads the file.