About using-backstage-catalog
using-backstage-catalog is a skill for implementing Backstage catalog operations in frontend and backend plugins. It provides patterns for fetching and querying entities and managing catalog locations, with guidance on credentials, hooks, and common pitfalls.
Key features
- 01Fetch entities by reference
- 02Query entities with filters
- 03Register, refresh, and unregister locations
- 04Frontend and backend patterns
- 05Guidance on credentials and async fetching
Use cases
- 01Look up a catalog entity in a plugin
- 02List entities matching catalog filters
- 03Manage catalog locations programmatically
- 04Add catalog operations to a scaffolded plugin
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ vinzscam/ backstage-skills --skill using-backstage-catalogAfter installing, type/using-backstage-catalogin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/fetch-by-ref.mdquery-entities.mdregister-entity.mdDetails
From the project READMEBackstage Catalog Patterns
When to use this skill
- Plugin needs to fetch a specific entity by its ref (e.g. a Group, Component, or User)
- Plugin needs to query entities with filters (e.g. all Components owned by a team, all Groups of a given type)
- Plugin needs to register a new catalog location, refresh an entity, or unregister one programmatically
- This applies to both frontend and backend code; the entry points differ but the operations are the same
Choose the right pattern
Frontend (in a frontend plugin component)
| Situation | Pattern | Reference |
|---|---|---|
| Fetch one entity by ref | useApi(catalogApiRef).getEntityByRef(ref) | references/fetch-by-ref.md (Frontend section) |
| Query entities with filters | useApi(catalogApiRef).getEntities({ filter }) | references/query-entities.md (Frontend section) |
| Register / refresh / unregister a location | useApi(catalogApiRef).addLocation / refreshEntity / removeLocationById | references/register-entity.md (Frontend section) |
Backend (in a backend plugin or module)
| Situation | Pattern | Reference |
|---|---|---|
| Fetch one entity by ref | catalog.getEntityByRef(ref, { credentials }) via catalogServiceRef | references/fetch-by-ref.md (Backend section) |
| Query entities with filters | catalog.getEntities({ filter }, { credentials }) via catalogServiceRef | references/query-entities.md (Backend section) |
| Register / refresh / unregister a location | catalog.addLocation / refreshEntity / removeLocationById via catalogServiceRef | references/register-entity.md (Backend section) |
Two invocation modes
- Standalone (mid-development): user is editing an existing plugin. Pick the right reference based on the situation table above and apply.
- Post-scaffold (called by
creating-backstage-plugin): apply the pattern to a freshly scaffolded plugin. Each reference's "Post-scaffold usage" section names the file and insertion point — frontend-template scaffolds use the Frontend pattern, backend-template scaffolds use the Backend pattern.
Common gotchas
- In frontend code,
catalogApiRefcomes from@backstage/plugin-catalog-react, NOT@backstage/catalog-client. The latter is for backend. useApiitself comes from@backstage/frontend-plugin-apiin NFS plugins;catalogApiRefis plugin-specific and stays in@backstage/plugin-catalog-react.- In backend code, depend on
catalogServiceReffrom@backstage/plugin-catalog-node— it wraps the catalog client with auth/discovery wiring already done and takesBackstageCredentialsdirectly. Methods take{ credentials }(aBackstageCredentialsobject), not{ token }(a string). For incoming HTTP requests, get credentials viahttpAuth.credentials(req). For service-to-service work (scheduled tasks, init-time fetches), useauth.getOwnServiceCredentials(). Don't manuallynew CatalogClient(...)— that's the underlying API but the service ref is the canonical surface. getEntityByRefreturnsEntity | undefined. Always handle the undefined case (entity may have been deleted or the ref may be malformed).getEntitiesreturns{ items: Entity[] }— destructure or access.items.- Filters on
getEntitiesare AND-combined within an object, OR-combined across an array of objects. - Frontend: don't fetch in a render — wrap in
useAsync(auto-fetch on mount/dep change) oruseAsyncFn(button-triggered fetch) fromreact-use. Don't manually wireuseStatefor{ loading, error, data }— the hook handles race conditions and unmount cleanup correctly. - Backend: don't fetch on every HTTP request without caching — for hot paths, use
coreServices.cacheto memoize results that don't need to be live.
UI conventions
Use @backstage/ui for rendering when possible (Skeleton, Alert, Text, Flex, Button, …). See using-backstage-ui skill for the full component catalog and styling guidance.
Comments
Markdown supported