Skip to content

Frontend Technology Reference

Detailed reference for every significant technology used in the Microtec ERP Angular micro-frontend platform.


Framework

Angular 17+

Version: 17.x (latest minor tracked)
Role: Primary UI framework for all 10 ERP web applications
Module system: NgModule-based (standalone: false) — no standalone components
Key features used:

  • Lazy-loaded feature modules (consumed by Module Federation host)
  • HttpClientModule with interceptors for auth and correlation IDs
  • Angular Router with child routes per micro-frontend
  • Reactive Forms (FormBuilder, FormGroup, FormControl)
  • Angular CDK — drag-and-drop, portal, overlay
typescript
// Standard feature module structure used across all micro-frontends
@NgModule({
  declarations: [InvoiceListComponent, InvoiceFormComponent],
  imports: [
    CommonModule,
    ReactiveFormsModule,
    PrimeNGModule,        // local barrel from shared-lib
    NgRxModule,           // StoreModule.forFeature, EffectsModule.forFeature
    AccountingRoutingModule,
  ],
})
export class AccountingModule {}

Why Angular 17?
The ERP was greenfield in 2023. Angular's strict TypeScript integration, strong DI, and NgRx ecosystem were a natural fit for a large enterprise app maintained by multiple teams.


Monorepo Tooling

Nx

Version: 17.x
Role: Monorepo build system for MFE-Apps/ workspace — task orchestration, computation caching, affected-change detection
Workspace root: MFE-Apps/

Key Nx features used:

FeatureUsage
affectedOnly rebuild/test apps affected by a commit
Computation cacheSkip re-running tasks whose inputs haven't changed
@nx/angular/module-federationGenerate and manage Module Federation webpack configs
Dependency graphnx graph — visualise app/lib relationships
Custom executorsDeploy to Azure SWA after build
bash
# Build only apps affected by changes since main
nx affected --target=build --base=main --head=HEAD

# Run all tests, using cache
nx run-many --target=test --all

# Visualise the dependency graph
nx graph

Why Nx?
10 Angular apps share 3 libraries. Nx eliminates full-workspace rebuilds on every commit by tracking which apps actually changed.


Micro-Frontend Architecture

Webpack Module Federation

Version: Webpack 5 (bundled with Angular CLI 17)
Role: Runtime integration of 9 remote Angular apps into the erp-home shell host
Integration: @nx/angular/module-federation wraps Webpack's ModuleFederationPlugin

Host/remote topology:

AppRolePortSWA Name (pattern)
erp-homeHost shell4401mic-erp-fr-{env}-home-swa
apps-accountingRemote4402mic-erp-fr-{env}-accounting-swa
apps-hrRemote4403mic-erp-fr-{env}-hr-swa
apps-financeRemote4404mic-erp-fr-{env}-finance-swa
apps-salesRemote4405mic-erp-fr-{env}-sales-swa
apps-purchaseRemote4406mic-erp-fr-{env}-purchase-swa
apps-inventoryRemote4407mic-erp-fr-{env}-inventory-swa
app-distributionRemote4408mic-erp-fr-{env}-distribution-swa
fixed-assetsRemote4409mic-erp-fr-{env}-fixed-assets-swa
bussiness-ownersStandalone4301mic-erp-fr-{env}-bo-swa

Each remote exposes exactly one entry point — ./Module. The host loads remote modules lazily via Angular Router.

typescript
// erp-home routing — lazy loading a remote module
{
  path: 'accounting',
  loadChildren: () => loadRemoteModule({
    remoteEntry: `${environment.accountingUrl}/remoteEntry.js`,
    remoteName: 'apps-accounting',
    exposedModule: './Module',
  }).then(m => m.AppModule),
},

Remote URL injection: Environment-specific URLs are stored in environment.ts files and injected at build time. No runtime URL resolution.


State Management

NgRx

Version: 17.x
Role: Centralised reactive state management — actions, reducers, effects, selectors
Used in: All 10 Angular apps

NgRx packages used:

PackagePurpose
@ngrx/storeImmutable state container
@ngrx/effectsSide effects (HTTP calls, notifications)
@ngrx/entityNormalised collection management
@ngrx/router-storeRoute state in the store
@ngrx/store-devtoolsRedux DevTools integration (dev only)
typescript
// Typical feature slice structure
// actions
export const loadInvoices = createAction('[Invoice] Load');
export const loadInvoicesSuccess = createAction(
  '[Invoice] Load Success',
  props<{ invoices: Invoice[] }>()
);

// reducer
export const invoiceReducer = createReducer(
  initialState,
  on(loadInvoicesSuccess, (state, { invoices }) =>
    invoiceAdapter.setAll(invoices, { ...state, loading: false }))
);

// effect
loadInvoices$ = createEffect(() =>
  this.actions$.pipe(
    ofType(loadInvoices),
    switchMap(() => this.invoiceService.getAll().pipe(
      map(invoices => loadInvoicesSuccess({ invoices })),
      catchError(err => of(loadInvoicesFailure({ error: err.message })))
    ))
  )
);

