Skip to content

Platform Mesh Portal – How It Uses OpenMFP

Executive Summary

The Platform Mesh Portal is a Kubernetes-native, micro-frontend application built on the Open Micro Frontend Platform (OpenMFP). It leverages OpenMFP's Luigi-based architecture to provide a unified, extensible UI for the Platform Mesh service ecosystem, enabling dynamic integration of micro frontends through configuration-driven discovery.

Project Origin & Context

Repository & Governance

Repository: github.com/platform-mesh/portal Copyright: SAP SE and Platform Mesh contributors License: Apache-2.0 Status: Alpha (APIs subject to breaking changes)

The Platform Mesh portal was created as the central user interface for the Platform Mesh ecosystem, which is a NeoNephos Foundation project under Linux Foundation Europe. The portal serves as a shell application that orchestrates multiple micro frontends representing different Platform Mesh services (accounts, extensions, security, etc.).

Key Design Goals:

  • Provide a unified interface for Platform Mesh services
  • Enable teams to develop and deploy micro frontends independently
  • Integrate with Kubernetes-native Extension Manager for dynamic micro frontend discovery
  • Reuse OpenMFP's proven Luigi-based architecture rather than building from scratch
  • Support entity-based navigation (Organizations → Accounts → Projects → Resources)

Development Status

The portal is currently in alpha stage. According to the repository: "APIs and concepts may change on short notice including breaking changes or complete removal of apis." Production use is not recommended.

How Platform Mesh Leverages OpenMFP

Platform Mesh uses OpenMFP as its foundational framework, building custom services on top of the OpenMFP libraries to create a Kubernetes-native portal experience.

OpenMFP Libraries Used

Library Version Purpose Platform Mesh Usage
@openmfp/portal-ui-lib v0.186.12 Frontend Luigi integration Core portal UI bootstrapping, configuration services
@openmfp/portal-server-lib v0.163.8 Backend REST API server Configuration endpoint, proxy management
@luigi-project/core v2.26.0 Luigi micro frontend framework Navigation, routing, context management
@luigi-project/client v2.26.0 Luigi Client API Micro frontend communication with shell
@luigi-project/plugin-auth-oauth2 v2.26.0 OAuth2 authentication OIDC integration with Keycloak

Platform Mesh Extensions to OpenMFP

Platform Mesh adds custom libraries that extend OpenMFP's functionality:

