Skip to main content

CLAUDE.md - app-portal

This file provides guidance to Claude Code when working with the app-portal Backstage application.

Prerequisites

# Install required tools
brew install node@20 direnv sops age

Quick Start

# Enter directory (auto-loads environment and decrypts secrets)
cd app-portal
direnv allow

# Install and start
yarn install
yarn start

Frontend: http://localhost:3000
Backend: http://localhost:7007

Secret Management

This project uses SOPS for secret encryption with SSH keys:

  • Encrypted files:
    • .env.enc - GitHub App credentials
    • github-app-key.pem.enc - GitHub App private key
  • Auto-decryption: Via direnv when entering directory
  • SSH-based: Uses your existing SSH key from GitHub

Adding Team Members

# Get their SSH public key
ssh-add -L # They run this

# Add to .sops.yaml, then:
sops updatekeys .env.enc
sops updatekeys github-app-key.pem.enc

Development Commands

# Start development server
yarn start
yarn start:log # With timestamped logging (Unix/Linux/macOS only)

# Installation
yarn install
yarn install:log # With timestamped logging (Unix/Linux/macOS only)

# Build for production
yarn build:backend
yarn build:all

# Testing
yarn test
yarn test:all
yarn test:e2e

# Linting and formatting
yarn lint
yarn lint:all
yarn prettier:check
yarn fix

# Clean build artifacts
yarn clean

# Create new plugin
yarn new

Logging Scripts

The :log variants capture timestamped output for debugging:

  • Default location: ./logs/
  • Custom: BACKSTAGE_LOG_DIR=/path yarn start:log
  • Platform: Unix/Linux/macOS only (uses shell-specific syntax)

Project Structure

app-portal/
├── packages/
│ ├── app/ # Frontend React application
│ │ ├── src/
│ │ │ ├── App.tsx # Main app component
│ │ │ └── components/ # UI components
│ │ └── package.json
│ └── backend/ # Backend Node.js services
│ ├── src/
│ │ ├── index.ts # Backend entry point
│ │ └── scaffolder/ # Custom scaffolder actions
│ │ ├── index.ts
│ │ └── generateId.ts
│ └── package.json
├── examples/ # Example data for development
│ ├── entities.yaml # Example catalog entities
│ ├── org.yaml # Example users/groups
│ └── template/ # Example template
├── app-config.yaml # Base configuration
├── app-config.production.yaml # Production overrides
├── app-config.local.yaml # Local overrides (gitignored)
├── .envrc # Direnv config (auto-loads secrets)
├── .sops.yaml # SOPS encryption config
└── backstage.json # Backstage version

Configuration

GitHub App Integration

The GitHub App provides:

  • Repository discovery
  • Template scaffolding
  • Authentication

Credentials are stored encrypted in .env.enc.

Catalog Providers

  1. GitHub Organization Scanner

    • Org: open-service-portal
    • Frequency: 30 minutes
  2. Template Discovery

    • Pattern: service-*-template repositories
    • Auto-imports templates from GitHub

Authentication

  • Development: GitHub OAuth + Guest auth
  • Production: GitHub OAuth only

Custom Features

Scaffolder Actions

Custom action for unique ID generation:

  • Location: packages/backend/src/scaffolder/generateId.ts
  • Generates unique resource identifiers

Integrations

  • GitHub (primary)
  • Kubernetes (optional, configured in app-config.local.yaml)
  • TechDocs (local builder)

Troubleshooting

Secrets not loading

# Check if SSH key is loaded
ssh-add -L

# If "The agent has no identities", add your SSH key:
ssh-add ~/.ssh/id_ed25519 # or ~/.ssh/id_rsa

# Manually test decryption
sops -d --input-type dotenv --output-type dotenv .env.enc

# Re-allow direnv
direnv allow

SSH key with passphrase

If using a passphrase-protected SSH key, you'll be prompted when entering the directory:

  • Enter the passphrase once per terminal session
  • Or add key to ssh-agent: ssh-add ~/.ssh/id_ed25519
  • Alternative: Use a dedicated key without passphrase for development

Build issues

# Clean and rebuild
yarn clean
yarn install
yarn build:backend

Port conflicts

Default ports:

  • Frontend: 3000
  • Backend: 7007

Change in app-config.yaml if needed.

Testing

# Unit tests
yarn test

# With coverage
yarn test:all

# E2E tests (requires running app)
yarn test:e2e

Deployment

See deploy-backstage repository for Kubernetes deployment.

Contributing

  1. Create feature branch from main
  2. Make changes
  3. Run tests: yarn test
  4. Run linter: yarn lint
  5. Create PR with semantic commit message