Skip to main content

Deployment & Environments

This page explains which app is deployed where, and how. It is the source of truth for the app-to-environment mapping. For the general Firebase mechanics and security headers, see the existing Development → Deployment Guide.


Two separate deploy surfaces

The apps are deployed through two independent paths that do not share configuration.

SurfaceWhat it deploysTriggered byWhere
Azure (CI)The production appPush to main (or manual dispatch)Azure Web App aquagen, Production slot
Firebase (scripts)Any appA developer running a scriptAll the Firebase sites below
The real production release is on Azure

Pushing to main builds production and deploys it to the Azure Web App aquagen. The Firebase aquagen site is separate. Do not assume Firebase is production for the main app.

The CI workflow lives at .github/workflows/production_aquagen.yml. An older, disabled version (production_aquagen_old.yml.disabled) is kept for reference only — see Legacy & Deprecated.


Where each product is deployed

Each product has a customer-facing production URL and one or more internal dev / pre-prod URLs. The dev and pre-prod sites run the same build as the customer-facing app — they are internal replicas used to catch issues before a release — so they are grouped together below.

ProductProduction (customer-facing)Dev / Pre-prod (internal replica)Analytics recorded
AquaGen (production)web.aquagen.co.in (Azure)pre-prod-aquagen.web.app · dev-aquagen.web.appProduction only
AquaRecycle (uwms)aquarecycle-aquagen.web.appaquarecycle-dev.web.appProduction only
Lakepulse (lakepulse)lakepulse-aquagen.web.applakepulse-dev.web.appProduction only
AquaRain (rwi)rwi-aquagen.web.apprainwater-dev.web.appProduction only
AquaGen Demo (demo)aquagen-demo.web.app (sales/demo, mock data)sales build
Dev / pre-prod = internal replicas, no analytics

The dev and pre-prod sites are exact replicas of the customer-facing product, hosted on an internal URL. They exist so the team can verify a release and reproduce issues without polluting product analytics — analytics (GA4, Mixpanel, Firebase) is recorded only on the production/customer-facing build. This is enforced by the constants.analyticsEnv flag (see Environment flags): the analytics service skips recording whenever that flag is truthy, and deploy.sh sets it truthy for every dev deploy.

The Firebase URLs above are the auto-provisioned https://<site-id>.web.app addresses (each site is also reachable at <site-id>.firebaseapp.com); custom domains may also front them. The full target → site mapping is in the hosting map below.


Firebase hosting map

Every Firebase deploy points a hosting target at a build output (dist/apps/<app>) and pushes it to a site. The mapping comes from two files:

  • .firebaserc — hosting target → Firebase site id
  • firebase.json — hosting target → build output (public)
Firebase targetServes app buildFirebase site idPurpose
aquagenproductionaquagenAquaGen prod (Firebase; real prod is Azure)
pre-prodproductionpre-prod-aquagenAquaGen pre-prod
devproductiondev-aquagenAquaGen dev
uatproductiontestuatAquaGen UAT
test1test7, test9productiontestN-aquagenAquaGen test servers
test8demo ⚠️test8-aquagenServes the demo build
demoproduction ⚠️aquagen-demoServes the production build
aquarecycleuwmsaquarecycle-aquagenAquaRecycle prod
aquarecycle-devuwmsaquarecycle-devAquaRecycle dev
lakepulselakepulselakepulse-aquagenLakepulse prod
lakepulse-devlakepulselakepulse-devLakepulse dev
rwirwirwi-aquagenAquaRain prod (defined twice ⚠️)
rwi-devrwirainwater-devAquaRain dev

Each site is served at https://<site-id>.web.app (and https://<site-id>.firebaseapp.com) — e.g. the dev target's dev-aquagen site is dev-aquagen.web.app. The customer-facing product URLs are collected in Where each product is deployed above.

See Known anomalies for the ⚠️ items.


The deploy scripts

Two bash scripts drive Firebase deploys (see Commands Reference for the npm mapping).

npm run deploydeploy.sh (interactive)

The main tool. It shows a menu of products and deploys the ones you pick:

Menu choiceApp builtDeploys to
1) Aquagenproductionpre-prod (dev only)
2) Lake Pulselakepulselakepulse-dev or lakepulse
3) Aqua Recycleuwmsaquarecycle-dev or aquarecycle
4) RWIrwirwi-dev or rwi
5) Demodemodemo target
6) All appsalleach to its targets

For each choice it builds the app, temporarily repoints firebase.json, deploys, and restores everything.

npm run deploy:app <app> <target>deploy-app.sh (non-interactive)

A single, scriptable deploy. It does not build — you must build first. Example:

npm run build:app -- demo      # produces dist/apps/demo
npm run deploy:app demo test8 # deploys that build to the test8 site

Both scripts use the same trick: back up firebase.json, rewrite the target's public to dist/apps/<app>, run firebase deploy --only hosting:<target>, then restore the original firebase.json.


Environment flags (constants.js)

The interactive deploy.sh also flips a few flags in libs/shared/src/constants/constants.js before building, then reverts them afterwards:

ConstantProd defaultWhat deploy.sh changes it to
constants.analyticsEnvdevelopment — evaluates to false in a production build, so analytics is recordedtrue for dev deploys, which turns analytics off (the analytics service does if (analyticsEnv) return;, i.e. it skips recording whenever this is truthy)
constants.currentEnvconstants.env.prodconstants.env.demo for the demo app
constants.isPreProdfalsetrue for dev deploys
analyticsEnv reads backwards

It behaves as a "disable analytics" flag: truthy = analytics off. That is why the customer-facing production builds (where it is false) record analytics, while every dev/pre-prod replica (where deploy.sh sets it true) does not.

Because the constants file is edited per build, both npm run build and the deploy scripts use --skip-nx-cache — otherwise Nx could serve a cached build with the wrong environment baked in.


Build & cache notes

  • Bundler: Rspack (via @nx/rspack). Nx infers each app's build/serve targets from rspack.config.js.
  • Remote cache: Nx Cloud is active (nxCloudId in nx.json). The installed @nx/azure-cache package is not wired in — see Legacy & Deprecated.
  • --skip-nx-cache is used by build, build:app, and the deploy scripts to force fresh, environment-correct builds.

Known anomalies

These are real quirks in the current config. They are documented here (and collected in Legacy & Deprecated) so they are not mistaken for bugs in your own setup.

  • demo and test8 public paths look swapped in firebase.json. The committed test8 public is dist/apps/demo and demo's is dist/apps/production. This only affects a manual firebase deploy — the deploy scripts rewrite public to the app being built, and deploy.sh's Demo choice publishes the demo build to the demo target (see the table above).
  • rwi is defined twice in firebase.json. Both entries point at dist/apps/rwi, so content is the same, but two hosting configs sharing one target can make firebase deploy --only hosting:rwi ambiguous. Worth de-duplicating.
  • .github/workflows references a missing file. nx.json lists .github/workflows/ci.yml as a shared input, but that file does not exist.
  • Firebase aquagen site is not the real prod for the main app — Azure is (see the top of this page).

Next steps