Skip to content

Backstage Plugin Installation & Configuration

Beta

The SkillMeat Backstage plugins (@skillmeat/backstage-plugin and @skillmeat/backstage-plugin-scaffolder-backend) are currently in early release (v0.1.0). APIs and configuration keys are stable for the documented scenarios below, but minor changes may occur before a 1.0 release. Pin plugin versions in production and review the changelog when upgrading.

Walkthrough available

See the Backstage Platform Engineer Walkthrough for a complete Backstage integration journey.

This guide walks platform engineers through installing both SkillMeat Backstage plugins into an existing Backstage app and verifying that the integration is working. By the end you will have:

  • The frontend plugin (@skillmeat/backstage-plugin) serving entity cards, drift status views, and optional telemetry dashboards on your entity pages.
  • The scaffolder backend plugin (@skillmeat/backstage-plugin-scaffolder-backend) registering three custom scaffolder actions so your templates can inject AI context packs and register deployments with SkillMeat.

Prerequisites

Before starting, confirm that the following are in place.

Backstage Version

The plugins target Backstage v1.27.x (RHDH 1.3+ is also supported). Run the following from your Backstage root to confirm the installed Backstage CLI version:

yarn backstage-cli --version

Check that the version satisfies ^0.30.0. The frontend plugin lists its Backstage peer dependencies explicitly:

Dependency Required Version
@backstage/core-plugin-api ^1.10.0
@backstage/core-components ^0.16.0
@backstage/plugin-catalog-react ^1.14.0
@backstage/catalog-model ^1.7.0

The scaffolder backend plugin requires:

Dependency Required Version
@backstage/backend-plugin-api ^1.0.0
@backstage/plugin-scaffolder-node ^0.6.0

If your Backstage version is older, upgrade it first using the standard Backstage upgrade guide.

Node.js Version

Both plugins require Node.js v18.x or later. Check your runtime:

node --version

SkillMeat API

