This is a monorepo for the LFX One application, built with Angular 20 and stable zoneless change detection.
apps/lfx-one: Angular 20 SSR application with stable zoneless change detection and direct PrimeNG UI components
The app is 100% TypeScript.
- Frontend: Angular 20 with stable zoneless change detection, Angular Signals, PrimeNG components, Tailwind CSS
- UI Framework: PrimeNG 20 with custom LFX UI Core preset and Tailwind CSS integration
- Styling: Tailwind CSS v3 with PrimeUI plugin, CSS layers architecture, Google Fonts (Inter + Roboto Slab)
- Icons: Font Awesome Pro via kits (no npm packages)
- Backend: Express.js server with Angular 20 SSR, Auth0 authentication, Pino logging
- Infrastructure: PM2 process management for production deployment
This has comprehensive development tooling:
- TypeScript for static type checking with strict configuration
- ESLint for code linting with Angular 20 specific rules
- Prettier for code formatting with Tailwind class sorting
- Turborepo for efficient monorepo builds and caching
- PM2 for production process management
Please read our Contributing Guide for details on our code of conduct, development process, and how to submit pull requests.
- Node.js v22+ (specified in package.json)
- Yarn v4.9.2+ package manager
- Auth0 Account for authentication setup
- Supabase Project for user profile email management
-
Copy the environment template:
cp apps/lfx-one/.env.example apps/lfx-one/.env
-
Configure required environment variables:
Auth0 Configuration:
- Set
PCC_AUTH0_CLIENT_IDandPCC_AUTH0_CLIENT_SECRET- Local Development: The default client ID is
lfxand you can get the client secret from the k8s viak get secrets authelia-clients -n lfx -o jsonpath='{.data.lfx}' | base64 --decode
- Local Development: The default client ID is
- Update
PCC_AUTH0_ISSUER_BASE_URLwith your Auth0 domain- Local Development:
https://auth.k8s.orb.local
- Local Development:
- Configure
PCC_AUTH0_AUDIENCEfor your API- Local Development:
http://lfx-api.k8s.orb.local/
- Local Development:
- Set
PCC_AUTH0_SECRETto a sufficiently long random string (32+ characters)- Generate a random 32 characters long string
API Gateway:
- Set
API_GW_AUDIENCEto the audience for the secondary API Gateway access token- This token is fetched silently alongside the primary bearer token on each authenticated request
- Local Development:
https://api-gw.dev.platform.linuxfoundation.org/
M2M (Machine-to-Machine) Authentication:
- Set
M2M_AUTH_CLIENT_IDandM2M_AUTH_CLIENT_SECRETfor server-side API calls - Configure
M2M_AUTH_ISSUER_BASE_URL(typically same as Auth0 base URL) - Set
M2M_AUTH_AUDIENCEto match your API audience
Supabase Configuration:
- Create a project in Supabase
- Get your project URL and anon key from Project Settings → API
- Set
SUPABASE_URLandPOSTGRES_API_KEY - Used exclusively for user profile email management
Microservice Configuration:
- Set
LFX_V2_SERVICEto your query service endpoint- Local Development:
http://lfx-api.k8s.orb.local
- Local Development:
AI Service Configuration (Optional):
- Set
AI_PROXY_URLto your LiteLLM proxy endpoint for meeting agenda generation - Provide a valid API key in
AI_API_KEY
NATS Configuration:
- Set
NATS_URLfor internal messaging system (typically in Kubernetes environments)- Local Development:
nats://lfx-platform-nats.lfx.svc.cluster.local:4222
- Local Development:
Testing Configuration (Optional):
- Set
TEST_USERNAMEandTEST_PASSWORDfor automated E2E testing
Local Development:
- Set
NODE_TLS_REJECT_UNAUTHORIZED=0when using Authelia for local authentication
- Set
# Install dependencies
yarn install
# Start development server (Angular dev server)
yarn start
# Build the application
yarn build
# Run tests
yarn test# Linting
yarn lint # Lint and auto-fix all packages
yarn lint:check # Check linting without fixing
# Formatting
yarn format # Format code with Prettier
yarn format:check # Check formatting without fixing
# Testing
yarn test # Run unit tests (Karma)
yarn e2e # Playwright E2E suite (headless)
yarn e2e:ui # Playwright UI mode# Development
yarn start # Start Angular dev server (ng serve)
yarn build # Build the application
yarn watch # Build in watch mode
# Production
yarn start:server # Start SSR server via PM2 runtime
yarn start:prod # Start with PM2 in production
yarn reload:prod # Zero-downtime reload
yarn logs:prod # View PM2 logsYou can run commands for the application using Turborepo filters:
# Start the Angular app
yarn start --filter=lfx-one
# Build the Angular app
yarn build --filter=lfx-one
# Run tests for the app
yarn test --filter=lfx-one
# Lint the app
yarn lint --filter=lfx-onelfx-one/
├── apps/
│ └── lfx-one/ # Angular 20 SSR application
│ ├── src/app/ # Feature modules, layouts, shared code
│ ├── src/server/ # Express SSR server (controllers, services, routes, middleware)
│ ├── e2e/ # Playwright E2E tests
│ ├── eslint.config.js # Angular-specific ESLint rules
│ ├── .prettierrc.js # Prettier with Tailwind integration
│ ├── ecosystem.config.js # PM2 production configuration
│ └── tailwind.config.js # Tailwind with PrimeUI plugin
├── packages/
│ └── shared/ # @lfx-one/shared — types, constants, enums, utils, validators
├── docs/ # Architecture and deployment documentation
├── turbo.json # Turborepo pipeline configuration
└── package.json # Root workspace configuration
For the full directory breakdown (including src/app/shared/ subdirs and src/server/ layout) see CLAUDE.md and Architecture Overview.
The application is organized into feature modules under apps/lfx-one/src/app/modules/:
| Module | Description |
|---|---|
| badges | LFX badges — view and manage credentialing badges earned across projects |
| committees | Committee management — view, create, and manage project committees |
| dashboards | Lens-based dashboards (Me, Foundation, Project, Org) and supporting drawers |
| documents | Document management — browse and manage project documents |
| events | Events — browse LFX events and manage attendance |
| mailing-lists | Mailing list management — subscribe, unsubscribe, and manage lists |
| meetings | Meeting scheduling — create, manage, and join meetings with calendar integration |
| profile | User profile — profile management and account settings |
| settings | Application settings — preferences and configuration |
| surveys | Survey management — create surveys, collect responses, view NPS analytics |
| trainings | Training enrollments — view and manage training programs |
| transactions | Transactions — view billing / purchase history |
| votes | Voting system — create polls, cast votes, and view results |
- Stable zoneless change detection for improved performance
- Angular Signals for reactive state management (preferred over RxJS)
- Standalone components with explicit imports
- Component prefix: All components use
lfx-prefix (enforced by ESLint)
- CSS Layers: Organized layer system (
tailwind-base, primeng, tailwind-utilities) - PrimeNG Integration: Custom preset using LFX UI Core design system
- Tailwind CSS: Utility-first styling with PrimeUI plugin integration
- Custom Fonts: Google Fonts (Inter + Roboto Slab) with CSS variables
- PrimeNG Components: Direct integration of PrimeNG components with LFX theming
- Custom Styling: PrimeNG components styled with LFX UI Core design system
- Template Support: Full access to PrimeNG template functionality
- Type Safety: Full TypeScript support with PrimeNG type definitions
- ESLint: Angular 20 specific rules with import organization and naming conventions
- Prettier: Automatic code formatting with Tailwind class sorting
- TypeScript: Strict configuration with path mappings (
@app/*,@config/*) - Testing: Angular testing framework with comprehensive coverage
The application supports deployment with PM2:
- Node.js with PM2: Production process management with clustering and zero-downtime deployments
See the deployment documentation for detailed instructions.
The Architecture Overview is the jumping-off point. Each canonical subtopic owns one file:
- Angular Patterns — Zoneless change detection, signals, control-flow syntax
- Component Architecture — PrimeNG wrapper strategy, layouts, module organization
- Lens & Persona System —
LensService, persona detection,ProjectContextService - State Management — Signal-first patterns, signal↔RxJS bridging
- Styling System — Tailwind + PrimeUI, CSS layers, font/color tokens
- Drawer Pattern — Drawer components, lazy data, chart integration
- Lazy Loading & Preloading — Route splitting + custom preloading strategy
- Feature Flags — OpenFeature + LaunchDarkly wiring, signal-reactive reads
- Performance — Bundle management, SSR, runtime patterns
- Backend Architecture — Controller-Service pattern, directory layout, core services
- SSR Server — Express + Angular SSR pipeline, middleware order
- Authentication — Auth0 setup, selective auth middleware, AuthContext, M2M tokens
- Impersonation — Auth0 CTE flow, effective-identity helpers
- Rate Limiting —
express-rate-limitbudgets for/api,/public/api,/login - Observability — OpenTelemetry auto-instrumentation and custom spans
- Logging & Monitoring — Logger service, operation lifecycle, log levels
- Error Handling — Error class hierarchy, error-handler middleware
- Server Helpers — Validation type guards, pagination, URL validation
- Pagination —
page_tokencursor pattern,fetchAllQueryResourceshelper - AI Service — LiteLLM proxy, meeting agenda generation
- NATS Integration — Request/reply pattern, lazy connections
- Snowflake Integration — Singleton pool, query deduplication
- Public Meetings — Unauthenticated meeting access, M2M tokens
- Deployment — PM2 configuration and production deployment
- Package Architecture —
@lfx-one/sharedstructure, import patterns, conventions - Development Workflow — Turborepo, Yarn workspaces, build caching
- E2E Testing — Dual-architecture spec files,
data-testidnaming, Playwright setup - Testing Best Practices — Content vs. structural tests, robust locator patterns
- 📋 Architecture Overview — High-level map that links to every canonical doc above
- 📋 Architecture Navigation Hub — Same navigation from inside the
architecture/directory - 🧪 Testing Guide — Comprehensive E2E testing with Playwright
- 🤖 CLAUDE.md — Gotchas, conventions, and contextual rules for Claude Code sessions
Pre-commit hooks (via husky + lint-staged) auto-format and lint staged files, then run yarn format:check, yarn lint:check, and yarn check-types across the whole repo — you don't need to run yarn format manually. Before opening a PR, sanity-check the full build and any broader linting:
yarn lint # Auto-fix linting across the monorepo
yarn build # Verify the production build
yarn e2e # Run the Playwright E2E suite (when applicable)Commit messages must follow Angular conventional-commit format and are validated by commitlint (@commitlint/config-angular). Commits must be signed off (git commit -s) to satisfy DCO — see the Contributing Guide for accepted types and sign-off details.
Note: All source files must include the MIT license header. ./check-headers.sh validates locally and the pre-commit hook enforces it.
Angular 20 makes components, directives, and pipes standalone by default — do not pass --standalone, it's redundant and produces a deprecation warning:
ng generate component my-feature # standalone is the default
ng generate service my-service
ng generate guard my-guardFeature code can import primeng/* directly, but the preferred path for new code is the thin lfx-* wrapper components under apps/lfx-one/src/app/shared/components/. The wrappers give LFX One UI-library independence and a consistent signal-based API; several feature modules still import PrimeNG modules directly today, and migrating them to wrappers is an ongoing effort. When building a new feature, prefer the wrapper:
import { ButtonComponent } from '@app/shared/components/button/button.component';
import { CardComponent } from '@app/shared/components/card/card.component';
@Component({
selector: 'lfx-example',
imports: [ButtonComponent, CardComponent],
templateUrl: './example.component.html',
})
export class ExampleComponent {}<!-- example.component.html -->
<lfx-card header="Example Card">
<lfx-button label="Click me" severity="primary" (onClick)="handleClick()" />
</lfx-card>See the Component Architecture doc for the wrapper pattern in full and for guidance on when to add a new wrapper vs. import PrimeNG directly.
- Angular 20 with stable zoneless change detection
- Angular Signals for state management
- PrimeNG 20 UI component library with custom LFX preset
- Tailwind CSS v3 with PrimeUI plugin
- LFX UI Core design system integration
- Font Awesome Pro icons (via kits)
- Google Fonts (Inter + Roboto Slab)
- Express.js server with Angular 20 SSR
- Auth0 authentication with express-openid-connect
- Pino high-performance structured logging
- PM2 for production process management and clustering
Learn more about the technologies used:
- Turborepo Documentation - Monorepo build system
- Angular Documentation - Angular framework
- Angular Signals - Reactive programming with Signals
- PrimeNG Components - UI component library
- Tailwind CSS - Utility-first CSS framework
- LFX UI Core - Linux Foundation design system
- PM2 Documentation - Process manager for Node.js
Copyright The Linux Foundation and each contributor to LFX.
This project's source code is licensed under the MIT License. A copy of the license is available in LICENSE.
This project's documentation is licensed under the Creative Commons Attribution 4.0 International License (CC-BY-4.0). A copy of the license is available in LICENSE-docs.