Internationalisation

@ngx-translate

Version: 15.x
Role: Runtime i18n — Arabic (RTL) and English (LTR) with hot-switching
Translation files: FrontApps/libs/shared-assets/i18n/

Supported locales:

LocaleDirectionFile
arRTLar.json
enLTRen.json
typescript
// Translate pipe in templates
<h1>{{ 'INVOICE.TITLE' | translate }}</h1>

// Service injection in components
constructor(private translate: TranslateService) {
  this.translate.use('ar'); // switch to Arabic at runtime
}

RTL support: Angular CDK's Directionality service is used with a CSS class on <body> (dir="rtl") applied by the shell app on language switch. PrimeNG's appendTo="body" overlays respect the dir attribute automatically.


UI Component Library

PrimeNG

Version: 17.x
Role: Primary enterprise UI component set — data tables, forms, dialogs, charts
Theme: Custom Microtec theme extending lara-light-blue
Used in: All Angular apps

Most-used components:

ComponentUse case
p-tableData grids with lazy loading, sort, filter, pagination
p-dialogModal forms and confirmations
p-dropdown / p-multiSelectSelect controls
p-calendarDate and date-range pickers
p-chartKPI dashboards (Chart.js wrapper)
p-toastNotification toasts
p-fileUploadDocument attachment upload
p-treeTableHierarchical data (chart of accounts)
typescript
// DataTable with lazy loading — standard pattern across all list pages
<p-table
  [value]="invoices$ | async"
  [lazy]="true"
  [paginator]="true"
  [rows]="20"
  [totalRecords]="total$ | async"
  (onLazyLoad)="store.dispatch(loadInvoices($event))">

CSS Framework

Bootstrap 5

Version: 5.x
Role: Grid system, utilities, and spacing — used alongside PrimeNG components
SCSS: Customised via _variables.scss overrides (colours, fonts, breakpoints)
Used in: Layout wrappers, page scaffolding, responsive grid

PrimeNG vs Bootstrap

PrimeNG provides interactive components (tables, forms, dialogs). Bootstrap provides the page grid, spacing utilities, and non-interactive layout. Both coexist without conflict — PrimeNG components are scoped with BEM class names; Bootstrap is utility-only.


Reactive Programming

RxJS

Version: 7.x (bundled with Angular 17)
Role: Async data streams — HTTP calls, store selectors, form value changes
Operators most used: switchMap, mergeMap, combineLatest, debounceTime, distinctUntilChanged, catchError, takeUntil

typescript
// Standard component pattern — auto-unsubscribe on destroy
export class InvoiceListComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();

  invoices$ = this.store.select(selectAllInvoices);
  loading$  = this.store.select(selectInvoicesLoading);

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Authentication (Frontend)

Keycloak-js

Version: 22.x
Role: OIDC client library — connects Angular apps to Keycloak
Realms used:

App typeKeycloak Realm
ERP apps (4401–4409)microtec
Business Owner (4301)businessowner

Integration: An APP_INITIALIZER factory runs keycloak.init() before the app bootstraps. All HTTP calls inject the Bearer token via a KeycloakBearerInterceptor.

typescript
// main.ts bootstrap with Keycloak
KeycloakService.init({
  url: environment.keycloakUrl,
  realm: environment.keycloakRealm,
  clientId: environment.keycloakClientId,
  initOptions: { onLoad: 'login-required', checkLoginIframe: false },
})

Testing

Jest

Version: 29.x
Role: Unit and component testing runner
Configuration: Per-app jest.config.ts files generated by Nx

Cypress

Version: 13.x
Role: End-to-end browser automation tests
Used in: Accounting and HR apps (critical user journeys)

Angular Testing Library

Version: 15.x
Role: Behaviour-driven component tests — queries by role, label, text rather than CSS selectors


Build Tooling

Angular CLI

Version: 17.x (via Nx)
Builder: @nx/angular:webpack-browser (Module Federation build)
Output: Static assets (index.html, chunked JS, CSS, assets)

Environment files:

FileEnvironment
environment.tsDevelopment (local)
environment.stage.tsStage
environment.cloud.tsCloud (preprod/uat)
environment.prod.tsProduction

Shared Libraries

LibraryPathPurpose
shared-libFrontApps/libs/shared-libCommon components, services, pipes, directives
shared-assetsFrontApps/libs/shared-assetsi18n JSON files, images, icons
microtec-auth-libFrontApps/libs/microtec-auth-libKeycloak wrapper, token management
apps-shared-libFrontApps/libs/apps-shared-libERP-domain shared models and helpers

Not in Module Federation shared scope

These libraries are bundled inside each remote app rather than being declared in the Module Federation shared config. This avoids version-mismatch runtime errors at the cost of duplicated bytes. Each remote is independently deployable.


Internal Documentation — Microtec Platform Team