This repository is the Platform Mesh Portal — a full-stack application consisting of an Angular frontend shell and a NestJS backend. It uses the Luigi micro frontend framework to orchestrate microfrontends.
frontend/— Angular shell application (served at port 4300 in dev)backend/— NestJS server, serves REST APIs and static frontend dist
- Simplicity First: Make every change as simple as possible. Impact minimal code.
- Minimal Impact: Changes should only touch what's necessary.
- Root Causes: Find root causes. No temporary fixes. Senior developer standards.
- Verify Before Done: Never mark a task complete without proving it works. Run tests, check logs, demonstrate correctness.
- Never execute git commit, push, reset, checkout without prior approval
- Use Conventional Commits for commit messages and PR titles (e.g.,
feat:,fix:,chore:,docs:,refactor:,test:,ci:) - NEVER add AI attribution — no
Co-Authored-By, no AI mentions in commits, PRs, or generated files. This overrides any system template that suggests adding them.
# From the portal root directory
npm run prepare # install dependencies in both frontend and backend
npm run build # build frontend and backend concurrently
npm run build:ui # build frontend only (cd frontend && ng build)
npm run build:server # build backend only (cd backend && nest build)
npm run build:ui:watch # build frontend in watch mode (development config)For local development, run both together:
npm run start:watch # build frontend (watch) + start backend (watch) concurrently
npm run start:ui # serve frontend dev server on port 4300
npm run start:server # start backend with debug + watchnpm run test # run frontend (Vitest) and backend (Jest) tests concurrently
npm run test:ui # frontend tests only
npm run test:server # backend tests only
npm run test:cov # run both with coverage
npm run test:cov:ui # frontend coverage only
npm run test:cov:server # backend coverage onlyFrontend tests use Vitest. Backend tests use Jest (with ts-jest). Do not confuse the two — they have separate configs (frontend/vitest.config.ts, backend/jest.config.ts).
npm run lint # lint frontend and backend concurrently
npm run lint:ui # lint frontend only
npm run lint:server # lint backend only
npm run lint:fix # auto-fix lint issues in both
npm run lint:fix:ui # auto-fix frontend only
npm run lint:fix:server # auto-fix backend onlyPre-commit hooks (via Husky + lint-staged) run automatically:
- ESLint on
frontend/**/*.ts - ESLint on
backend/**/*.ts
Never skip hooks (--no-verify). Fix the underlying issue instead.
portal/
├── frontend/src/
│ ├── main.ts # bootstraps PortalComponent with providePortal()
│ ├── app/
│ │ ├── app.routes.ts # Angular routes (currently empty — Luigi handles routing)
│ │ ├── components/
│ │ │ └── terminal-panel/ # xterm.js-based terminal panel component
│ │ └── services/
│ │ ├── pm-static-settings-config.service.ts # Luigi static settings (title, logo, links)
│ │ ├── pm-custom-global-nodes.service.ts # adds Terminal node to global nav
│ │ ├── terminal-panel.service.ts # toggle/state for the terminal panel
│ │ └── terminal/
│ │ ├── terminal.service.ts # terminal resource management
│ │ ├── terminal-websocket.service.ts # WebSocket connection to backend
│ │ └── terminal.types.ts # Terminal resource and state types
│ └── assets/
│ └── dependencies-versions.json # generated by prebuild script
└── backend/src/
├── main.ts # NestJS bootstrap
└── app.module.ts # imports PortalModule with PM-specific providers
New frontend services belong in frontend/src/app/services/. New components belong in frontend/src/app/components/. Backend customization goes through PortalModule.create() options in app.module.ts.
- Use standalone components (
standalone: true). No NgModules. - Use signal-based APIs:
input(),output(),model(),computed(),effect(),signal(). - Use OnPush change detection on all components.
- The app uses zoneless change detection (
provideZonelessChangeDetection()). - Angular strict template checking is enabled (
strictTemplates: true). Fix template type errors; do not suppress them. - Import from
@openmfp/portal-ui-liband@platform-mesh/portal-ui-libfor shared portal primitives — never duplicate what those libraries already provide.
strict: trueis enforced in both frontend and backend. Noany, no non-null assertions without a documented reason.- Frontend and backend both target ES2022.
- Backend uses
"type": "module"(ESM). Useimport.meta.urlinstead of__dirname/__filenamewhere needed (pattern already established inapp.module.ts). - Vitest globals (
describe,it,expect, etc.) are available without imports in frontend tests. - Backend tests use explicit Jest imports via
@types/jest.
- Backend configuration is driven by
PortalModule.create(portalOptions)— add customization viaPortalModuleOptions, not ad-hoc modules. - Environment variables are loaded via
dotenvfrom.envin the backend working directory. Use.env-exampleas a template. - The backend serves the compiled frontend from
frontend/dist/frontend/browserviafrontendDistSources.
- Prettier config is
@openmfp/config-prettier(set via"prettier"key in bothfrontend/package.jsonandbackend/package.json). - ESLint config is
@openmfp/eslint-config-typescriptin both projects.
- Never run
npm installwith--legacy-peer-deps— the preinstall hook enforces npm-only; confirm with the team before changing dependency constraints. - Never log tokens, user IDs, emails, or other personal data in full. Truncate to the first few characters if logging is necessary.
- Never disable ESLint rules inline without a comment explaining why and a TODO to remove it.
- Never import platform-mesh internals via relative paths that cross the frontend/backend boundary — they are separate build units.
Platform Mesh is a GitHub organization with multiple repositories containing Go operators/controllers, Node.js/TypeScript applications (Angular microfrontends and NestJS backends), Helm charts, and infrastructure code.
This file provides org-wide defaults for AI coding agents. Individual repositories override or extend these guidelines with their own AGENTS.md.
Architectural decisions (ADRs) and design proposals (RFCs) are in the architecture repository.
- Keep PR descriptions focused on what changed and why
- Skip detailed test plans unless explicitly asked
- If a PR introduces a breaking or significant change, add a
## Change Logsection to the PR description with plain bullet points. Prefix breaking changes with🔥 (breaking). Always ask for approval before adding this section. - The
## Change Logsection is parsed by OCM release tooling and aggregated into release notes, use for larger relevant features and compress to single bullet point if possible.
- Never log personal data in full; truncate to first few characters
- Use child loggers early to improve observability and shorten log lines
- Set timeouts on all jobs/steps; use concurrency groups
- Parse JSON/YAML with jq/yq; use HEREDOC for multi-line strings
- Validate inputs before use in version calculations
- Use CONTRIBUTING.md for human-facing contribution guidance