Skip to main content

Deployment Guide

How to build and deploy the AquaGen apps to Firebase Hosting.

There are two ways to deploy:

CommandStyleUse when
npm run deployGuided (menu-driven)Almost always — it builds, sets env flags, and deploys for you
npm run deploy:appManual (you pass app + target)Deploying to a specific target (e.g. a testN env) or scripting

See the Commands Reference for the full script list.


Prerequisites

  1. Firebase CLI installed globally:
    npm install -g firebase-tools
    firebase --version
  2. Logged in to the Firebase account that has access to the project:
    firebase login
    firebase projects:list
  3. The project is aquagen-f6d24 (set in .firebaserc). No extra config needed — the deploy scripts handle firebase.json for you.

The apps and their hosting targets

Each app builds into dist/apps/<app-name>/ and deploys to one or more Firebase hosting targets. Targets are defined in firebase.json; the target → live site mapping lives in .firebaserc.

AppPurposedev targetprod target
productionMain Aquagen apppre-prodaquagen
demoDemo builddemo
lakepulseLake Pulselakepulse-devlakepulse
uwmsAqua Recycleaquarecycle-devaquarecycle
rwiRainwater (RWI)rwi-devrwi

There are also several shared test targets that all serve the production build: test1test7, test9, plus uat and dev. (test8 serves the demo build.) These are for manual QA deploys via deploy:app.

note

The public path you see in firebase.json is a placeholder — both deploy scripts rewrite it to the correct dist/apps/<app> at deploy time and restore the file afterwards.


npm run deploy

Follow the prompts:

  1. Pick an app — Aquagen, Lake Pulse, Aqua Recycle, RWI, Demo, or All (All = Lake Pulse + Aqua Recycle + RWI).
  2. Pick an environmentdev or prod, where the app supports both.
  3. Confirm the summary.

The script then, for each selected app:

  • Sets the build flags in libs/shared/src/constants/constants.js (analyticsEnv, currentEnv, isPreProd) to match the chosen environment
  • Builds it: nx build <app> --skip-nx-cache
  • Points firebase.json at the fresh build and runs firebase deploy --only hosting:<target>
  • Reverts the constants and restores firebase.json when finished — even if the deploy fails — so your working copy is always left clean
Environment rules the menu enforces

Aquagen (production) only deploys to dev (pre-prod). Demo only deploys to its prod target (demo). Lake Pulse, Aqua Recycle, and RWI support both.


Manual deploy — npm run deploy:app

Use this when you want to target a specific hosting target (for example a testN QA environment) or deploy without the menu. You build first, then deploy:

# 1. Build the app you want to ship
npm run build # production (shortcut for build:app production)
# or
npm run build:app demo # any other app

# 2. (Optional) preview the build locally on http://localhost:3000
npm run serve:build demo

# 3. Deploy: npm run deploy:app <app-name> <hosting-target>
npm run deploy:app production uat
npm run deploy:app production test5
npm run deploy:app demo test8

What it does:

  1. Checks the build exists in dist/apps/<app-name>/ (errors if you forgot to build)
  2. Backs up firebase.json, rewrites its public path to the build
  3. Runs firebase deploy --only hosting:<hosting-target>
  4. Restores the original firebase.json

Unlike npm run deploy, this does not build for you and does not touch the environment constants — you are fully in control.


firebase.json and .firebaserc

  • firebase.json — one entry per hosting target. Each entry defines the build folder (public), SPA rewrites, and security headers.
  • .firebaserc — maps each target name to the live Firebase site it deploys to (e.g. aquagen → the aquagen site, demoaquagen-demo, lakepulselakepulse-aquagen).

SPA routing

Every target rewrites all paths to index.html, so client-side routing works on refresh:

"rewrites": [{ "source": "**", "destination": "/index.html" }]

Security headers

Every target ships a full set of security headers, including:

X-Frame-Options, Content-Security-Policy, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, Strict-Transport-Security, Permissions-Policy, X-Permitted-Cross-Domain-Policies, Cross-Origin-Resource-Policy, Cross-Origin-Opener-Policy, and Cache-Control.

If you add a new external service (API, font host, WebSocket, iframe), you will likely need to add its origin to the Content-Security-Policy for every target in firebase.json.


Rollback

Firebase keeps a release history per site, so the fastest rollback is through the console:

  1. Firebase Console → Hosting
  2. Select the site → Release history
  3. Find the last good release → Rollback

To redeploy a known-good commit instead:

git checkout <good-commit>
npm run build
npm run deploy:app production <target>
git checkout - # back to your branch

Troubleshooting

"Build directory ... does not exist"

You tried to deploy before building. Build first:

npm run build:app <app-name>
ls dist/apps/<app-name> # confirm it's there

"Hosting target ... not found in firebase.json"

The target name is misspelled or not defined. Check the target table above, or list them:

node -e "console.log(require('./firebase.json').hosting.map(h=>h.target).join('\n'))"

"No user signed in" / 403 permission errors

Run firebase login. If you're logged in but still get 403, your account needs the Firebase Hosting Admin role on the aquagen-f6d24 project — ask a project admin.

404 when refreshing a route

This means the SPA rewrites rule is missing for that target. Confirm the target has the "source": "**" → "/index.html" rewrite in firebase.json.

Old version still showing

Browser or CDN cache. Hard-refresh (Cmd/Ctrl+Shift+R), and give the CDN a few minutes to propagate.


Next Steps