Library Version Purpose
@platform-mesh/portal-ui-lib v0.31.0 Custom service implementations for Platform Mesh-specific features
@platform-mesh/portal-server-lib v0.6.15 Kubernetes client integration, Extension Manager API client

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                     Platform Mesh Portal (Shell)                     │
│                                                                       │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │                 Frontend (Angular + OpenMFP)                    │ │
│  │  ┌──────────────────────────────────────────────────────────┐  │ │
│  │  │           @openmfp/portal-ui-lib (PortalComponent)        │  │ │
│  │  │  - providePortal(portalOptions)                           │  │ │
│  │  │  - Luigi Core Bootstrap                                   │  │ │
│  │  │  - Navigation Tree Management                             │  │ │
│  │  │  - Authentication Handler (OAuth2)                        │  │ │
│  │  └──────────────────────────────────────────────────────────┘  │ │
│  │                              ↕                                  │ │
│  │  ┌──────────────────────────────────────────────────────────┐  │ │
│  │  │      Platform Mesh Custom Service Implementations        │  │ │
│  │  │  (@platform-mesh/portal-ui-lib)                          │  │ │
│  │  │                                                           │  │ │
│  │  │  - PMStaticSettingsConfigService                         │  │ │
│  │  │  - NodeChangeHookConfigServiceImpl                       │  │ │
│  │  │  - CustomGlobalNodesServiceImpl                          │  │ │
│  │  │  - NodeContextProcessingServiceImpl                      │  │ │
│  │  │  - LuigiExtendedGlobalContextConfigServiceImpl           │  │ │
│  │  │  - HeaderBarConfigServiceImpl                            │  │ │
│  │  │  - UserProfileConfigServiceImpl                          │  │ │
│  │  │  - CustomRoutingConfigServiceImpl                        │  │ │
│  │  └──────────────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                       │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │              Backend (NestJS + OpenMFP Server)                  │ │
│  │  ┌──────────────────────────────────────────────────────────┐  │ │
│  │  │        @openmfp/portal-server-lib (NestJS Module)        │  │ │
│  │  │  - /rest/config endpoint                                 │  │ │
│  │  │  - Environment variable injection                        │  │ │
│  │  │  - Static file serving                                   │  │ │
│  │  └──────────────────────────────────────────────────────────┘  │ │
│  │                              ↕                                  │ │
│  │  ┌──────────────────────────────────────────────────────────┐  │ │
│  │  │     Platform Mesh Server Extensions                      │  │ │
│  │  │  (@platform-mesh/portal-server-lib)                      │  │ │
│  │  │                                                           │  │ │
│  │  │  - Kubernetes Client (@kubernetes/client-node)           │  │ │
│  │  │  - Extension Manager API Integration (GraphQL)           │  │ │
│  │  │  - Account Controller Integration (REST)                 │  │ │
│  │  │  - Content Configuration Aggregation                     │  │ │
│  │  └──────────────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬───────────────────────────────────────┘
                ┌───────────────┴────────────────┐
                │                                │
                ▼                                ▼
    ┌───────────────────────┐      ┌───────────────────────────┐
    │  Kubernetes Cluster   │      │   Platform Mesh Services  │
    │                       │      │                           │
    │  - Extension CRDs     │      │  - Extension Manager      │
    │  - ConfigMaps         │      │  - Account Controller     │
    │  - Secrets            │      │  - Security Operator      │
    │  - ServiceAccounts    │      │  - Other Controllers      │
    └───────────────────────┘      └───────────────────────────┘
                │                                │
                └────────────────┬───────────────┘
                ┌────────────────────────────────────┐
                │     Deployed Micro Frontends       │
                │                                    │
                │  - Account Management UI           │
                │  - Extension Catalog UI            │
                │  - Security Dashboard UI           │
                │  - Resource Management UI          │
                │  - Monitoring UI                   │
                └────────────────────────────────────┘

Component Responsibilities

Clear Separation of Concerns

OpenMFP Libraries (reused as-is):

  • Luigi framework integration
  • Base authentication flows
  • Configuration service interfaces
  • REST API structure
  • Static file serving

Platform Mesh Custom Code:

  • Kubernetes client integration
  • Extension Manager API communication
  • Entity model (Organizations, Accounts, Projects)
  • Custom navigation logic
  • Platform Mesh-specific authentication context
  • GraphQL API integration
  • Platform Mesh branding and theming

Technical Stack Deep Dive

Frontend Stack

{
  "framework": "Angular v20.3.15",
  "language": "TypeScript v5.9.3",
  "microFrontendFramework": "Luigi v2.26.0",
  "stateManagement": "RxJS v7.8.2",
  "uiComponents": "@ui5/webcomponents-ngx v0.5.10",
  "utilities": [
    "lodash v4.17.23",
    "jwt-decode v4.0.0",
    "jmespath v0.16.0"
  ],
  "buildTool": "Angular CLI v20.3.13",
  "testing": "Jest v29.7.0"
}

Key Frontend Dependencies:

  • Angular 20: Latest Angular framework with standalone components
  • Luigi Core & Client: SAP's micro frontend orchestrator
  • UI5 Web Components: SAP Fiori-compliant UI components
  • RxJS: Reactive programming for async operations
  • JMESPath: JSON query language for content configuration visibility rules
  • JWT Decode: Token parsing for authentication context

Backend Stack

{
  "framework": "NestJS v11.1.9",
  "platform": "Node.js",
  "language": "TypeScript v5.9.3",
  "httpServer": "Express (via @nestjs/platform-express)",
  "kubernetesClient": "@kubernetes/client-node v1.4.0",
  "graphqlClient": "graphql-request v7.4.0",
  "httpClient": "axios v1.13.2 (@nestjs/axios v4.0.1)",
  "validation": "class-validator v0.14.3",
  "config": "dotenv v17.2.3",
  "testing": "Jest v30.2.0 + supertest + nock"
}

Key Backend Dependencies:

  • NestJS: Enterprise-grade Node.js framework with TypeScript and dependency injection
  • Kubernetes Client: Direct integration with Kubernetes API for CRD management
  • GraphQL Request: Client for Extension Manager GraphQL API
  • Axios: HTTP client for REST API calls to Platform Mesh services
  • Class Validator: DTO validation for incoming requests
  • Dotenv: Environment variable management

