Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AllianceBioversityCIAT/alliance-research-indicators-client/llms.txt

Use this file to discover all available pages before exploring further.

The Alliance Research Indicators client is a single Angular 19 SPA that acts as the browser tier of a multi-platform results federation. It communicates with three independent backend services, authenticates through AWS Cognito, and maintains a real-time presence channel via WebSocket. This page describes the system topology, the domain module split, and the conventions that govern every new piece of code.

System topology

┌────────────────────────────────────────────┐
│      Browser (Angular 19 SPA, this repo)   │
│                                            │
│  - PrimeNG 19 UI, Signals + RxJS, SCSS     │
│  - Lazy standalone routes                  │
│  - JWT + Cognito auth                      │
│  - WebSocket presence/notifications        │
│  - Analytics: Hotjar, Clarity, GA, BugHerd │
└──────────┬───────────────┬──────────────┬──┘
           │ HTTPS / REST  │ HTTPS / REST │ WSS
           │               │              │
┌──────────▼──┐   ┌────────▼──────┐  ┌────▼──────────┐
│  Main API   │   │ Text-Mining   │  │ File Manager  │
│  (NestJS)   │   │ microservice  │  │ microservice  │
└─────────────┘   └───────────────┘  └───────────────┘


   ┌─────────────┐         ┌───────────────────┐
   │   CLARISA   │         │ STAR / TIP / PRMS │
   │ (lists)     │         │ AICCRA (federation)│
   └─────────────┘         └───────────────────┘


              ┌───────────────┐
              │ AWS Cognito   │
              └───────────────┘

Backend services