Your SkillMeat API server must be reachable from the host running the Backstage backend process:

  • API URL known: you need the base URL of the SkillMeat API (e.g., https://sam.internal or http://localhost:8080 for local dev).
  • SkillMeat API v1.0.0+: verify with a health check:
curl -sf https://sam.internal/health | jq .

A 200 OK response with {"status": "ok"} confirms the API is reachable.

Admin Access to Backstage Repo

You need the ability to:

  • Modify packages/app/src/App.tsx (frontend route registration)
  • Modify packages/app/src/components/Root/Root.tsx (sidebar)
  • Modify packages/backend/src/index.ts (new backend system) or packages/backend/src/plugins/scaffolder.ts (legacy backend)
  • Add keys to app-config.yaml
  • Run yarn to install packages

SkillMeat API Token

The scaffolder backend plugin makes server-to-server requests to the SkillMeat API. You need a service account token generated in SkillMeat before configuring the plugin. See Authentication Setup for how to create API tokens.

Tip

For local development you may omit the token if your SkillMeat instance is running in zero-auth mode. For production always use a service account token.


Step 1: Install the Frontend Plugin

The frontend plugin provides entity page tabs, drift status cards, and optional telemetry dashboards.

1.1 — Add the Package

From the Backstage monorepo root, install into the packages/app workspace:

yarn --cwd packages/app add @skillmeat/backstage-plugin

Confirm the package appears in packages/app/package.json.

1.2 — Register Routes in App.tsx

Open packages/app/src/App.tsx and add the SkillMeat imports and routes. The demo app at demo/backstage-app/packages/app/src/App.tsx is the canonical reference:

// packages/app/src/App.tsx

import {
  PlatformHealthDashboardPage,
  GlobalROIDashboardPage,
} from '@skillmeat/backstage-plugin';

// ... existing imports ...

Inside the <FlatRoutes> block, add the two standalone dashboard routes:

const routes = (
  <FlatRoutes>
    {/* ... existing routes ... */}

    {/* SkillMeat: Platform Health dashboard (KPI header, catalog health, drift alerts) */}
    <Route path="/platform-health" element={<PlatformHealthDashboardPage />} />

    {/* SkillMeat: Global AI ROI dashboard (enterprise-wide workflow effectiveness) */}
    <Route path="/skillmeat-roi" element={<GlobalROIDashboardPage />} />
  </FlatRoutes>
);

The entity-page tabs (EntitySkillMeatContent, EntitySkillMeatIntelligenceContent) are registered per entity kind in your entity page configuration — covered in Catalog Integration.

Note

The plugin also exports skillmeatPlugin which self-registers its API factories when any of its components are imported. You do not need to add it manually to createApp({ plugins: [...] }) — Backstage's tree-shaking mechanism handles this automatically when you use the route components.

1.3 — Add Sidebar Entries

Open packages/app/src/components/Root/Root.tsx and add sidebar items for the two dashboard pages. Import a suitable Material UI icon:

// packages/app/src/components/Root/Root.tsx

import DashboardIcon from '@material-ui/icons/Dashboard';
import AssessmentIcon from '@material-ui/icons/Assessment';

// Inside the <SidebarGroup label="Menu" ...> block:
<SidebarItem
  icon={AssessmentIcon}
  to="platform-health"
  text="Platform Health"
/>
<SidebarItem
  icon={DashboardIcon}
  to="skillmeat-roi"
  text="AI ROI Dashboard"
/>

Place these items in the SidebarScrollWrapper or in the main menu group, depending on your sidebar structure. The exact position is at your discretion.


Step 2: Install the Scaffolder Backend Plugin

The scaffolder backend plugin registers three custom actions for use in Backstage scaffolder templates:

Action Purpose
skillmeat:bundle:validate Validates a bundle exists in SkillMeat before scaffold steps run
skillmeat:context:inject Fetches and injects a rendered Golden Context Pack into the workspace
skillmeat:deployment:register Links a newly created repository to a SkillMeat deployment record

Note

The scaffolder backend plugin also exports skillmeat:attest and skillmeat:bom:generate actions. These are available for use in templates but are not shown in the minimal install below.

2.1 — Add the Package

From the Backstage monorepo root, install into the packages/backend workspace:

yarn --cwd packages/backend add @skillmeat/backstage-plugin-scaffolder-backend

2.2 — Register with the Backend

New backend system (recommended) — edit packages/backend/src/index.ts and add skillmeatScaffolderModule after the scaffolder plugin registration:

// packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';
import { skillmeatScaffolderModule } from '@skillmeat/backstage-plugin-scaffolder-backend';

const backend = createBackend();

// ... other plugins ...
backend.add(import('@backstage/plugin-scaffolder-backend'));
backend.add(import('@backstage/plugin-scaffolder-backend-module-github'));

// SkillMeat scaffolder actions
backend.add(skillmeatScaffolderModule);

await backend.start();

The skillmeatScaffolderModule registers all SkillMeat actions with the scaffolder's scaffolderActionsExtensionPoint automatically.

Legacy backend system — if your Backstage app still uses the legacy backend, import the action factory functions directly in packages/backend/src/plugins/scaffolder.ts:

// packages/backend/src/plugins/scaffolder.ts (legacy backend only)

import {
  createSkillMeatValidateBundleAction,
  createSkillMeatInjectAction,
  createSkillMeatRegisterAction,
} from '@skillmeat/backstage-plugin-scaffolder-backend';

// Inside createRouter({ ..., actions }):
const actions = [
  ...builtinActions,
  createSkillMeatValidateBundleAction(),
  createSkillMeatInjectAction(),
  createSkillMeatRegisterAction(),
];

Tip

If you are unsure which backend system your app uses, check whether packages/backend/src/index.ts contains createBackend() from @backstage/backend-defaults (new system) or createRouter calls in separate plugins/ files (legacy system).


Step 3: Configure app-config.yaml

Both plugins read from the skillmeat key in app-config.yaml. Add the following block, substituting your real values:

# app-config.yaml

skillmeat:
  # Required: base URL of your SkillMeat API instance.
  # No trailing slash. Used by both the frontend and scaffolder backend plugins.
  baseUrl: https://sam.internal

  # Recommended for production: service account token for machine-to-machine auth.
  # Set via environment variable — never commit the raw token value.
  serviceAccountToken: ${SAM_SERVICE_ACCOUNT_TOKEN}

  # Legacy token config (backward compatible). If serviceAccountToken is set,
  # it takes precedence over this value.
  # token: ${SAM_API_TOKEN}

Optional: Telemetry Proxy Configuration

The frontend plugin's telemetry widgets (workflow effectiveness cards, agentic metrics, global ROI dashboard) route API calls through the Backstage proxy. If you plan to enable telemetry dashboards, add a proxy entry:

# app-config.yaml

proxy:
  '/telemetry':
    target: 'https://sam.internal'
    changeOrigin: true
    allowedMethods: ['GET']
    allowedHeaders: ['Content-Type', 'Authorization']
    # If your SAM backend enforces bearer auth, inject the token here:
    headers:
      authorization: 'Bearer ${TELEMETRY_API_TOKEN}'

The telemetry widgets construct requests to /telemetry/integrations/idp/telemetry/* relative to the Backstage backend.

Optional: Enable Telemetry Feature Flag

All telemetry widgets (the analytics dashboard, workflow effectiveness cards, and agentic metrics tabs) are gated behind a Backstage feature flag called backstage_analytics_widgets. Without this flag enabled the plugin loads normally but does not render any telemetry components — no empty placeholders are shown.

To enable telemetry widgets:

# app-config.yaml

featureFlags:
  backstage_analytics_widgets: true

Note

The three core entity cards (SkillMeatContextCard, SkillMeatBomCard, SkillMeatDriftCard) and EntitySkillMeatContent are not gated by this feature flag and are always available once the plugin is installed.

Authentication Priority for Scaffolder Actions

The scaffolder backend resolves auth credentials in the following order. Higher-priority sources override lower ones, and per-step template inputs override all global config:

  1. Per-step token input in the template YAML — highest priority
  2. skillmeat.serviceAccountToken — recommended for production (service-to-service)
  3. skillmeat.token — legacy fallback
  4. Unauthenticated — if all token config is omitted (only appropriate for zero-auth SkillMeat deployments)

Step 4: Configure Authentication

Generating a Service Account Token

The scaffolder backend requires a token with sufficient scope to call the SkillMeat scaffold, validate, and deployment registration endpoints. To generate a token:

  1. Open the SkillMeat web UI and navigate to Settings → Authentication.
  2. Create or select a service account.
  3. Generate an API token with at minimum artifacts:read, deployments:write, and integrations:idp scopes.

For detailed token management steps, see Authentication Setup.

Injecting the Token as an Environment Variable

Never commit token values directly to app-config.yaml. Inject them at runtime using environment variables and the ${VAR_NAME} substitution syntax that Backstage supports natively.

For local development, create app-config.local.yaml (this file is git-ignored in the default Backstage setup):

# app-config.local.yaml — not committed to source control

skillmeat:
  baseUrl: http://localhost:8080
  token: your-dev-token-here

For production and CI/CD, set the environment variable before starting Backstage:

export SAM_SERVICE_ACCOUNT_TOKEN="your-service-account-token"
yarn start

Or in your container/Kubernetes deployment, inject SAM_SERVICE_ACCOUNT_TOKEN as a secret environment variable and reference it with ${SAM_SERVICE_ACCOUNT_TOKEN} in app-config.yaml as shown above.

Warning

If you deploy Backstage as a Docker container, ensure the environment variable is available to the backend process, not just the build step. Backstage evaluates ${...} substitutions at server startup, not at build time.


Step 5: Start Backstage and Verify

5.1 — Start the Development Server

From your Backstage root:

yarn dev

This starts both the backend (port 7007) and the frontend (port 3000) simultaneously.

For production:

yarn build
yarn start

5.2 — Verify the Frontend Plugin Loaded

  1. Open your browser to http://localhost:3000 (or your Backstage URL).
  2. Check the sidebar for the Platform Health and AI ROI Dashboard items you added.
  3. Navigate to Platform Health (/platform-health). The page should render the platform health dashboard. If telemetry is enabled you will also see the KPI header row with aggregate metrics.
  4. Navigate to /skillmeat-roi to confirm the Global ROI dashboard renders.

For entity-level cards, navigate to any Backstage catalog entity and follow the steps in Catalog Integration to add the SkillMeat tab to your entity page.

5.3 — Verify the Scaffolder Backend Plugin Loaded

Check the backend process logs for a line confirming SkillMeat actions were registered:

[skillmeat-scaffolder-module] Registered actions: skillmeat:context:inject,
skillmeat:deployment:register, skillmeat:attest, skillmeat:bom:generate

The exact log format depends on your Backstage version. To confirm actions are available via the API:

curl -s http://localhost:7007/api/scaffolder/v2/actions \
  | jq '[.[] | select(.id | startswith("skillmeat:"))]'

A successful response lists all registered SkillMeat actions:

[
  { "id": "skillmeat:bundle:validate", ... },
  { "id": "skillmeat:context:inject", ... },
  { "id": "skillmeat:deployment:register", ... },
  { "id": "skillmeat:attest", ... },
  { "id": "skillmeat:bom:generate", ... }
]

5.4 — Verify SkillMeat API Connectivity

The frontend plugin calls skillmeat.baseUrl directly from the browser using the Backstage fetchApi. Confirm the URL is reachable from the browser host (not only from the backend):

curl -sf https://sam.internal/api/v1/version | jq .

Expected response includes {"version": "1.x.x", ...}.


Health Check and Troubleshooting

Plugin Not Appearing in Sidebar

Symptom: The Platform Health or AI ROI Dashboard items are missing from the sidebar.

Check:

  1. Confirm @skillmeat/backstage-plugin is listed in packages/app/package.json — if missing, re-run the yarn add step.
  2. Confirm the <SidebarItem> entries were added to Root.tsx and that the file was saved.
  3. Check the browser console for JavaScript import errors.

CORS Errors

Symptom: Browser console shows CORS policy errors when the frontend plugin calls the SkillMeat API.

Resolution: The SkillMeat API must include Access-Control-Allow-Origin headers that permit requests from the Backstage frontend origin (e.g., http://localhost:3000).

For the telemetry endpoints, route calls through the Backstage backend proxy instead of calling the API directly. Add the proxy configuration described in Step 3 and ensure changeOrigin: true is set.

For the core plugin (context cards, BOM, drift), the SkillMeatClient uses the Backstage fetchApi which inherits the frontend origin. Ensure your SkillMeat API is configured to allow CORS from your Backstage origin.

Authentication Token Missing

Symptom: Scaffolder templates using skillmeat:context:inject or skillmeat:deployment:register fail with a 401 Unauthorized response from the SkillMeat API.

Check:

  1. Confirm SAM_SERVICE_ACCOUNT_TOKEN (or SAM_API_TOKEN) is exported in the environment where the Backstage backend process runs.
  2. Verify the variable name in your environment matches the ${VAR_NAME} reference in app-config.yaml — variable names are case-sensitive.
  3. Restart the Backstage backend process after setting the environment variable — Backstage reads app-config.yaml substitutions at startup.

Scaffolder Actions Not Found

Symptom: Scaffolder templates referencing skillmeat:* actions fail with "Action not found".

Check:

  1. Confirm @skillmeat/backstage-plugin-scaffolder-backend is listed in packages/backend/package.json.
  2. For the new backend system, verify skillmeatScaffolderModule is added with backend.add(skillmeatScaffolderModule) in packages/backend/src/index.ts.
  3. For the legacy backend, verify the action factories are imported and included in the actions array passed to createRouter.
  4. Run the curl verification command from Step 5.3 to confirm the actions appear in the scaffolder API.

Version Mismatch

Symptom: TypeScript compilation errors in packages/app or packages/backend after installing the plugin, referencing mismatched Backstage API types.

Resolution: The plugins target Backstage v1.27.x. If your Backstage version is older, run backstage-cli versions:bump to update all Backstage packages to a compatible version. Check the compatibility table:

Plugin Version Backstage Version RHDH Version
0.1.x 1.27.x 1.3+

SkillMeat API Unreachable from Backend

Symptom: Scaffolder actions fail with connection-refused or timeout errors, but the API is accessible in the browser.

Explanation: The scaffolder backend plugin runs in the Backstage backend process (Node.js), not in the browser. The skillmeat.baseUrl must be reachable from the backend host, not only from the client browser.

Resolution:

  1. Test connectivity from the backend host:
    curl -sf https://sam.internal/health
    
  2. If the API is only accessible internally, adjust the skillmeat.baseUrl to use the internal service DNS name or IP.
  3. If DNS resolution is the issue, add the hostname to /etc/hosts or use an IP address directly.

Next Steps

With the plugins installed and the basic configuration verified, continue to:

  • Catalog Integration — Set up the entity provider to expose SkillMeat artifacts in Backstage's software catalog, add EntitySkillMeatContent tabs to your entity pages, and configure entity refresh triggers.

  • Developer Portal Integration — Configure the developer portal surface so that developers can discover, browse, and adopt SkillMeat artifacts within their IDP workflow.

  • Governance & Permissions — Define organizational policies, role/group mappings, and audit configuration for controlled artifact adoption.