Deployment Stack

Docker → Multi-stage build
  ├─ Stage 1: Build Frontend (Angular CLI)
  ├─ Stage 2: Build Backend (TypeScript compiler)
  └─ Final: Serve from single container
      ├─ Port 4300: Frontend assets
      └─ Port 3000: Backend REST API

Frontend Integration: PortalOptions Configuration

The core of Platform Mesh's OpenMFP integration is the PortalOptions configuration in frontend/src/main.ts:

const portalOptions: PortalOptions = {
  staticSettingsConfigService: PMStaticSettingsConfigService,
  nodeChangeHookConfigService: NodeChangeHookConfigServiceImpl,
  customGlobalNodesService: CustomGlobalNodesServiceImpl,
  nodeContextProcessingService: NodeContextProcessingServiceImpl,
  luigiExtendedGlobalContextConfigService:
    LuigiExtendedGlobalContextConfigServiceImpl,
  headerBarConfigService: HeaderBarConfigServiceImpl,
  userProfileConfigService: UserProfileConfigServiceImpl,
  routingConfigService: CustomRoutingConfigServiceImpl,
};

bootstrapApplication(PortalComponent, {
  providers: [
    provideRouter(routes),
    providePortal(portalOptions),
    provideZonelessChangeDetection(),
  ],
});

Service Implementations

Custom Service Layer

Each service implements an OpenMFP interface and customizes portal behavior for Platform Mesh:

1. PMStaticSettingsConfigService

Purpose: Defines static Luigi configuration (navigation structure, routing mode, authentication provider)

