mcpField
U
using-backstage-ui

using-backstage-ui

github.com/vinzscamDesign & UI446 installsUpdated 9w ago
Repository

About using-backstage-ui

A skill for building and editing Backstage frontend components with Backstage UI (BUI). It covers component selection, styling conventions, data-fetching hooks, and applying BUI defaults to new plugin scaffolds.

Key features

  1. 01BUI component selection guidance
  2. 02CSS modules and design-token styling
  3. 03Remix Icon usage
  4. 04Async data-fetching hook patterns
  5. 05Frontend scaffold defaults

Use cases

  1. 01Building a Backstage plugin interface
  2. 02Choosing form or navigation components
  3. 03Styling components with BUI tokens
  4. 04Loading data in frontend components

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/vinzscam/backstage-skills --skill using-backstage-ui

After installing, type/using-backstage-uiin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
components.md
icons.md
styling.md

Details

From the project README

Backstage UI (BUI) Patterns

When to use this skill

  • Authoring or editing any frontend component in a Backstage plugin
  • Picking the right component for layout, typography, form input, dialog, menu, tab, table, etc.
  • Styling components (BUI uses CSS modules + design tokens, not makeStyles)
  • Adding icons (use @remixicon/react)

Setup

A new plugin scaffolded with yarn new includes @backstage/ui automatically. If installing manually:

yarn add @backstage/ui @remixicon/react

Then add the stylesheet to your app entry (packages/app/src/index.tsx or similar):

import '@backstage/ui/css/styles.css';

Choose the right component

NeedComponentReference
Page layout / wrappersBox, Container, Flex, FullPage, Gridreferences/components.md
TypographyTextreferences/components.md
Buttons / actionsButton, ButtonIcon, ButtonLinkreferences/components.md
FormsTextField, PasswordField, SearchField, Select, Combobox, Checkbox, RadioGroup, Switch, DatePicker, DateRangePickerreferences/components.md
FeedbackAlert, Skeleton, Tooltip, Tag, TagGroupreferences/components.md
OverlaysDialog, Menu, Popoverreferences/components.md
NavigationTabs, Header, PluginHeader, Linkreferences/components.md
DataTable (+ useTable hook), List (+ ListRow), Avatar, Cardreferences/components.md
Icons@remixicon/react (e.g. RiSearchLine, RiAddLine)references/icons.md
StylingCSS modules with BUI tokens (--bui-space-*, --bui-fg-*, --bui-bg-*)references/styling.md

Two invocation modes

  • Standalone (mid-development): user is editing an existing plugin component. Pick the relevant reference and apply.
  • Post-scaffold (called by creating-backstage-plugin for any frontend template): apply BUI defaults to the freshly scaffolded plugin's example component, ensuring imports come from @backstage/ui and styles use CSS modules with BUI tokens.

Common gotchas

  • BUI ≠ Material UI. Don't mix prop names: disabled → isDisabled; variant="contained" → variant="primary".
  • Flex uses justify="between" (NOT space-between); gap goes via inline style or BUI tokens.
  • Tooltip requires TooltipTrigger as a parent.
  • TextField's onChange receives a string directly, not an event object.
  • One known fallback where BUI doesn't have an equivalent: @material-ui/lab Timeline has no BUI replacement. Use MUI in that specific case.

Data fetching convention

Don't manually wire useState for loading/error/data. Use react-use hooks:

  • useAsync(fn, deps) — runs the async function on mount and whenever deps change. Use for "load data when the component renders or its props change."
  • useAsyncFn(fn) — returns [state, callback]. Use for "load data when the user does X" (button click, form submit, etc.).

Manual useState for { loading, error, value } is an anti-pattern in this codebase: it duplicates logic the hook handles correctly (race conditions, unmount-during-fetch, etc.). The catalog and identity references show useAsync; the same applies anywhere data is fetched.

import useAsyncFn from 'react-use/lib/useAsyncFn';
import { Button, Skeleton, Alert, Text } from '@backstage/ui';

export const FetchOnDemand = () => {
  const [{ loading, error, value }, fetch] = useAsyncFn(async (id: string) => {
    return await someApi.get(id);
  }, []);

  return (
    <>
      <Button onClick={() => fetch('foo')}>Fetch</Button>
      {loading && <Skeleton width={200} height={20} />}
      {error && <Alert status="danger" title={error.message} />}
      {value && <Text>{value.name}</Text>}
    </>
  );
};

Comments

Markdown supported