A real-time urban intelligence dashboard for Boston, MA. An AI agent (LangGraph + Gemini) answers natural-language queries about traffic, weather impact, and city incidents, and renders the results as live map layers.
- AI Agent — 4-node LangGraph pipeline: intent classification → data collection → spatial reasoning → natural-language response
- Real-time traffic simulation — time-of-day-aware vehicle simulation across 10 Boston neighborhoods
- Live weather — OpenWeatherMap integration (falls back to season-aware simulation)
- Gemini LLM — natural-language intent detection and response generation (falls back to keyword matching)
- WebSocket streaming — traffic and event updates pushed to the frontend every 5 s
- Interactive map — MapLibre GL JS with CartoDB dark tiles (no API key required)
- Zero-token map — works entirely without a Mapbox account
git clone <repo-url>
cd urban-pulse
cp backend/.env.example backend/.env
# Edit backend/.env and add your API keys (optional — app works without them)cd backend
pip install -r requirements.txt
uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadOpen frontend/index.html in your browser directly, or serve it:
cd frontend
python -m http.server 3000
# then visit http://localhost:3000# Copy and fill in env file
cp backend/.env.example backend/.env
# Build and start
docker-compose up --build
# Frontend → http://localhost:3000
# API → http://localhost:8000| Key | Where to get | Effect when missing |
|---|---|---|
GOOGLE_API_KEY |
aistudio.google.com | Uses keyword-based intent + template responses |
OPENWEATHER_API_KEY |
openweathermap.org/api | Uses season-aware Boston weather simulation |
TOMTOM_API_KEY |
developer.tomtom.com | Uses time-of-day Boston traffic simulation |
All keys fall back gracefully — the app is fully functional in demo mode.
TomTom's free plan includes 2 500 requests/day. Urban Pulse makes 10 flow calls + 1 incident call per refresh cycle. The default cache TTL is 5 minutes → ~3 168 calls/day.
To stay within the free limit set a longer cache in backend/.env:
TOMTOM_CACHE_TTL=600 # 10 min → ~1 584 calls/day
When the TomTom key is active the header badges flip from
SIM TRAFFIC → LIVE TRAFFIC automatically.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Service status and mode info |
GET |
/api/weather |
Current weather for Boston |
GET |
/api/traffic |
Traffic hotspots + neighborhood summary |
GET |
/api/events |
Recent incidents |
POST |
/api/query |
Run the AI agent ({ "query": "..." }) |
WS |
/ws/stream |
Real-time push: traffic + weather + events |
curl -X POST http://localhost:8000/api/query \
-H "Content-Type: application/json" \
-d '{"query": "If it rains, where are the delays?"}'frontend/index.html
│ REST /api/query, /api/weather, /api/traffic
│ WS /ws/stream (5 s push)
└──► backend/main.py (FastAPI)
│
├── agent.py (LangGraph)
│ analyze → collect_data → spatial_reasoning → generate_response
│ └── Gemini 1.5 Flash (optional)
│
├── weather_service.py
│ └── OpenWeatherMap API (optional)
│
├── stream_processor.py
│ └── Time-of-day Boston traffic simulation
│
└── spatial_tools.py
└── 10 Boston neighborhoods + flood zones + transit chokepoints
| Layer | Technology |
|---|---|
| Frontend | HTML/CSS/JS, MapLibre GL JS, CartoDB tiles |
| Backend | Python 3.11, FastAPI, uvicorn |
| AI Agent | LangGraph, LangChain, Google Gemini 1.5 Flash |
| Spatial | Custom Boston neighborhood polygons, point-in-polygon, Haversine |
| Real-time | WebSocket (FastAPI native) |
| Deployment | Docker, docker-compose, nginx |
