UI Development in Backstage

VerifiedSafe

Learn how to build UI using the new Backstage UI design system (bui) versus legacy components like @backstage/core-components and MUI v4.

Sby Skills Guide Bot
DevelopmentIntermediate
7/22/2026
Claude CodeCursorCodex
#backstage#bui-design-system#material-ui#frontend#storybook

Recommended for

Automated summary

Guides UI work in a Backstage repository by explaining when to reach for the new bui design system (@backstage/ui) versus the legacy core-components and Material UI v4 layers.

Strengths

  • Clarifies the coexistence of three UI layers (bui, core-components, MUI v4) with an explicit priority rule
  • Documents the setup already in place (backstage:^ dependency, one-time global CSS import, no BUIProvider)
  • Points to reliable sources (Backstage Storybook, the shared InfoCard wrapper, the tables skill) instead of guessing at props

Limitations

  • Heavily tied to the described Giantswarm/Backstage repository, so it is barely reusable elsewhere
  • The provided file is truncated: the section on reading Storybook source is incomplete
  • Does not enumerate detailed bui component props, deferring to external verification
When to use it

Use it whenever creating or changing a page, card, layout, button, or any other frontend component in this Backstage repository.

When not to use it

Avoid it for frontend projects that use neither Backstage nor this bui design system, or for in-depth table work that belongs to the tables skill.

Security analysis

Safe
Quality score90/100

The skill is documentation for frontend UI conventions. Its curl examples only fetch public Backstage Storybook/GitHub source read-only; there are no destructive commands, secret exfiltration, obfuscated payloads, or safety-disabling instructions.

No concerns found

How this analysis is made

Examples

New bui card
Add a cluster status card to the gs plugin using the shared InfoCard wrapper built on @backstage/ui, with a header action button.
Migrate a page to bui
This page currently uses only @backstage/core-components and MUI v4 — which parts can I move to @backstage/ui and which must stay legacy?
Check bui component API
Does bui have a Menu component and what props does MenuItem take? Help me confirm against the Backstage Storybook source.

name: ui description: How to build UI in this repo — the bui (@backstage/ui) design system vs legacy @backstage/core-components + MUI v4, which to reach for, and how to read Backstage Storybook component/story source. Use when creating or changing pages, cards, layouts, buttons, or any frontend component.

The three UI layers in this repo

| Layer | Import from | Status | | --- | --- | --- | | bui — the new Backstage design system | @backstage/ui (aka "Backstage UI", "BUI") | Preferred for new work. The direction we're migrating toward. | | core-components — classic Backstage components | @backstage/core-components | Legacy but still required where bui has no equivalent (e.g. feature-rich Table, Page/Header/Content scaffolding, Link with route refs). | | Material UI v4 | @material-ui/core | Legacy primitives + makeStyles. Used for styling and gaps bui doesn't cover. MUI v4 docs. |

Rule of thumb: reach for bui first. Fall back to core-components / MUI v4 only when bui lacks the piece you need. Mixing all three in one file is normal and expected during the migration — see ClusterAboutCard.tsx, which imports Grid from bui, Link from core-components, and Box/Tooltip from MUI v4 together.

@backstage/ui is currently 0.16.0 — a young, fast-moving package. APIs change between releases and it is not a full replacement for core-components yet. When unsure whether a bui component exists or what props it takes, check the Storybook source (see below) rather than guessing.

