Applications Overview
The AquaGen codebase is one Nx monorepo that builds five separate web applications. They share the same libraries but ship as different products, to different customers, at different URLs.
This page is the map. Read it first, then dive into Products, Standalone Apps, or Deployment & Environments.
Every app is a plain React single-page app built with Rspack. They are not wired together with Module Federation — that is turned off everywhere. See Module Federation Status for details.
The five apps at a glance
| App folder | Ships as | Role | Build output |
|---|---|---|---|
production | AquaGen | Main product — the full platform | dist/apps/production |
demo | AquaGen Demo | Sales/demo build of the main product | dist/apps/demo |
uwms | AquaRecycle | Standalone product (urban water / recycle) | dist/apps/uwms |
lakepulse | Lakepulse | Standalone product (lake monitoring) | dist/apps/lakepulse |
rwi | AquaRain | Standalone product (rainwater) | dist/apps/rwi |
Each real app also has a matching end-to-end test app (production-e2e, demo-e2e, uwms-e2e, lakepulse-e2e, rwi-e2e). Those only run Cypress/Playwright tests and never ship.
Main app vs. standalone apps
There are two kinds of app in the repo.
The main app (production, and its clone demo)
production is the full AquaGen platform. It carries every feature — dashboards, all monitoring types, leadership, SCADA, HMI, energy, all the water indices, and more. demo is a near-identical copy used for sales demos (it drops real login and adds a couple of demo-only pages like trueCost).
The main app decides what to show at runtime, based on the logged-in account's permissions. It uses the generic navigation helper and shows the whole route table.
Standalone apps (uwms, lakepulse, rwi)
Each standalone app is a single, focused product built from a small slice of the same libraries:
- AquaRecycle (
uwms) is built around the Used Water Index (uwi). - Lakepulse (
lakepulse) is built around lake monitoring (ilm). - AquaRain (
rwi) is built around the Rainwater Monitoring (rwi).
A standalone app has its own smaller route table, its own navigation helper, and tells the shared store which product it is. The mechanics of how that works — and how the pattern has evolved — are explained in Standalone Apps.
It is three small things in the app's startup code: it calls createValidateLogin(<AppNavigationHelper>), it passes standaloneAppName="<app>" into the shared store, and it hands its own navInstance to the layout. Nothing is loaded remotely. See Standalone Apps.
How the apps compare
| production | demo | uwms | lakepulse | rwi | |
|---|---|---|---|---|---|
| Product name | AquaGen | AquaGen Demo | AquaRecycle | Lakepulse | AquaRain |
| Scope | Full catalog | Full catalog + demo pages | uwi vertical | ilm (lake) vertical | rwi vertical |
| Startup pattern | Legacy (double-nested) | Legacy (double-nested) | Current (clean) | Current (cleanest) | Hybrid (half-migrated) |
| Login (MSAL) | Yes | No | Yes | Yes | Yes |
| Navigation helper | Generic (implicit) | Generic (implicit) | UwmsNavigationHelper | LakePulseNavigationHelper | RwiNavigationHelper |
| Reports library | reportsV2 | reportsV2 | reports (v1) | reports (v1) | reports (v1) |
| Route count (approx.) | ~47 (superset) | ~46 | ~22 | ~14 (smallest) | ~20 |
| Dev server port | 4200 | 4200 | 4200 | 4200 | 4202 |
"Startup pattern" is explained in Standalone Apps → How the pattern evolved. In short, production and demo still use the old pattern, uwms and lakepulse use the clean new one, and rwi is mid-migration.
Naming conventions
The repo uses a few naming systems that are easy to confuse. Keep this table handy.
| Thing | Convention | Examples |
|---|---|---|
| App folder / Nx project | short lowercase | production, demo, uwms, lakepulse, rwi |
Product / brand name (the <title>) | marketing name | AquaGen, AquaRecycle, Lakepulse, AquaRain |
| Library import path | @aquagen-mf-webapp/<lib> | @aquagen-mf-webapp/shared, @aquagen-mf-webapp/monitoring |
| Firebase hosting target | environment/product | dev, pre-prod, aquarecycle, rwi-dev |
| Firebase site id | <name>-aquagen (mostly) | dev-aquagen, aquarecycle-aquagen, rainwater-dev |
| Navigation helper | <App>NavigationHelper | UwmsNavigationHelper, RwiNavigationHelper |
The uwms app ships as the AquaRecycle product and is built around the uwi (Used Water Index) library. The rwi app ships as AquaRain and is built around the rwi library. The <title> in each app's index.html is the source of truth for the product name.
The @aquagen-mf-webapp/ import scope is historical — "mf" stands for Module Federation, which the project was originally built around but no longer uses. The scope name stayed even though the architecture changed.
Where things live
aquagen_web_appp/
├── apps/
│ ├── production/ # AquaGen (main) → dist/apps/production
│ ├── demo/ # AquaGen Demo → dist/apps/demo
│ ├── uwms/ # AquaRecycle → dist/apps/uwms
│ ├── lakepulse/ # Lakepulse → dist/apps/lakepulse
│ ├── rwi/ # AquaRain → dist/apps/rwi
│ └── *-e2e/ # test-only apps (never shipped)
├── libs/ # shared + feature libraries (see Architecture → Libraries)
├── bash-scripts/ # build & deploy scripts (see Deployment & Environments)
├── firebase.json # Firebase hosting config (target → build output)
├── .firebaserc # Firebase hosting targets → site ids
└── .github/workflows/ # CI/CD (Azure deploy for production)
Inside each app the important startup files are:
| File | Purpose |
|---|---|
src/main.jsx | One line: import('./bootstrap'). A leftover async boundary from the old Module Federation setup. |
src/bootstrap.jsx | The real entry point — sets up providers, login, and the router. |
src/app/app.jsx | The app shell. In the current pattern it is just the router; in the legacy pattern it also re-declares providers. |
src/routes/routes.js | The app's route table. |
rspack.config.js | The build config Nx actually uses (output path, library aliases). |
rspack.config.prod.js | Not used — dead config, see Legacy & Deprecated. |
Next steps
- Products — what each product is and who it is for.
- Standalone Apps — the pattern that makes
uwms,lakepulse, andrwiwork. - Module Federation Status — why the apps are plain SPAs today.
- Deployment & Environments — which app is deployed where, and how.
- Legacy & Deprecated — everything in the repo that is no longer used.
- Architecture → Libraries — the shared libraries every app is built from.