Inspiration

I live in the Houston area, and if you have ever driven past the Ship Channel you know the air out there is not the same as the air in River Oaks a few miles west. Some neighborhoods just carry more stress than others, between traffic, heat, and pollution, and the city usually finds out about a problem after it happens instead of before. I wanted to build something that could watch the whole city at once and flag where things are getting bad while there is still time to react.

What it does

CityPulse AI is a live dashboard that tracks 36 Houston neighborhoods and gives each one a stress score from 0 to 100. The score is built from real data: live air quality from the WAQI sensor network and live heat index from Open-Meteo, mixed with a traffic model that follows the city's normal rush hour pattern.

Click any neighborhood and you see exactly what is driving its score. An AI layer powered by Google Gemini writes a short read on the situation and a resource plan, like where to stage EMS or when to open a cooling station. There is also a time slider that plays through a full 24 hour day so you can watch stress climb and fall across the map during rush hour and the afternoon heat.

How I built it

It is a single HTML file with plain JavaScript and no frameworks, so it loads instantly and runs anywhere.

  • Air quality comes from the WAQI API using a coordinate based station lookup
  • Weather and heat index come from Open-Meteo, which is free and needs no key
  • The AI writeups come from Google Gemini, with a local reasoning fallback I wrote myself so the dashboard still explains itself even if the API is down or rate limited
  • Deployed on GitHub Pages

The stress score weights each input on purpose: 45 percent the neighborhood baseline, 30 percent traffic, 15 percent heat, and 10 percent air quality.

Challenges I ran into

Real data is a lot messier than I expected. The air quality API sometimes returns a dash instead of a number when a station goes idle, and that single dash was quietly turning every score on the map into NaN. It took me a while to figure out the bug was bad incoming data, not my math.

The AI also kept hitting a 429 rate limit because I was firing a fresh request on every click. I fixed it by caching each answer and only calling once per zone, and I added the local fallback so a judge clicking around fast would never hit a dead panel.

Accomplishments that I'm proud of

I am proud that this actually pulls real, live data instead of faking it. The air quality and heat numbers on the screen are the real Houston readings at the moment you load the page, not random values I made up to look impressive.

I am also proud of how I handled the Ship Channel neighborhoods. Places like Channelview, Pasadena, and Galena Park really do carry some of the worst air in the metro, and the dashboard surfaces that instead of treating every part of the city the same. It turns a class project into something that points at a real problem real people deal with.

The part I am most proud of on the technical side is that the whole thing keeps working even when something breaks. If the air quality station goes idle, it falls back to the model. If the AI hits a rate limit, my own backup writeup engine takes over. A judge can click around as fast as they want and never hit a broken screen, and getting it that stable took the most work.

What I learned

APIs do not always hand you clean data, and you have to defend against that. I learned to validate every value before trusting it, to cache instead of spamming a service, and to always build a fallback so the project keeps working when something outside your control breaks.

What's next

Pulling real air quality per zone from each nearest station, adding a citywide trend chart, and bringing in real traffic data if I can get access to a feed.

Built With

Share this project:

Updates

Submission history