Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
},
"metadata": {
"description": "Orchestrator skill for RHDH plugin development - onboard, update, and maintain plugins in the Extensions Catalog",
"version": "0.6.0"
"version": "0.7.0"
},
"plugins": [
{
"name": "rhdh",
"source": "./",
"description": "Skills for RHDH plugin lifecycle management",
"version": "0.6.0",
"version": "0.7.0",
"strict": true
}
]
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rhdh",
"description": "All-in-one toolkit for Red Hat Developer Hub (RHDH). Covers plugin development, overlay management, environment setup, version compatibility, CI/CD, and RHDH ecosystem navigation.",
"version": "0.6.0",
"version": "0.7.0",
"author": {
"name": "RHDH Store Manager"
},
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "rhdh-skill"
version = "0.6.0"
version = "0.7.0"
description = "Claude Code skill for RHDH plugin development"
readme = "README.md"
license = "Apache-2.0"
Expand Down
241 changes: 241 additions & 0 deletions skills/rhdh-coding/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
---
name: rhdh-coding
description: >-
Backstage and RHDH plugin development patterns. Use when writing, modifying,
or reviewing code in a Backstage or RHDH plugin — frontend components, backend
services, API clients, styling, testing, entity pages, scaffolder actions,
catalog processors, NFS Blueprints, dynamic plugin configuration. Also use
when asked to "add a feature to a plugin", "implement a Backstage component",
"create an API client", "write plugin tests", "add a backend route", "create
a scaffolder action", "what plugin type should I use", or any coding task in
a Backstage or RHDH codebase.
---

# RHDH Coding

Patterns for Backstage and RHDH plugin development that agents need but can't
reliably get from training data or codebase discovery alone. This covers what
you'd learn after six months of getting burned by non-obvious conventions.

## Before You Write Code

### 1. Check for existing specs

Look for a spec, PRD, or OpenSpec design for this work — in `docs/plans/**/`,
`specifications/`, `openspec/changes/*/`, or linked from the issue. If found,
use the component list and acceptance criteria as your implementation blueprint.
Read `references/frontend-specs.md` for what good frontend specs include.

### 2. Discover the plugin context

Run the detection script to understand what you're working with:

```bash
python scripts/detect-rhdh-context.py --path <plugin-dir>
```

This reports: Backstage role, frontend system (legacy/NFS/dual), existing
extensions, MUI version, dynamic plugin status, plugin ID, scalprum name.

### 3. Read workspace instructions

```bash
test -f AGENTS.md && cat AGENTS.md
test -f CLAUDE.md && cat CLAUDE.md
```

These contain repo-specific rules that override general patterns.

### 4. Check version compatibility

Consult `../rhdh/references/versions.md` for the RHDH → Backstage version
matrix. Your `@backstage/*` dependency versions must match the target RHDH
version. Mismatched versions cause runtime errors — most commonly "Cannot
read properties of undefined."

## Styling: BUI First

**For new plugins,** use Backstage UI (`@backstage/ui`) with CSS Modules and
BUI CSS variables. **In existing plugins,** match whatever the workspace already
uses — if it's MUI v4, stay consistent rather than mixing libraries. Only
introduce BUI in a workspace that has already adopted it or is actively migrating.

**Priority for new plugins:**
1. **BUI** (`@backstage/ui`) — default for new plugins and new workspaces
2. **MUI v5** (`@mui/material`) — when BUI lacks the component you need
3. **MUI v4** (`@material-ui/core`) — legacy maintenance only

When using MUI v5 alongside BUI, add the class name generator to prevent
collisions in dynamic plugin bundles:

```typescript
// src/index.ts
import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';
ClassNameGenerator.configure(name => name.startsWith('v5-') ? name : `v5-${name}`);
```

**Icons:** Use `@remixicon/react` (not `@material-ui/icons`).

Read `references/bui.md` for the component mapping table and CSS variable reference.

## Frontend System: NFS for New Plugins

New plugins targeting RHDH 1.5+ should use the **new frontend system (NFS)**
with Blueprints (`createFrontendPlugin`, `PageBlueprint`, `EntityCardBlueprint`,
etc.).

Legacy system (`createPlugin` + `createRoutableExtension`) is for existing
plugins not yet migrated. For migration, use the `nfs-migration` sibling skill.

Read `references/nfs.md` for Blueprint patterns, alpha export structure, and
compatWrapper decisions.

## Plugin Types

Not sure whether to build a page, a card, an entity tab, or a backend module?
Read `references/plugin-types.md` for the decision guide.

## Backend: New System Only

All backend code MUST use:
- `createBackendPlugin` — new standalone backend capabilities
- `createBackendModule` — extensions to existing plugins (catalog, scaffolder, auth)

From `@backstage/backend-plugin-api`. Never the legacy backend system.

Core services: `httpRouter`, `logger`, `rootConfig`, `httpAuth`, `database`,
`scheduler`, `permissions`, `discovery`.

**Default export is required** from the entry point (`src/index.ts`). Missing
default export is the #1 cause of "plugin not loading" in RHDH.

## RHDH Dynamic Plugins

Key gotchas (read `references/rhdh.md` for full details):

- **Default export required** from `src/index.ts` — missing this is the #1 cause of "plugin not loading"
- **Scalprum name** must match the key in `dynamic-plugins.yaml` wiring (derived from package name)
- **MUI v5 class name generator** required when using `@mui/material` in dynamic bundles
- **Auth:** use `fetchApi` — it includes auth headers automatically. Don't implement custom auth.
- **RHDH-only Blueprints:** `AppDrawerContentBlueprint`, `GlobalHeaderMenuItemBlueprint` — not upstream

