Deployment Guide
How to build and deploy the AquaGen apps to Firebase Hosting.
There are two ways to deploy:
| Command | Style | Use when |
|---|---|---|
npm run deploy | Guided (menu-driven) | Almost always — it builds, sets env flags, and deploys for you |
npm run deploy:app | Manual (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
- Firebase CLI installed globally:
npm install -g firebase-tools
firebase --version - Logged in to the Firebase account that has access to the project:
firebase login
firebase projects:list - The project is
aquagen-f6d24(set in.firebaserc). No extra config needed — the deploy scripts handlefirebase.jsonfor 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.
| App | Purpose | dev target | prod target |
|---|---|---|---|
production | Main Aquagen app | pre-prod | aquagen |
demo | Demo build | — | demo |
lakepulse | Lake Pulse | lakepulse-dev | lakepulse |
uwms | Aqua Recycle | aquarecycle-dev | aquarecycle |
rwi | Rainwater (RWI) | rwi-dev | rwi |
There are also several shared test targets that all serve the production
build: test1–test7, test9, plus uat and dev. (test8 serves the
demo build.) These are for manual QA deploys via deploy:app.
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.
Guided deploy — npm run deploy (recommended)
npm run deploy
Follow the prompts:
- Pick an app — Aquagen, Lake Pulse, Aqua Recycle, RWI, Demo, or All (All = Lake Pulse + Aqua Recycle + RWI).
- Pick an environment —
devorprod, where the app supports both. - 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.jsonat the fresh build and runsfirebase deploy --only hosting:<target> - Reverts the constants and restores
firebase.jsonwhen finished — even if the deploy fails — so your working copy is always left clean
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:
- Checks the build exists in
dist/apps/<app-name>/(errors if you forgot to build) - Backs up
firebase.json, rewrites its public path to the build - Runs
firebase deploy --only hosting:<hosting-target> - 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), SPArewrites, and securityheaders..firebaserc— maps each target name to the live Firebase site it deploys to (e.g.aquagen→ theaquagensite,demo→aquagen-demo,lakepulse→lakepulse-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:
- Firebase Console → Hosting
- Select the site → Release history
- 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
- Validation & Troubleshooting — smoke-test a deploy and debug when it breaks
- Commands Reference — every script explained
- Components — the shared UI library
- Utilities & Helpers — shared helpers and services