ServiceEnvironment variablePurpose
Main API (NestJS)mainApiUrlAll core business logic — results CRUD, indicator catalog, user management, CLARISA controlled-list proxying, dashboards, and the authorization endpoints
Text-Mining microservicetextMiningUrlAI/NLP extraction and auto-fill for result form fields
File Manager microservicefileManagerUrlMultipart evidence file upload; returns a persistent URL that is stored on the result record (raw file bytes are never embedded in a result POST)
CLARISA provides the authoritative controlled vocabularies (institutions, countries, regions, SDGs, levers, impact areas, and more) via Main API proxy endpoints at /tools/clarisa/*. The federation platforms STAR, TIP, PRMS, and AICCRA are linked read-only from the client via deep-link URLs supplied by the Main API.

Folder layout

src/
├── environments/             # environment.ts / environment.dev.ts
├── styles/                   # Global SCSS: colors, fonts, tokens, PrimeNG overrides
└── app/
    ├── app.config.ts         # Providers: router, HTTP client, interceptors, service worker
    ├── app.routes.ts         # Lazy standalone routes and route guards
    ├── pages/                # Feature pages — one folder per route group
    │   ├── landing/          # Public landing surface
    │   ├── login/            # Cognito login entry
    │   ├── auth/             # OAuth callback handler
    │   ├── room/             # WebSocket real-time collaboration
    │   ├── oicr-download/    # Public OICR template download
    │   ├── dynamic-fields/   # Form-field configuration utility
    │   └── platform/         # Authenticated shell + child pages
    │       └── pages/
    │           ├── home/
    │           ├── about/
    │           ├── indicator/
    │           ├── result/         # Result detail — 11 metadata tabs
    │           ├── results-center/
    │           ├── search-a-result/
    │           ├── my-projects/
    │           ├── project-detail/
    │           ├── dashboard/
    │           ├── notifications/
    │           ├── profile/
    │           └── administration/center-admin/
    ├── shared/               # Cross-cutting code
    │   ├── components/       # Shared UI components
    │   ├── services/         # ApiService, CacheService, RolesService, etc.
    │   ├── interceptors/     # JWT, http-error, result
    │   ├── guards/           # rolesGuard, centerAdminGuard
    │   ├── interfaces/       # TypeScript shapes
    │   ├── pipes/            # format-date, s3-image-url, filter-by-text-with-attr
    │   ├── utils/            # Date/geo/map helpers
    │   ├── sockets/          # WebsocketService
    │   ├── types/            # Shared TS type helpers
    │   └── enums/            # Enum constants
    ├── theme/                # PrimeNG Aura preset (roartheme.ts)
    └── testing/              # Shared test mocks and harness

Domain modules

The app is organized by page domain under src/app/pages/, mirroring the spec taxonomy in docs/specs/.
ModulePathResponsibility
Platform shellpages/platform/Authenticated shell — navbar, sidebar, router outlet for children
Homepages/platform/pages/home/Logged-in dashboard / entry actions
Indicatorpages/platform/pages/indicator/, about-indicators/Indicator catalog and detail view
Resultspages/platform/pages/result/, results-center/, search-a-result/, load-result/Result lifecycle: create, edit (11 metadata tabs), search, hub
Projectspages/platform/pages/my-projects/, project-detail/Project portfolio and detail
Dashboardpages/platform/pages/dashboard/Aggregate analytics with Chart.js visualizations
Notificationspages/platform/pages/notifications/Real-time notification feed
Profilepages/platform/pages/profile/User settings and theme preferences
Aboutpages/platform/pages/about/Application information
Administration / Center Adminpages/platform/pages/administration/center-admin/Bulk upload and SDG management (requires role_id === 1 or center-admin composite check)
Authpages/login/, pages/auth/Cognito login entry and OAuth callback
Landingpages/landing/Public-facing surface
Real-timepages/room/WebSocket collaboration room
OICR Downloadpages/oicr-download/Public OICR template download
Dynamic Fieldspages/dynamic-fields/Form-field configuration utility
Sharedsrc/app/shared/Components, services, pipes, utilities, interfaces — referenced by all domain modules
Themesrc/app/theme/PrimeNG Aura preset (roartheme.ts); dark mode uses .dark-mode CSS class selector
Testingsrc/app/testing/Shared test mocks and harness; co-located .spec.ts files live next to their subjects

Angular 19 conventions

Standalone components only. No NgModules are used in this codebase (PRD constraint C-6). Every component, directive, and pipe is declared with standalone: true and imports what it needs directly. Lazy loading via loadComponent. Every authenticated route in app.routes.ts uses the loadComponent: () => import(...) pattern. This keeps the initial bundle small and respects the Angular budget constraints (initial bundle ≤ 2 MB warning / 3 MB error). View transitions. The router is configured with withViewTransitions() in app.config.ts, enabling CSS @view-transition animations between route changes where the browser supports them. Component selector prefix. All generated selectors use the app prefix (for example app-results-table), as configured in angular.json. Strict TypeScript. The tsconfig.json enables strict, noImplicitOverride, noPropertyAccessFromIndexSignature, noImplicitReturns, noFallthroughCasesInSwitch, and strictTemplates. Do not weaken these settings.

Path aliases

All imports inside src/ must use these aliases rather than deep relative paths. They are declared in tsconfig.json and must be kept in sync with jest.config.ts.
AliasResolves to
@public/*public/*
@envs/*src/environments/*
@pages/*src/app/pages/*
@platform/*src/app/pages/platform/*
@auth/*src/app/pages/auth/*
@landing/*src/app/pages/landing/*
@shared/*src/app/shared/*
@components/*src/app/shared/components/*
@services/*src/app/shared/services/*
@interfaces/*src/app/shared/interfaces/*
@interceptors/*src/app/shared/interceptors/*
@guards/*src/app/shared/guards/*
@sockets/*src/app/shared/sockets/*
@utils/*src/app/shared/utils/*
@ts-types/*src/app/shared/types/*

Application bootstrap

app.config.ts is the root provider configuration. The interceptor chain, router options, PrimeNG theme, and the app initializer are all registered here:
export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes, withViewTransitions()),
    provideHttpClient(withInterceptors([jWtInterceptor, httpErrorInterceptor, resultInterceptor])),
    importProvidersFrom(BrowserModule, BrowserAnimationsModule),
    provideAnimationsAsync(),
    providePrimeNG({
      theme: {
        preset: MyPreset,
        options: { darkModeSelector: '.dark-mode' }
      }
    }),
    provideAppInitializer(() => {
      // initializes tracking tools, validates cached tokens, and loads date-format config
    }),
    provideServiceWorker('ngsw-worker.js', {
      enabled: !isDevMode(),
      registrationStrategy: 'registerWhenStable:30000'
    })
  ]
};
The service worker is registered only in production builds (!isDevMode()). It waits 30 seconds after the app stabilizes before registering, avoiding interference with the initial load.

Build docs developers (and LLMs) love