TeamAPI latest
On this page
  1. Install
  2. Use
  3. Decisions worth knowing about
  4. The TeamAPI toolchain
  5. License

@jgalego/teamapi-backstage

npm CI Node License: MIT

A Backstage catalog entity provider that reads a live Team API as Code server, so the catalog never drifts from the org graph.

teamapi generate backstage writes catalog-info.yaml files, which suits an org that wants the catalog in git. It does not suit an org that already has Backstage: a generated file is a snapshot, correct until somebody changes a team document and wrong until somebody remembers to regenerate. That gap is where a catalog stops being trusted.

Install#

npm install @jgalego/teamapi-backstage

Use#

import { TeamApiEntityProvider } from "@jgalego/teamapi-backstage";

const provider = new TeamApiEntityProvider({
  baseUrl: "http://teamapi:3000",
  token: process.env.TEAMAPI_API_TOKEN, // only if the server was started with one
  refreshIntervalMs: 5 * 60 * 1000,
});

builder.addEntityProvider(provider);

It polls GET /backstage/catalog — the same generator teamapi generate backstage uses, served rather than written — so there is no second mapping between the two models to keep in sync.

Decisions worth knowing about#

No @backstage/* dependency. EntityProvider is a structural interface, and depending on @backstage/plugin-catalog-node to get it would pull the framework and its peer set into a workspace of YAML parsers, and pin this to one Backstage version — the thing most likely to be wrong for any given installation. The three shapes it needs are twenty lines, written out here, so this is a plain TypeScript module any Backstage version accepts.

A full mutation, under one stable location. That's what lets a team removed from the org graph leave the catalog. An incremental mutation would leave it there forever, which is the exact failure the generated-file approach already had.

A failed refresh leaves the catalog alone. A Team API server being briefly unreachable is not a reason to empty somebody's service catalog — which is precisely what a full mutation of zero entities would do. The previously ingested entities stay; the error goes to onError if you gave one, and is otherwise rethrown so the host's logger sees it. It is never logged from inside the library, and never swallowed — a catalog frozen by silent failures looks exactly like one that is up to date.

Entities are checked before they are applied. One with no kind or name crashes the catalog processor several layers away from the server that produced it, so the provider rejects the whole response instead.

The TeamAPI toolchain#

One org graph, seven doors into it — install only the ones you need:

Package What it does
@jgalego/teamapi The CLI — validate, diagram, check, import, reconcile, serve and chat with your org
@jgalego/teamapi-core The engine: $ref resolution, the org graph, scoring, checks, diagrams, generators
@jgalego/teamapi-schema Zod schemas and TypeScript types for the extended spec
@jgalego/teamapi-rest-api REST API, live dashboard, Swagger UI, Prometheus metrics
@jgalego/teamapi-mcp-server The org graph as MCP tools for LLM assistants
@jgalego/teamapi-chat Chat as a team or member — Anthropic or any OpenAI-compatible endpoint
@jgalego/teamapi-backstage (this package) Live Backstage catalog entity provider

Docs, examples and the extended spec: teamapi.dev · github.com/JGalego/TeamAPI

License#

MIT