bui setup (already done)

  • The plugin's package.json must declare "@backstage/ui": "backstage:^" (already present in gs, ui-react, ai-chat, and app).
  • The global stylesheet is imported once in packages/app/src/index.tsx: import '@backstage/ui/css/styles.css';. Don't re-import it per component.
  • We do not wrap the app in BUIProvider — bui components render against the existing app theme + the global CSS. (Storybook recipes use BUIProvider because they render in isolation; the real app doesn't need it.)

bui components we actually use

Common primitives already in the codebase (import from @backstage/ui):

  • Layout: Flex, Grid, Box, Container
  • Surfaces: Card, CardHeader, CardBody, CardFooter
  • Typography: Text (e.g. <Text as="h3" variant="title-x-small" weight="bold">)
  • Controls: Button, ButtonIcon, Switch, Link
  • Overlay/menu: Tooltip, TooltipTrigger, MenuTrigger, Menu, MenuItem
  • Data display: Table + Cell / CellText / ColumnConfig, List, ListRow, Avatar
  • Page chrome: PluginHeader, Header (the two-tier header pattern — plugin-level PluginHeader above an entity-level Header). NFS page headers and SubPageBlueprint tabs are rendered by the custom GSPageLayout swappable component, not directly — see "Page headers and tabs" in docs/ui.md before building a tabbed page.

Cards: use the shared InfoCard wrapper

@giantswarm/backstage-plugin-ui-react exports an InfoCard built on bui's Card/CardHeader/CardBody/CardFooter with our standard title styling and header/footer action slots. Prefer it over hand-rolling a bui Card or the core-components InfoCard for new cards. Source: plugins/ui-react/src/components/InfoCard/InfoCard.tsx.

Tables: see the tables skill

The bui Table (data-driven columnConfig + data, cells must return Cell/CellText) and the feature-rich core-components Table are both documented in depth in the tables skill, including the choice matrix and gotchas (loading skeleton needs data={undefined}). Read that skill for anything table-related; don't duplicate it here.

Reading Backstage Storybook source

The Backstage Storybook renders components from the upstream backstage/backstage monorepo — stories are .stories.tsx files colocated with their components. There is no separate storybook repo, and we do not run a local storybook. To learn a pattern (how a page/card is composed, what props a bui component takes), read the story + component source directly.

The reliable technique: index.json → importPath → GitHub raw

Every Storybook deployment publishes a machine-readable index at https://backstage.io/storybook/index.json. Each entry carries the exact source paths:

{
  "id": "recipes-pluginheader-and-header--with-tabs",
  "title": "Recipes/PluginHeader and Header",
  "importPath": "./packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx",
  "componentPath": "./packages/ui/src/components/PluginHeader/PluginHeader.tsx"
}

Then fetch the raw source from GitHub (strip the leading ./):

BASE=https://raw.githubusercontent.com/backstage/backstage/master
curl -sfL "$BASE/packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx"
curl -sfL "$BASE/packages/ui/src/components/PluginHeader/PluginHeader.tsx"

To find the story ID for a Storybook URL: the ?path=/story/<id> query param is the entry id. Story IDs can drift between releases (the "Recipes/..." example also now exists as "Backstage UI/PluginHeader") — search index.json by title or a keyword rather than trusting an old URL. Quick lookup:

curl -sfL https://backstage.io/storybook/index.json \
  | jq '.entries | to_entries[] | select(.value.title|test("PluginHeader";"i")) | .value | {id,importPath,componentPath}'

Live inspection with Chrome DevTools

Use the chrome-devtools MCP when you want to inspect the rendered result (DOM, computed styles, a11y tree) or grab index.json without CORS friction:

  • new_page / navigate_page to https://backstage.io/storybook/
  • evaluate_script running fetch('https://backstage.io/storybook/index.json') (same-origin, so no CORS block) to pull the index or any raw story text
  • take_snapshot for the a11y tree of a rendered story

Note: the chrome-devtools MCP has its own filesystem roots — it can't write into the session scratchpad. Fetch text via evaluate_script and return it inline, or just curl the GitHub raw URL from Bash instead.

Related skills

  • tables — bui Table vs core-components Table, columns, filtering, faceted sidebars.
  • components — component directory structure, named exports, barrel files.
  • upstream-search — searching a local clone of backstage/backstage (needs BACKSTAGE_UPSTREAM_DIR set; the Storybook technique above needs no clone).

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/ui-development-in-backstage-mrwak8ze' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/ui-development-in-backstage-mrwak8ze/download' --output '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md.part' && mv '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md.part' '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.

Claude Code
test -f '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && test -s '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/ui' && cp -R '.skill-downloads/ui-development-in-backstage-mrwak8ze' '.claude/skills/ui'

Cursor
test -f '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && test -s '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/ui' && cp -R '.skill-downloads/ui-development-in-backstage-mrwak8ze' '.cursor/skills/ui'

Codex
test -f '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && test -s '.skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/ui' && cp -R '.skill-downloads/ui-development-in-backstage-mrwak8ze' '.agents/skills/ui'

OpenSkills

OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.

Official OpenSkills installation
openskills install './.skill-downloads/ui-development-in-backstage-mrwak8ze'

openskills read 'ui-development-in-backstage-mrwak8ze'

Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.

For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.

openskills sync

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/ui-development-in-backstage-mrwak8ze/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills