# Project export: AirMigo

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Helping respiratory patients with real-time AI-powered air quality monitoring for better health management
- Devpost: https://devpost.com/software/tbd-nd1ov6
- GitHub: https://github.com/qtrunguyen/AirMigo
- Demo: https://airmigo.vercel.app/
- Team: 2 GitHub contributor(s) — Trung Nguyen (19 commits), Nam Khanh Nguyen (16 commits)

## Devpost submission (written by the team)

### Inspiration

Our inspiration came from the growing concern over air pollution and its detrimental effects on individuals with respiratory conditions like asthma and allergies. Most available AQI data only updates hourly, making it difficult for people to track real-time changes. We wanted to create a solution that provides real-time, personalized, and actionable alerts, helping individuals proactively manage their health and stay safe.

### What it does

The application collects real-time data from multiple sources, including traffic, pollens level and air quality index (AQI) data. It analyzes the air quality in the user's surrounding area, visualizes on the map, and provides real-time updates. Based on the user’s specific health conditions, such as asthma or allergies, the app sends personalized notifications with warnings and recommendations, helping users to take appropriate action to protect their health.

### How we built it

We first collect real-time data from multiple third-party APIs, including Google Maps API, to gather information such as traffic, air quality, and pollen levels. Then, we use SingleStore DB for low-latency queries, allowing to query and update data in real-time. We also use Groq API to call the Llama 3 model. With the metadata about the surroundings and user's health condition, the LLM model generate personalized notification messages. We use React for frontend and Node for backend development. Lastly, we deploy it on Vercel.

### Challenges we ran into

Data Integration: Collecting real-time data from multiple sources and ensuring consistent, accurate updates was quite a challenge. Familiarizing with SDKs: We spent considerable time getting familiar with the SingleStore SDK and Groq SDK. API Rate Limits: Handling rate limits from third-party APIs posed a challenge, especially for a real-time application that requires frequent updates.

### Accomplishments we're proud of

We successfully built a working product with core features, including real-time data updates, personalized LLM-generated messages, and map visualization. We also talked to a bunch of cool people, from hackers to sponsors. Implemented and learned a handful of new technologies.

### What we learned

We learned a lot about the architecture behind real-time applications, particularly in handling large volumes of data and optimizing for low latency. In the future, we could explore using a Kafka queue to streamline real-time data even further. We gained insights into how AI models like Llama 3 can be used to generate personalized and meaningful notifications. BIGGEST LESSON: SLEEP IS IMPORTANT !!! What's Next for AirMigo We aim to expand the app’s capabilities to account for a wider range of health conditions, such as COPD, bronchitis, or heart conditions, to make the app more versatile. We plan to integrate additional real-time data sources, such as weather conditions, humidity levels, and wildfire smoke, to provide even more accurate real-time air quality reports. In case of having more resources (more API rates), we want to increase the geographical radius for data collection and allow for more frequent updates and larger coverage areas. Let users go to a destination via a path with least air resistance. Cleaner and more intuitive UI

## README (from the GitHub repository)

![Demo](demo.png)
# AirMigo (Cal Hacks 11.0)
Helping respiratory patients with real-time AI-powered air quality monitoring for better health management

## Inspiration
Our inspiration came from the growing concern over air pollution and its detrimental effects on individuals with respiratory conditions like asthma and allergies. Most available AQI data only updates hourly, making it difficult for people to track real-time changes. We wanted to create a solution that provides real-time, personalized, and actionable alerts, helping individuals proactively manage their health and stay safe.

## What it does
The application collects real-time data from multiple sources, including traffic and air quality index (AQI) data. It analyzes the air quality in the user's surrounding area, visualizes the hotspots on the map, and provides real-time updates. Based on the user’s specific health conditions, such as asthma or allergies, the app sends personalized notifications with warnings and recommendations, helping users to take appropriate action to protect their health.

## How we built it
We first collect real-time data from multiple third-party APIs, including Google Maps API, to gather information such as traffic, air quality, and pollen levels. Then, we use SingleStore DB for low-latency queries, allowing to query and update data in real-time. We also use Groq API to call the Llama 3 model. With the metadata about the surroundings and user's health condition, the LLM model generate personalized notification messages. Last but not least, we use React for frontend and Node for backend.

## Challenges we ran into
- Data Integration: Collecting real-time data from multiple sources and ensuring consistent, accurate updates was quite a challenge.
- Familiarizing with SDKs: We spent considerable time getting familiar with the SingleStore SDK and Groq SDK.
- API Rate Limits: Handling rate limits from third-party APIs posed a challenge, especially for a real-time application that requires frequent updates.

## Accomplishments that we're proud of
- We successfully built a working product with core features, including real-time data updates, personalized LLM-generated messages, and map visualization for air quality hotspots.
- We also managed to achieved a moderately low-latency updates ( around 1s to send new updates to users).

## What we learned
- We learned a lot about the architecture behind real-time applications, particularly in handling large volumes of data and optimizing for low latency. In the future, we could explore using a Kafka queue to streamline real-time data even further.
- We gained insights into how AI models like Llama 3 can be used to generate personalized and meaningful notifications.

## What's Next for AirMigo
- We aim to expand the app’s capabilities to account for a wider range of health conditions, such as COPD, bronchitis, or heart conditions, to make the app more versatile.
- We plan to integrate additional real-time data sources, such as weather conditions, humidity levels, and wildfire smoke, to provide even more accurate real-time air quality reports.
- In case of having more resources (more API rates), we want to increase the geographical radius for data collection and allow for more frequent updates and larger coverage areas.



## Detected evidence (automated analysis)

Indexed codebase: 23 recognized source files, 33 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (28 of 28)

```
.gitignore
backend/core/auth/login.js
backend/core/auth/signup.js
backend/index.js
backend/lib/airquality.js
backend/lib/fetchAndJoin.js
backend/lib/fetchTrafficData.js
backend/lib/generateWarning.js
backend/lib/singlestoreClient.js
backend/package.json
frontend/.gitignore
frontend/eslint.config.js
frontend/index.html
frontend/package.json
frontend/README.md
frontend/src/App.css
frontend/src/App.jsx
frontend/src/GMap.jsx
frontend/src/index.css
frontend/src/main.jsx
frontend/src/Nav.jsx
frontend/src/Overlay.jsx
frontend/src/Panel.jsx
frontend/src/PoiMarkers.jsx
frontend/src/Popup.jsx
frontend/vite.config.js
LICENSE
README.md
```

### Dependencies

- backend/package.json: @singlestore/client@^0.0.41, axios@^1.7.7, bcrypt@^5.1.1, cors@^2.8.5, dotenv@^16.4.5, express@^4.21.1, groq-sdk@^0.7.0, mysql2@^3.11.3
- frontend/package.json: @eslint/js@^9.11.1, @react-google-maps/api@^2.20.3, @types/react@^18.3.10, @types/react-dom@^18.3.0, @vis.gl/react-google-maps@^1.3.0, @vitejs/plugin-react@^4.3.2, axios@^1.7.7, eslint@^9.11.1, eslint-plugin-react@^7.37.0, eslint-plugin-react-hooks@^5.1.0-rc.0, eslint-plugin-react-refresh@^0.4.12, globals@^15.9.0, react@^18.3.1, react-dom@^18.3.1, react-icons@^5.3.0, vite@^5.4.8

### Recent commits (newest first)

- Update README.md
- Add files via upload
- install google maps api
- Update PoiMarkers.jsx
- small changes
- Add circle around pin
- Merge pull request #6 from qtrunguyen/trung
- fix data queries
- add logo
- logo link test
- Update frontend new
- Major UI Update
- Drag and drop coord update
- Update README.md
- Merge pull request #5 from qtrunguyen/trung
- add users health condition
- Merge branch 'main' of https://github.com/qtrunguyen/AirMigo
- create groq endpoint
- Update README.md
- make a template for popup

## Key source files (fetched from GitHub, selected and truncated for size)

### backend/package.json

