Inspiration
Cities deploy thousands of expensive IoT sensors to monitor infrastructure — but every citizen already carries a powerful sensor in their pocket. I asked: what if we could turn every smartphone into a smart city sensor? CityPulse was born from the idea that civic reporting should be as easy as taking a photo.
What it does
Citizens snap a photo of an urban issue — pothole, broken streetlight, graffiti, flooding — and CityPulse handles the rest:
- AI classifies the issue type, severity, and responsible department in seconds (Groq Llama 4 Scout vision)
- DBSCAN clusters nearby reports into actionable hotspots
- Interactive dashboard shows a live map with severity-colored markers, heatmap density overlay, and city health metrics
- AI chat assistant answers questions about city conditions using report data and live local news
- City council briefings are auto-generated — professional memos ready for officials
- Real-time updates via SSE — submit on your phone, watch it appear on the dashboard instantly
- Citizens can upvote/verify reports, and severity auto-escalates after 3 confirmations
- Reports flow through a resolution workflow (open → in progress → resolved)
- Multi-city support — add any city with a config entry
- Privacy-first — all photo metadata (EXIF/GPS) is stripped before storage
- Voice reporting via Web Speech API for accessibility
- Accessibility impact score weights issues by their effect on disabled citizens
- Neighborhood risk scoring grades areas by report density, severity, and resolution rates
- GeoJSON open data API for integration with external GIS tools
How I built it
- Backend: FastAPI with SQLite/SQLAlchemy — simple, fast, no infrastructure overhead
- AI: Groq API — Llama 4 Scout for vision classification, Llama 3.1 8B for chat, briefings, and news translation
- Clustering: scikit-learn DBSCAN on raw lat/lng coordinates (eps=0.003 ≈ 300m)
- Map: Folium/Leaflet with heatmap overlay, LayerControl for toggling layers
- Real-time: Server-Sent Events with asyncio.Queue per connected client
- News: SWR RSS feeds filtered by city keywords, auto-translated to English via Groq
- Seed data: 40 real street-level photos from Mapillary API, each AI-classified
- Privacy: Pillow strips all EXIF metadata from uploaded photos
- Frontend: Vanilla HTML/CSS/JS — no frameworks, dark mode, PWA-ready
- Testing: 47 pytest tests covering classification, clustering, health score, submissions, and dashboard
- Deployment: VPS with nginx + Let's Encrypt SSL at citypulse.help
Challenges I ran into
- Gemini API quota exhaustion — Google's free tier ran out mid-development. I pivoted to Groq (Llama 4 Scout) which has a more generous free tier and faster inference
- RSS news quality — German regional news feeds include stories from the entire state. I built a keyword filter for city-specific news and auto-translate German headlines to English via Groq
- Folium limitations — Folium generates static HTML, so I can't dynamically add markers. I solved real-time updates with SSE toast notifications instead
- Street-level photos — Mapillary coverage is patchy. I implemented progressive search radius (300m → 600m → 1km) to maximize coverage, getting 40/50 locations covered
Accomplishments I'm proud of
- 22+ features built and deployed solo — every one peer-reviewed by adversarial AI agents
- Zero unclassified reports — every seed photo was AI-classified, with Groq finishing what Gemini couldn't
- 47 passing tests with zero regressions throughout development
- Real Mapillary photos from actual Stuttgart streets — not stock photos or placeholders
- Multi-model AI architecture — vision classification, conversational chat, council briefings, and news translation all running on Groq's free tier
- The app is live and functional at citypulse.help — not a prototype
What I learned
- Free AI APIs have real quota limits — always have a fallback provider
- Adversarial peer review (even between AI agents) catches bugs that solo development misses
- For hackathons, a working deployed product beats a feature list every time
- Folium is great for quick map prototyping but has limitations for real-time interactivity
- Privacy features (EXIF stripping) are trivial to implement but powerful for user trust
What's next for CityPulse
- More cities — the multi-city architecture is ready, just needs data seeding
- User accounts — track your reports, get notifications when they're resolved
- Department portal — city officials manage assignments and SLA tracking
- Before/after photos — citizens document when issues are fixed
- Predictive maintenance — use historical patterns to schedule preventive repairs
- Native mobile app — PWA works today, but a native app could access camera and GPS more seamlessly
Built With
- css
- dbscan
- fastapi
- folium
- groq
- html
- httpx
- javascript
- jinja
- leaflet.js
- llama-3.1
- llama-4-scout
- mapillary
- pillow
- python
- rss
- scikit-learn
- server-sent-events
- sqlalchemy
- sqlite
- web-speech-api
Log in or sign up for Devpost to join the conversation.