|
| 1 | +--- |
| 2 | +name: rhdh-coding |
| 3 | +description: >- |
| 4 | + Backstage and RHDH plugin development patterns. Use when writing, modifying, |
| 5 | + or reviewing code in a Backstage or RHDH plugin — frontend components, backend |
| 6 | + services, API clients, styling, testing, entity pages, scaffolder actions, |
| 7 | + catalog processors, NFS Blueprints, dynamic plugin configuration. Also use |
| 8 | + when asked to "add a feature to a plugin", "implement a Backstage component", |
| 9 | + "create an API client", "write plugin tests", "add a backend route", "create |
| 10 | + a scaffolder action", "what plugin type should I use", or any coding task in |
| 11 | + a Backstage or RHDH codebase. |
| 12 | +--- |
| 13 | + |
| 14 | +# RHDH Coding |
| 15 | + |
| 16 | +Patterns for Backstage and RHDH plugin development that agents need but can't |
| 17 | +reliably get from training data or codebase discovery alone. This covers what |
| 18 | +you'd learn after six months of getting burned by non-obvious conventions. |
| 19 | + |
| 20 | +## Before You Write Code |
| 21 | + |
| 22 | +### 1. Check for existing specs |
| 23 | + |
| 24 | +Look for a spec, PRD, or OpenSpec design for this work — in `docs/plans/**/`, |
| 25 | +`specifications/`, `openspec/changes/*/`, or linked from the issue. If found, |
| 26 | +use the component list and acceptance criteria as your implementation blueprint. |
| 27 | +Read `references/frontend-specs.md` for what good frontend specs include. |
| 28 | + |
| 29 | +### 2. Discover the plugin context |
| 30 | + |
| 31 | +Run the detection script to understand what you're working with: |
| 32 | + |
| 33 | +```bash |
| 34 | +python scripts/detect-rhdh-context.py --path <plugin-dir> |
| 35 | +``` |
| 36 | + |
| 37 | +This reports: Backstage role, frontend system (legacy/NFS/dual), existing |
| 38 | +extensions, MUI version, dynamic plugin status, plugin ID, scalprum name. |
| 39 | + |
| 40 | +### 3. Read workspace instructions |
| 41 | + |
| 42 | +```bash |
| 43 | +test -f AGENTS.md && cat AGENTS.md |
| 44 | +test -f CLAUDE.md && cat CLAUDE.md |
| 45 | +``` |
| 46 | + |
| 47 | +These contain repo-specific rules that override general patterns. |
| 48 | + |
| 49 | +### 4. Check version compatibility |
| 50 | + |
| 51 | +Consult `../rhdh/references/versions.md` for the RHDH → Backstage version |
| 52 | +matrix. Your `@backstage/*` dependency versions must match the target RHDH |
| 53 | +version. Mismatched versions cause runtime errors — most commonly "Cannot |
| 54 | +read properties of undefined." |
| 55 | + |
| 56 | +## Styling: BUI First |
| 57 | + |
| 58 | +**For new plugins,** use Backstage UI (`@backstage/ui`) with CSS Modules and |
| 59 | +BUI CSS variables. **In existing plugins,** match whatever the workspace already |
| 60 | +uses — if it's MUI v4, stay consistent rather than mixing libraries. Only |
| 61 | +introduce BUI in a workspace that has already adopted it or is actively migrating. |
| 62 | + |
| 63 | +**Priority for new plugins:** |
| 64 | +1. **BUI** (`@backstage/ui`) — default for new plugins and new workspaces |
| 65 | +2. **MUI v5** (`@mui/material`) — when BUI lacks the component you need |
| 66 | +3. **MUI v4** (`@material-ui/core`) — legacy maintenance only |
| 67 | + |
| 68 | +When using MUI v5 alongside BUI, add the class name generator to prevent |
| 69 | +collisions in dynamic plugin bundles: |
| 70 | + |
| 71 | +```typescript |
| 72 | +// src/index.ts |
| 73 | +import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; |
| 74 | +ClassNameGenerator.configure(name => name.startsWith('v5-') ? name : `v5-${name}`); |
| 75 | +``` |
| 76 | + |
| 77 | +**Icons:** Use `@remixicon/react` (not `@material-ui/icons`). |
| 78 | + |
| 79 | +Read `references/bui.md` for the component mapping table and CSS variable reference. |
| 80 | + |
| 81 | +## Frontend System: NFS for New Plugins |
| 82 | + |
| 83 | +New plugins targeting RHDH 1.5+ should use the **new frontend system (NFS)** |
| 84 | +with Blueprints (`createFrontendPlugin`, `PageBlueprint`, `EntityCardBlueprint`, |
| 85 | +etc.). |
| 86 | + |
| 87 | +Legacy system (`createPlugin` + `createRoutableExtension`) is for existing |
| 88 | +plugins not yet migrated. For migration, use the `nfs-migration` sibling skill. |
| 89 | + |
| 90 | +Read `references/nfs.md` for Blueprint patterns, alpha export structure, and |
| 91 | +compatWrapper decisions. |
| 92 | + |
| 93 | +## Plugin Types |
| 94 | + |
| 95 | +Not sure whether to build a page, a card, an entity tab, or a backend module? |
| 96 | +Read `references/plugin-types.md` for the decision guide. |
| 97 | + |
| 98 | +## Backend: New System Only |
| 99 | + |
| 100 | +All backend code MUST use: |
| 101 | +- `createBackendPlugin` — new standalone backend capabilities |
| 102 | +- `createBackendModule` — extensions to existing plugins (catalog, scaffolder, auth) |
| 103 | + |
| 104 | +From `@backstage/backend-plugin-api`. Never the legacy backend system. |
| 105 | + |
| 106 | +Core services: `httpRouter`, `logger`, `rootConfig`, `httpAuth`, `database`, |
| 107 | +`scheduler`, `permissions`, `discovery`. |
| 108 | + |
| 109 | +**Default export is required** from the entry point (`src/index.ts`). Missing |
| 110 | +default export is the #1 cause of "plugin not loading" in RHDH. |
| 111 | + |
| 112 | +## RHDH Dynamic Plugins |
| 113 | + |
| 114 | +Key gotchas (read `references/rhdh.md` for full details): |
| 115 | + |
| 116 | +- **Default export required** from `src/index.ts` — missing this is the #1 cause of "plugin not loading" |
| 117 | +- **Scalprum name** must match the key in `dynamic-plugins.yaml` wiring (derived from package name) |
| 118 | +- **MUI v5 class name generator** required when using `@mui/material` in dynamic bundles |
| 119 | +- **Auth:** use `fetchApi` — it includes auth headers automatically. Don't implement custom auth. |
| 120 | +- **RHDH-only Blueprints:** `AppDrawerContentBlueprint`, `GlobalHeaderMenuItemBlueprint` — not upstream |
| 121 | + |
| 122 | +`references/rhdh.md` covers all RHDH-specific patterns including backend modules, |
| 123 | +extension points, theming, i18n, and the common package pattern. |
| 124 | + |
| 125 | +## Analytics |
| 126 | + |
| 127 | +BUI components (`Link`, `ButtonLink`, `Tab`, `MenuItem`, `Tag`, `Table` rows) |
| 128 | +have built-in click analytics via the Backstage Analytics API. Don't add manual |
| 129 | +`captureEvent('click', ...)` for these — it produces duplicates. Use `noTrack` |
| 130 | +prop to suppress the built-in event only when replacing it with a domain-specific |
| 131 | +verb (e.g., `deploy`, `approve`). For detailed instrumentation guidance, install |
| 132 | +the official `plugin-analytics-instrumentation` skill from backstage.io. |
| 133 | + |
| 134 | +## Testing |
| 135 | + |
| 136 | +Backstage has its own test infrastructure that differs from standard React testing. |
| 137 | +Read `references/testing.md` for: TestApiProvider setup, renderInTestApp, |
| 138 | +entity context mocking, async component testing, accessibility testing, and |
| 139 | +common gotchas. |
| 140 | + |
| 141 | +## Reference Index |
| 142 | + |
| 143 | +| Reference | Load when... | |
| 144 | +|-----------|-------------| |
| 145 | +| `references/frontend-specs.md` | Writing specs, PRDs, or OpenSpec proposals for frontend features | |
| 146 | +| `references/bui.md` | Using BUI components — mapping table, CSS variables, icons | |
| 147 | +| `references/plugin-types.md` | Deciding what type of plugin or extension to build | |
| 148 | +| `references/nfs.md` | Writing NFS code — Blueprints, package exports, compatWrapper | |
| 149 | +| `references/dev-app.md` | Plugin dev mode, full Backstage app setup, sidebar, app-config | |
| 150 | +| `references/testing.md` | Writing tests — TestApiProvider, entity mocking, a11y | |
| 151 | +| `references/rhdh.md` | RHDH-specific patterns — dynamic plugins, backend modules, i18n | |
| 152 | + |
| 153 | +## Sibling Skills (rhdh-skill) |
| 154 | + |
| 155 | +| Skill | Use when... | |
| 156 | +|-------|------------| |
| 157 | +| `create-plugin` | Scaffolding a new plugin from scratch | |
| 158 | +| `nfs-migration` | Migrating an existing plugin from legacy to NFS | |
| 159 | +| `overlay` | Managing overlay packaging for the Extensions Catalog | |
| 160 | +| `backstage-upgrade` | Upgrading Backstage dependency versions | |
| 161 | +| `rhdh-local` | Running and testing plugins locally | |
| 162 | +| `rhdh` | RHDH version matrix, repo navigation, ecosystem context | |
| 163 | + |
| 164 | +## Official Backstage Skills (backstage.io) |
| 165 | + |
| 166 | +Install via `npx skills add https://backstage.io`. These are complementary — |
| 167 | +they cover migration and instrumentation workflows that this skill does not. |
| 168 | + |
| 169 | +| Skill | Use when... | |
| 170 | +|-------|------------| |
| 171 | +| `mui-to-bui-migration` | Migrating a plugin from MUI to BUI (component-by-component guide) | |
| 172 | +| `plugin-new-frontend-system-support` | Adding NFS support while keeping legacy working (dual entry point) | |
| 173 | +| `plugin-full-frontend-system-migration` | Fully migrating a plugin to NFS, dropping legacy | |
| 174 | +| `app-frontend-system-migration` | Migrating an entire Backstage app to the new frontend system | |
| 175 | +| `plugin-analytics-instrumentation` | Adding analytics events via Backstage Analytics API | |
| 176 | +| `onboard-to-openapi-server` | Migrating backend router to typed OpenAPI tooling | |
0 commit comments