```
{
  "name": "blessyou",
  "version": "1.0.0",
  "description": "Cal Hacks 11.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@singlestore/client": "^0.0.41",
    "axios": "^1.7.7",
    "bcrypt": "^5.1.1",
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.21.1",
    "groq-sdk": "^0.7.0",
    "mysql2": "^3.11.3"
  }
}

```

### frontend/package.json

```
{
  "name": "frontend",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@react-google-maps/api": "^2.20.3",
    "@vis.gl/react-google-maps": "^1.3.0",
    "axios": "^1.7.7",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-icons": "^5.3.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.11.1",
    "@types/react": "^18.3.10",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.2",
    "eslint": "^9.11.1",
    "eslint-plugin-react": "^7.37.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.12",
    "globals": "^15.9.0",
    "vite": "^5.4.8"
  }
}

```

### backend/index.js

```javascript
import express from 'express';
import dotenv from 'dotenv';
import cors from 'cors';

import { getCurrentAir } from './lib/airquality.js';
import { fetchTrafficDensity } from './lib/fetchTrafficData.js';
import { fetchAndJoin } from './lib/fetchAndJoin.js';
import { generateWarning } from './lib/generateWarning.js';

const app = express()
app.use(cors({
    origin: ["http://localhost:5173", "https://airmigo.vercel.app"]
}))
app.use(express.json())

app.post('/groq', async (req, res) => {
    let {latitude, longitude, conditions} = req.body
    await getCurrentAir(latitude, longitude);
    await fetchTrafficDensity(latitude, longitude);
    res.send(await generateWarning(latitude, longitude, conditions))
})

const port = 4000;
app.listen(port, () => {
    console.log('Listening on port ' + port)
})

```

### frontend/src/main.jsx

```javascript
import React, { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

```

### frontend/src/App.jsx

```javascript
import React, { useState } from "react";
import "./App.css";

import Overlay from "./Overlay";
import Nav from "./Nav";
import GMap from "./GMap";

function App() {

  return (
    <>
      <Overlay></Overlay>
      <Nav ></Nav>
      <GMap ></GMap>
    </>
  );
}

export default App;

```

### frontend/vite.config.js

```javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
})

```

### frontend/index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/assets/AirMigoLogo.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AirMigo</title>
  </head>
  <body class="loading">
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

```

### frontend/eslint.config.js

```javascript
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
  { ignores: ['dist'] },
  {
    files: ['**/*.{js,jsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
      parserOptions: {
        ecmaVersion: 'latest',
        ecmaFeatures: { jsx: true },
        sourceType: 'module',
      },
    },
    settings: { react: { version: '18.3' } },
    plugins: {
      react,
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...js.configs.recommended.rules,
      ...react.configs.recommended.rules,
      ...react.configs['jsx-runtime'].rules,
      ...reactHooks.configs.recommended.rules,
      'react/jsx-no-target-blank': 'off',
      'react-refresh/only-export-components': [
        'warn',
        { allowConstantExport: true },
      ],
    },
  },
]

```

### frontend/src/Overlay.jsx

```javascript
import React from "react";
import { BiLoaderCircle } from "react-icons/bi";

export default function Overlay() {
    return (
        <>
            <div className="overlay">
                <div className="loading-container">
                    <div className="loading-spin">
                        <BiLoaderCircle />
                    </div>
                    Loading
                </div>
            </div>
        </>
    );
}

```

### frontend/src/Nav.jsx

```javascript
import React from "react";

function Nav() {
    const navitems = [{ name: "About", link: "https://devpost.com/software/tbd-nd1ov6?ref_content=my-projects-tab&ref_feature=my_projects", note: "about us" }];

    return (
        <div id="nav">
            <a href="/">
                <img src="AirMigoLogo.png" alt="Logo" className="nav-logo" />
            </a>
            <div className="navigation-link">
                {navitems.map((item, index) => (
                    <div key={index}>
                        <a href={item.link} target="_blank">{item.name}</a>
                    </div>
                ))}
            </div>
        </div>
    );
}

export default Nav;

```

[13 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]