`references/rhdh.md` covers all RHDH-specific patterns including backend modules,
extension points, theming, i18n, and the common package pattern.

## Analytics

BUI components (`Link`, `ButtonLink`, `Tab`, `MenuItem`, `Tag`, `Table` rows)
have built-in click analytics via the Backstage Analytics API. Don't add manual
`captureEvent('click', ...)` for these — it produces duplicates. Use `noTrack`
prop to suppress the built-in event only when replacing it with a domain-specific
verb (e.g., `deploy`, `approve`). For detailed instrumentation guidance, install
the official `plugin-analytics-instrumentation` skill from backstage.io.

## Testing

Backstage has its own test infrastructure that differs from standard React testing.
Read `references/testing.md` for: TestApiProvider setup, renderInTestApp,
entity context mocking, async component testing, accessibility testing, and
common gotchas.

## Before You Commit

Run these commands **in order** from the workspace root (e.g., `workspaces/boost/`).
Stop on first failure — fix it before continuing. This sequence catches every CI
gate locally.

```bash
yarn prettier:fix # format code
yarn tsc:full # full TypeScript type check
yarn build:all # build all packages in the workspace
yarn test --watchAll=false # run tests (disable watch mode)
yarn build:api-reports:only # generate/update API report files
```

### API reports

`build:api-reports:only` generates `report.api.md` files for packages with
public exports. These files **must be committed** — CI checks them. All public
exports need `/** @public */` JSDoc with a description (not just the bare tag).

### Changesets

Changesets are required for published package changes. Rules:
- Only cover plugins under `plugins/` — **never `packages/*`** (those are
private app/backend packages that are never published)
- Only include a plugin if it has changes in `src/` or other published paths
(root `index.ts`, `config.d.ts`, `package.json`)
- Changes only in `dev/`, `tests/`, `__fixtures__/`, or stories do NOT need
a changeset for that plugin
- Write the changeset file directly to `<workspace>/.changeset/<id>.md` —
don't run `yarn changeset` interactively

### Commits

All commits must be signed off (`git commit -s`) per DCO requirements.

## Reference Index

| Reference | Load when... |
|-----------|-------------|
| `references/frontend-specs.md` | Writing specs, PRDs, or OpenSpec proposals for frontend features |
| `references/bui.md` | Using BUI components — mapping table, CSS variables, icons |
| `references/plugin-types.md` | Deciding what type of plugin or extension to build |
| `references/nfs.md` | Writing NFS code — Blueprints, package exports, compatWrapper |
| `references/dev-app.md` | Plugin dev mode, full Backstage app setup, sidebar, app-config |
| `references/testing.md` | Writing tests — TestApiProvider, entity mocking, a11y |
| `references/rhdh.md` | RHDH-specific patterns — dynamic plugins, backend modules, i18n |

## Sibling Skills (rhdh-skill)

| Skill | Use when... |
|-------|------------|
| `create-plugin` | Scaffolding a new plugin from scratch |
| `nfs-migration` | Migrating an existing plugin from legacy to NFS |
| `overlay` | Managing overlay packaging for the Extensions Catalog |
| `backstage-upgrade` | Upgrading Backstage dependency versions |
| `rhdh-local` | Running and testing plugins locally |
| `rhdh` | RHDH version matrix, repo navigation, ecosystem context |

## Ecosystem Skills (skills.sh)

These open-source skills complement rhdh-coding with generic frontend quality
patterns. Install into `.fullsend/customized/skills/` or your local skills
directory.

**Essential:**

| Skill | Source | What it adds |
|-------|--------|-------------|
| `ui-ux-pro-max` | nextlevelbuilder/ui-ux-pro-max-skill | 99 UX rules — accessibility, touch targets, animation, forms, navigation |
| `frontend-design` | anthropics/skills | Design thinking, anti-AI-aesthetic, microcopy quality |
| `webapp-testing` | anthropics/skills | Playwright-based browser testing, server lifecycle |

**Recommended:**

| Skill | Source | What it adds |
|-------|--------|-------------|
| `design-taste-frontend` | leonxlnx/taste-skill | Anti-slop discipline, design inference |
| `emil-design-eng` | emilkowalski/skills | Animation decisions, CSS polish |

```bash
npx skills add https://github.com/nextlevelbuilder/ui-ux-pro-max-skill --skill ui-ux-pro-max
npx skills add https://github.com/anthropics/skills --skill frontend-design
npx skills add https://github.com/anthropics/skills --skill webapp-testing
npx skills add https://github.com/leonxlnx/taste-skill --skill taste-skill
npx skills add https://github.com/emilkowalski/skills --skill emil-design-eng
```

## Official Backstage Skills (backstage.io)

Install via `npx skills add https://backstage.io`. These cover migration and
instrumentation workflows that this skill does not.

| Skill | Use when... |
|-------|------------|
| `mui-to-bui-migration` | Migrating a plugin from MUI to BUI (component-by-component guide) |
| `plugin-new-frontend-system-support` | Adding NFS support while keeping legacy working (dual entry point) |
| `plugin-full-frontend-system-migration` | Fully migrating a plugin to NFS, dropping legacy |
| `app-frontend-system-migration` | Migrating an entire Backstage app to the new frontend system |
| `plugin-analytics-instrumentation` | Adding analytics events via Backstage Analytics API |
| `onboard-to-openapi-server` | Migrating backend router to typed OpenAPI tooling |
Loading