December 2025
[IMPORTANT] Read Section 4 before running this repo for the first time.
More information on the backend can be found in this repo: CITIESair-node-server. This documentation mostly concerns the frontend application.
CITIESair is a network of heterogeneous air quality sensors for institutions in the UAE. It consists of 3 layers:
- Infrastructure: physical sensors
- Digital: this CITIESair frontend dashboard and backend system
- Social: partnerships with institutions and surrounding community
This documentation will only concern the CITIESair frontend dashboard.
Home page: at a glance statistics and map of all public outdoor sensors in the network
Dashboard page: showing for each institution current air quality measurements and visualizations
Raw dataset download dialog on the Dashboard page
Alert dialog on the Dashboard page
Dedicated TV Screen page, for displaying at locations such as the Campus Center and Dining Hall at NYU Abu Dhabi
CITIESair frontend is built with React.js and Material UI. It utilizes (mostly) Google Charts and (sometimes) Nivo Charts for generating interactive data visualizations for air quality datasets.
CITIESair frontend communicates with CITIESair backend server via RestAPI for:
- GET: getting current and historical air quality data, getting current user data, getting school metadata, getting email subscribers, getting alerts...
- POST/EDIT/DELETE: CRUD operations for alerts and email subscribers The full list of API endpoints is documented in API Documentation
CITIESair frontend is hosted on GitHub Pages. Section 2.4 explains how the deployment process works.
There are quite a lot of overlapping components between CITIESair and CITIES Dashboard (as Air Quality used to be a dataset within the much bigger CITIES Dashboard). The CITIES Dashboard repo with documentation can be found here.
-
App.jsx: serves as the root component for CITESair frontend web app, orchestrating the overall layout, routing, and theme management. It utilizes
BrowserRouterfromreact-router-domto map URLs to specific pages such asHomeandDashboard. A404page is also set up to handle unmatched routes. These routes are defined within theRoutescomponent, which renders the appropriate page based on the current URL path. -
API: contains metadata for API calls to backend and wrapper functions for API calls
-
Components: contains reusable components that are used across multiple pages and sections of CITIESair. These components enable functionalities like raw dataset downloading in CSV format, showing comment section, providing navigational aids like Speed Dial Buttons, etc.
-
ContextProviders: contains providers to share state across components, particularly for:
- managing navigation and dynamically updating the UI based on the current page or section
- managing metadata of charts
- loading Google library
- and more...
-
Graphs: contains the specific components responsible for rendering data visualizations using Google Charts and Nivo Charts.
-
hooks: contains all custom React Query hooks used for fetching real-time air quality data, alerts, and metadata from the backend. These hooks use React Query’s caching system (persistent caching in production, no caching in development) and support automatic refetching based on
staleTime. -
Pages: contains the main pages of the dashboard, including:
HomeDashboardandProject: for each school in the networkScreens: for glanceable TV air quality screensEmbeds: for embedding in other external apges404: for undefined routes in the application
-
Themes: contains the custom themes and color schemes used by the dashboard.
-
Utils: contains utility functions and helper methods used throughout the application. These utilities include an HTML-to-MUI parser, Google Analytics Tracker, etc.
REMARK: The React application is wrapped in
<StrictMode>, read more here, which will re-render components an extra time and runuseEffect()twice. Consequently, this makes most API calls to the backend duplicated if they are called inuseEffect(). This only happens in development mode (npm run dev) and not on the build (npm run build). In some circumstances, such asLogin, this might create some weird bugs on the backend (for example, two user sessions). Therefore, for the most accurate testing that reflects the real deployment production, build the application first before testing it.
-
Clone the repository
-
Create two
.envat the root:.env VITE_APP_ENV=development VITE_APP_BACKEND_URL=[SERVER DOMAIN] # VITE_APP_ENV=production # VITE_APP_BACKEND_URL=http://localhost:3001.env.production VITE_APP_ENV=production VITE_APP_BACKEND_URL=[SERVER DOMAIN]Vite will automatically uses the
.env.productionwhen building and deploying to Github Page. -
Install the dependencies:
npm install
CITIESair frontend can be run in several configurations, depending on the environment variables:
To switch configurations, comment/uncomment and choose the desired values in the .env file, then run npm run dev to apply the new environment settings.
| # | Frontend (VITE_APP_ENV) |
Backend (VITE_APP_BACKEND_URL) |
Comment |
|---|---|---|---|
| 1 | development | [SERVER DOMAIN] | [DEFAULT] Best used to avoid caching in frontend while using most up-to-date data from prod backend |
| 2 | development | localhost:3001 | Best used when developing both frontend and backend at the same time |
| 3 | production | localhost:3001 | Not sure when it'll ever be useful |
| 4 | production | [SERVER DOMAIN] | [ACTUAL PROD] Best used to verify everything works as intended before deploying to PROD (exact setup used for PROD) |
¹ development → no query caching
² production → uses query caching
If you want to run a stable build, run the below instead:
npm run build && serve -s dist
The stable build has the following characteristics:
- More optimized and faster compared to the dev application
- Google login works correctly (doesn't throw error when there is no error after a successful login)
- But 404 page doesn't work
CITIESair front-end application is deployed on GitHub in this repo. The domain (citiesair.com) is managed in name.com.
To deploy changes to the production website, double check for bugs and run npm run deploy in development environment.