Key Configuration:

  • Routing: Hash-based routing (#/organizations/123/accounts/456)
  • Authentication: OAuth2 plugin with Keycloak integration
  • Navigation: Top-level nodes (Home, Organizations, Settings)
  • Context: Global context variables (user info, tenant info)

2. NodeChangeHookConfigServiceImpl

Purpose: Executes logic when navigation nodes change (e.g., user navigates from one page to another)

Platform Mesh Usage:

  • Track current entity context (organization ID, account ID, project ID)
  • Fetch dynamic extensions when entering entity contexts
  • Update breadcrumbs
  • Load entity-specific data

3. CustomGlobalNodesServiceImpl

Purpose: Provides additional navigation nodes beyond what's defined in micro frontend configurations

Platform Mesh Usage:

  • Inject "Home" node
  • Add "Admin" section for cluster administrators
  • Provide "Settings" and "User Profile" nodes
  • Create "Help" and "Documentation" links

4. NodeContextProcessingServiceImpl

Purpose: Processes and enriches Luigi context before passing to micro frontends

Platform Mesh Usage:

  • Extract entity IDs from URL path
  • Fetch entity details from Account Controller API
  • Add user roles and permissions from Security Operator
  • Inject tenant-specific configuration
  • Add feature toggle states

5. LuigiExtendedGlobalContextConfigServiceImpl

Purpose: Manages global context shared across all micro frontends

Platform Mesh Usage:

  • User authentication token (JWT)
  • User profile (name, email, roles)
  • Current tenant/organization
  • Cluster connection details
  • Feature flags
  • Theme preferences

6. HeaderBarConfigServiceImpl

Purpose: Configures the portal header bar (logo, title, actions)

Platform Mesh Usage:

  • Platform Mesh logo and branding
  • Global search integration
  • User profile dropdown
  • Notification center
  • Quick actions (create project, view docs)

7. UserProfileConfigServiceImpl

Purpose: Defines user profile menu items and actions

Platform Mesh Usage:

  • User settings
  • Theme switcher
  • Language selector
  • Logout action
  • Help & Support links

8. CustomRoutingConfigServiceImpl

Purpose: Custom routing logic and deep linking

Platform Mesh Usage:

  • Entity-aware routing (/organizations/:orgId/accounts/:accountId)
  • Default route redirects
  • 404 handling
  • Access control checks

Backend Integration: Extension Discovery

The backend server extends @openmfp/portal-server-lib with Platform Mesh-specific endpoints and integrations.

Extension Manager Integration

// Platform Mesh backend fetches extensions from Extension Manager GraphQL API
const extensionsQuery = `
  query GetExtensions($entityType: String!, $workspaceId: String!) {
    extensions(entityType: $entityType, workspaceId: $workspaceId) {
      id
      name
      version
      contentConfigurationUrl
      enabled
    }
  }
`;

// Aggregate content configurations from all extensions
const contentConfigurations = await Promise.all(
  extensions.map(ext =>
    axios.get(ext.contentConfigurationUrl)
  )
);

// Merge into unified Luigi configuration
const luigiConfig = mergeContentConfigurations(contentConfigurations);

Configuration Endpoint

OpenMFP Provides: /rest/config endpoint that serves environment variables as JSON

Platform Mesh Extends:

GET /rest/config
{
  "extensions": [...],           // From Extension Manager
  "entities": {                  // From Account Controller
    "organizations": [...],
    "accounts": [...]
  },
  "permissions": {...},          // From Security Operator
  "clusterConfig": {...},        // Kubernetes context
  "features": {...}              // Feature flags
}

Kubernetes Integration

import * as k8s from '@kubernetes/client-node';

// Read in-cluster service account
const kc = new k8s.KubeConfig();
kc.loadFromCluster();

const k8sApi = kc.makeApiClient(k8s.CustomObjectsApi);

// Fetch Extension CRDs
const extensions = await k8sApi.listNamespacedCustomObject(
  'platform-mesh.io',
  'v1',
  namespace,
  'extensions'
);

Runtime Integration Flow

End-to-End Flow

1. Portal Initialization

User accesses https://portal.platform-mesh.example.com
Browser loads Portal Angular app (PortalComponent)
Angular calls providePortal(portalOptions)
OpenMFP portal-ui-lib initializes Luigi Core
Luigi requests configuration from backend
GET /rest/config → Backend returns merged configuration
Luigi builds navigation tree from configuration
Portal renders header, navigation, and empty content frame

2. Authentication Flow

Luigi detects no auth token
Redirects to OAuth2 provider (Keycloak)
User logs in with credentials
Keycloak redirects back with authorization code
Luigi OAuth2 plugin exchanges code for JWT token
LuigiExtendedGlobalContextConfigServiceImpl stores token
Token injected into global context
All backend requests include Authorization: Bearer <token>

3. Navigation & Entity Context

User clicks "Organizations" in navigation
Luigi routes to /#/organizations
NodeChangeHookConfigServiceImpl detects route change
Backend fetches organizations from Account Controller
Organizations list micro frontend loaded in iframe
User clicks specific organization "ACME Corp"
Luigi routes to /#/organizations/acme-123
NodeChangeHookConfigServiceImpl extracts organizationId=acme-123
Backend requests extensions for entityType="organization"
Extension Manager returns applicable extensions
Luigi dynamically adds extension nodes to navigation
NodeContextProcessingServiceImpl enriches context:
    {
      organizationId: "acme-123",
      organization: { name: "ACME Corp", ... },
      user: { ... },
      permissions: [...]
    }
Context passed to micro frontend via Luigi Client
Micro frontend receives context and renders organization dashboard

4. Micro Frontend Communication

Account Management Micro Frontend loads
Initializes Luigi Client library
Requests context via LuigiClient.getContext()
Receives:
    {
      organizationId: "acme-123",
      organization: { name: "ACME Corp" },
      accountId: "account-456",  // if in account context
      user: { id: "user-1", roles: ["admin"] },
      permissions: { canEdit: true, canDelete: false }
    }
Micro frontend makes API call to Account Controller
    GET /api/accounts/account-456
    Authorization: Bearer <token from global context>
Micro frontend renders account details
User clicks "Edit Account" button
Micro frontend shows confirmation dialog using Luigi UX Manager:
    LuigiClient.uxManager().showConfirmationModal({
      header: "Edit Account",
      body: "Do you want to edit this account?",
      buttonConfirm: "Yes",
      buttonDismiss: "Cancel"
    })
User confirms → Micro frontend saves changes
Micro frontend shows success alert:
    LuigiClient.uxManager().showAlert({
      text: "Account updated successfully",
      type: "success"
    })
Micro frontend publishes custom event for other micro frontends:
    LuigiClient.publishEvent(new CustomEvent('account-updated', {
      detail: { accountId: "account-456" }
    }))
Other micro frontends listening to this event refresh their data

Key Integration Points

1. Luigi Configuration Merging

OpenMFP Behavior: Fetches content configurations from registered URLs and merges them into Luigi navigation tree

Platform Mesh Extension:

  • Queries Extension Manager for available extensions
  • Filters extensions based on current entity context
  • Applies permission checks (Security Operator)
  • Merges configurations with conflict resolution
  • Adds Platform Mesh global nodes

2. Authentication & Authorization

OpenMFP Behavior: Luigi OAuth2 plugin handles OIDC flow

Platform Mesh Extension:

  • Integrates with Keycloak (Platform Mesh's IdP)
  • Stores JWT in global context
  • Passes token to all backend API calls
  • Queries Security Operator for fine-grained permissions
  • Injects permissions into micro frontend context

3. Entity-Based Navigation

OpenMFP Behavior: Supports defineEntity in content configuration

Platform Mesh Extension:

  • Defines entity hierarchy (Organization → Account → Project → Resource)
  • Fetches entity details from Account Controller
  • Dynamically loads entity-specific extensions
  • Updates breadcrumbs with entity names
  • Resolves entity titles via API calls

4. Development Mode

OpenMFP Behavior: Allows registering local micro frontends for testing

Platform Mesh Usage:

  1. Developer runs micro frontend locally: npm start (http://localhost:4200)
  2. Opens Platform Mesh portal: https://portal.platform-mesh.example.com
  3. Clicks user menu → Settings → Development
  4. Enables "Development Mode"
  5. Adds local URL: http://localhost:4200/assets/content-configuration.json
  6. Portal fetches configuration and adds to navigation
  7. Developer can test integration without deploying

Deployment & Operations

Docker Build

# Multi-stage build
FROM node:25.6.0 AS builder

# Build frontend
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build

# Build backend
WORKDIR /app/backend
COPY backend/package*.json ./
RUN npm ci
COPY backend/ ./
RUN npm run build

# Production image
FROM node:25.6.0-slim
WORKDIR /app

# Copy built assets
COPY --from=builder /app/frontend/dist /app/public
COPY --from=builder /app/backend/dist /app/dist
COPY backend/package*.json ./
RUN npm ci --only=production

# Expose ports
EXPOSE 3000 4300

CMD ["node", "dist/main.js"]

Environment Configuration

# OpenMFP Configuration (via portal-server-lib)
OPENMFP_PORTAL_CONTEXT_api_base_url=https://api.platform-mesh.example.com
OPENMFP_PORTAL_CONTEXT_cluster_domain=cluster.local

# Platform Mesh Configuration
KUBERNETES_SERVICE_HOST=kubernetes.default.svc
KUBERNETES_SERVICE_PORT=443
EXTENSION_MANAGER_URL=http://extension-manager.platform-mesh.svc.cluster.local/graphql
ACCOUNT_CONTROLLER_URL=http://account-controller.platform-mesh.svc.cluster.local
SECURITY_OPERATOR_URL=http://security-operator.platform-mesh.svc.cluster.local

# Authentication
OIDC_ISSUER=https://keycloak.platform-mesh.example.com/realms/platform-mesh
OIDC_CLIENT_ID=platform-mesh-portal
OIDC_CLIENT_SECRET=<secret>

# Feature Flags
FEATURE_ANALYTICS_ENABLED=false
FEATURE_BETA_EXTENSIONS=true

Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: platform-mesh-portal
  namespace: platform-mesh
spec:
  replicas: 3
  selector:
    matchLabels:
      app: portal
  template:
    metadata:
      labels:
        app: portal
    spec:
      serviceAccountName: portal
      containers:
      - name: portal
        image: platform-mesh/portal:latest
        ports:
        - containerPort: 3000
          name: backend
        - containerPort: 4300
          name: frontend
        env:
        - name: KUBERNETES_SERVICE_HOST
          value: kubernetes.default.svc
        envFrom:
        - configMapRef:
            name: portal-config
        - secretRef:
            name: portal-secrets
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: portal
  namespace: platform-mesh
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: portal-extension-reader
rules:
- apiGroups: ["platform-mesh.io"]
  resources: ["extensions"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: portal-extension-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: portal-extension-reader
subjects:
- kind: ServiceAccount
  name: portal
  namespace: platform-mesh

How Platform Mesh Benefits from OpenMFP

Value Delivered

1. Accelerated Development

Without OpenMFP: Platform Mesh would need to build from scratch:

  • Luigi integration layer (months of work)
  • Configuration service architecture
  • Authentication integration
  • Development mode tooling
  • Documentation and examples

With OpenMFP: Platform Mesh gets all this out of the box, focusing only on Platform Mesh-specific logic.

Time Saved: Estimated 6-9 months of development time

2. Community-Driven Improvements

OpenMFP is maintained by the broader community. When OpenMFP releases improvements (e.g., better error handling, performance optimizations, new Luigi features), Platform Mesh automatically benefits by upgrading dependencies.

Example: When OpenMFP added support for Luigi v2.26.0 features, Platform Mesh upgraded @openmfp/portal-ui-lib and immediately gained those features.

3. Proven Architecture

OpenMFP's patterns are battle-tested across multiple projects. Platform Mesh avoids common pitfalls and architectural mistakes by following OpenMFP's established patterns.

4. Documentation & Learning Resources

Developers joining Platform Mesh can refer to OpenMFP documentation, tutorials, and examples. This reduces onboarding time and training costs.

5. Standards & Interoperability

By using OpenMFP, Platform Mesh ensures its micro frontends follow industry standards and can potentially be reused in other OpenMFP-based portals.

Differences from Pure OpenMFP

Platform Mesh Customizations

While Platform Mesh heavily relies on OpenMFP, it adds several custom layers:

Aspect OpenMFP Default Platform Mesh Customization
Extension Discovery Static URLs or manual registration Dynamic discovery via Extension Manager CRDs in Kubernetes
Entity Model Basic entity support Rich hierarchy (Org → Account → Project → Resource) with Account Controller integration
Authorization Basic visibility rules Integration with Security Operator and OpenFGA for fine-grained permissions
Configuration Source Environment variables or config files Kubernetes ConfigMaps, Secrets, and CRDs
Backend API Simple REST endpoints GraphQL integration with Extension Manager, REST APIs to multiple controllers
Deployment Docker or static hosting Kubernetes-native with ServiceAccounts, RBAC, and cluster integration
Monitoring Basic health checks Integration with Platform Mesh observability stack (Prometheus, Grafana)

Development Workflow

1. Local Development Setup

# Clone repository
git clone https://github.com/platform-mesh/portal.git
cd portal

# Install dependencies
npm run npm:install:ui
npm run npm:install:server

# Start development servers (frontend + backend)
npm start

# Frontend: http://localhost:4300
# Backend: http://localhost:3000

2. Creating a New Service Implementation

# Example: Add a new configuration service

# 1. Create service in frontend/src/services/
touch frontend/src/services/my-custom-config.service.ts

# 2. Implement OpenMFP service interface
import { MyConfigService } from '@openmfp/portal-ui-lib';

export class MyCustomConfigServiceImpl implements MyConfigService {
  getConfig(): Config {
    return {
      // Custom Platform Mesh configuration
    };
  }
}

# 3. Register in portalOptions (main.ts)
const portalOptions: PortalOptions = {
  // ... existing services
  myCustomConfigService: MyCustomConfigServiceImpl,
};

# 4. Test locally
npm start

3. Testing Changes

# Lint code
npm run lint

# Auto-fix lint issues
npm run lint:fix

# Run unit tests
npm test

# Run tests with coverage
npm run test:cov

# Build production bundle
npm run build

4. Pre-commit Hooks

Platform Mesh uses Husky and lint-staged to enforce quality:

{
  "lint-staged": {
    "**/*.ts": [
      "eslint --fix",
      "prettier --write"
    ]
  }
}

Every commit automatically: - Lints TypeScript files - Formats code with Prettier - Runs affected tests

Contributing to Platform Mesh Portal

Contribution Process

1. Fork & Clone

# Fork the repository on GitHub
# Clone your fork
git clone https://github.com/<your-username>/portal.git
cd portal

2. Create Feature Branch

git checkout -b feature/my-new-feature

3. Make Changes

  • Follow existing code patterns
  • Add tests for new functionality
  • Update documentation if needed
  • Ensure all tests pass

4. Commit & Push

# Commits trigger pre-commit hooks (lint-staged)
git commit -m "feat: add new custom service for XYZ"
git push origin feature/my-new-feature

5. Open Pull Request

  1. Open PR against platform-mesh/portal main branch
  2. Fill out PR template
  3. Request review from maintainers
  4. Address review feedback
  5. Wait for approval and merge

6. Contributing to OpenMFP Libraries

If your change requires modifications to OpenMFP libraries:

  1. Open issue in openmfp/<library> repository
  2. Discuss proposed change with OpenMFP maintainers
  3. Submit PR to OpenMFP repository
  4. Wait for OpenMFP release
  5. Update Platform Mesh to use new OpenMFP version

Monitoring & Troubleshooting

Development Mode Debugging

// Enable Luigi debug logs in browser console
localStorage.setItem('luigi.debug', 'true');

// Inspect current context
LuigiClient.getContext();

// Check loaded extensions
fetch('/rest/config').then(r => r.json()).then(console.log);

Common Issues

Issue Symptoms Resolution
Extensions not loading Empty navigation Check Extension Manager API connectivity; verify CRDs exist in Kubernetes
Authentication loop Keeps redirecting to login Verify Keycloak configuration; check OIDC client ID and secret
Blank micro frontend White iframe Check CORS headers on micro frontend; verify content-configuration.json is accessible
Context not available Empty getContext() Ensure Luigi Client addInitListener is used; check backend context processing
Permissions denied Features hidden Verify Security Operator integration; check permission assignments in OpenFGA

Backend Logs

# View portal backend logs
kubectl logs -n platform-mesh deployment/platform-mesh-portal -c portal

# Follow logs in real-time
kubectl logs -n platform-mesh deployment/platform-mesh-portal -c portal -f

# Check Extension Manager integration
kubectl logs -n platform-mesh deployment/platform-mesh-portal -c portal | grep "extension-manager"

Health Checks

# Backend health
curl http://localhost:3000/health

# Configuration endpoint
curl http://localhost:3000/rest/config

# Kubernetes readiness
kubectl get pod -n platform-mesh -l app=portal

Performance Considerations

1. Lazy Loading

OpenMFP supports lazy loading of micro frontends. Platform Mesh leverages this with preloadUrl: false:

{
  "pathSegment": "analytics",
  "viewGroup": {
    "preloadUrl": false  // Only load when user navigates to this page
  }
}

2. Configuration Caching

Platform Mesh backend caches Extension Manager responses to avoid repeated GraphQL queries:

// Cache configuration for 5 minutes
const configCache = new NodeCache({ stdTTL: 300 });

async function getExtensions(entityType: string) {
  const cacheKey = `extensions:${entityType}`;
  let extensions = configCache.get(cacheKey);

  if (!extensions) {
    extensions = await extensionManagerClient.query(...);
    configCache.set(cacheKey, extensions);
  }

  return extensions;
}

3. Frontend Optimization

  • Angular Zoneless Change Detection: Reduces overhead
  • OnPush Change Detection: Components only update when inputs change
  • Lazy Loaded Routes: Split bundles for faster initial load
  • Service Worker: Caches static assets (future enhancement)

Future Roadmap

Subject to Change

Potential future enhancements to Platform Mesh's OpenMFP integration:

  • [ ] Progressive Web App (PWA) support
  • [ ] Offline mode for read-only operations
  • [ ] Real-time updates via WebSockets
  • [ ] Advanced analytics and usage tracking
  • [ ] Multi-tenancy improvements
  • [ ] Theme customization per organization
  • [ ] Plugin marketplace for community extensions
  • OpenMFP Overview - Core framework concepts
  • Luigi Framework - Underlying micro frontend framework
  • Extension Manager - Kubernetes operator for micro frontend management
  • Account Controller - Entity model and API
  • Security Operator - Authorization and permissions
  • Keycloak Integration - Identity provider

Further Resources

Official Documentation

Community

  • Platform Mesh discussions on GitHub
  • OpenMFP Zulip Chat
  • NeoNephos Foundation community calls

Contributing & Community

How to Get Involved

Submit Issues: github.com/platform-mesh/portal/issues

Pull Requests: Follow CONTRIBUTING.md in the repository

Code of Conduct: All contributors must adhere to the project's CODE_OF_CONDUCT.md

License: Apache-2.0

Sources: