Inspiration
Every year, New Yorkers file over 3 million 311 service requests - real complaints about real problems: no heat, a pothole, a broken streetlight, a landlord who won't fix the plumbing. But the system has a structural flaw that has nothing to do with whether the city cares: most residents don't know which of NYC's 40+ agencies actually handles their problem, so complaints get misrouted, under-detailed, or never filed at all.
This isn't a small-edge-case problem. City data shows heat and hot water complaints alone rose past 246,000 in 2024 - up 14% since 2019 - concentrated in the same neighborhoods, year after year, often the same buildings. The people most likely to give up on filing are the people the system most needs to hear from: renters who don't speak English fluently, people working multiple jobs, elderly residents, and anyone who's never had a reason to learn how city bureaucracy works.
We built ResolutionIQ for bumblebee, after noticing that the hardest part of getting a city problem fixed usually isn't the city being slow - it's residents never successfully entering the system in the first place.
What it does
ResolutionIQ turns a plain-language description of a problem - "my landlord hasn't fixed the heat for 10 days, it's winter, I have two kids" - into a properly routed, professionally drafted, trackable government complaint.
- Routes it correctly. AI classifies the complaint against NYC's official 311 taxonomy and identifies the exact responsible agency (e.g., HPD for heat, DOT for potholes) - not just "call 311."
- Drafts the complaint. Generates a formal letter with the right tone, the right legal code citations (e.g. NYC Admin Code §27-2029 for heat), and the user's real facts - ready to copy and submit. The user can ask for it to be more urgent, more detailed, or simpler, and can hand-edit it directly.
- Sets a real timeline. Instead of vague reassurance, the user sees a resolution estimate built from historical NYC 311 data, broken into fast/typical/slow percentiles for their specific complaint type - so "wait and see" becomes "follow up after day 9, here's why."
- Prepares the next move automatically. If the deadline passes with no response, a pre-written, agency-specific escalation letter and a City Council follow-up are ready to go - locked behind a "did you actually file the first one" gate so users don't skip the agency for political pressure prematurely.
- Shows where the problem is, and who else has it. A map lets the user pin the exact location, auto-fills the verified address into the complaint, shows nearby NYC 311 complaints of the same type, and detects the user's real City Council district instead of guessing - so the complaint can honestly say "this is a recurring issue, not an isolated one," backed by real numbers.
How we built it
- Frontend: React 19 + Vite 6, no backend - the entire app runs client-side, so there's no server holding user data.
- AI: Google Gemini 2.5 Flash, used for two distinct jobs: structured classification (problem → category → agency → urgency → legal code, returned as JSON) and structured generation (the formal complaint letter and its revisions). Temperature is kept low (0.3) because we want consistent, factual output, not creative variation.
- Maps: Mapbox GL JS via
react-map-glfor the interactive pin, a heatmap layer built from live NYC 311 query results, and a council-district boundary overlay computed entirely client-side with Turf.js point-in-polygon - no extra API calls. - Data layer: Static, hand-verified JSON for the things that must never be wrong -agency contacts, legal code citations, and historical resolution-time percentiles computed from NYC's public 311 dataset. The AI is never the source of truth for facts; it's the source of language.
- State: A single
useReducerstore persisted tosessionStorage- survives a refresh, clears when the tab closes, no accounts, no login.
Challenges we ran into
- Getting the AI to be consistently formal and fact-based, rather than emotionally persuasive, required tight prompt constraints and a strict JSON output schema - early drafts sometimes drifted into advocacy language that wouldn't read as a credible government complaint.
- Deciding what the AI should never be allowed to touch. We didn't want a single hallucinated detail - wrong phone number, wrong legal code - to undermine an otherwise-good complaint, so we made AI output secondary to a verified static dataset wherever a wrong answer would actually cost the user.
Accomplishments we're proud of
- A complaint generator where the AI never has the final say on a single fact that matters - agency, contact info, and legal codes are independently verified, even when the AI is the one writing the sentence.
- A hardcoded safety override for life-threatening complaint types (gas leaks) that the AI cannot suppress, no matter how it classifies the input.
- A map layer that doesn't just show a pin - it makes the complaint itself stronger, by automatically detecting and citing nearby identical complaints as evidence of a pattern.
What we learned
We learned that the AI's job needed to be narrower than we expected - great at turning a messy complaint into clear, classified language, but never trusted as the source of truth for facts that actually mattered, like legal codes or agency contacts. Those stayed in a verified static dataset instead. We also learned how much useful signal - like real resolution-time patterns - is buried in NYC's open data but never shown to the residents it would actually help.
What's next
- Expand city coverage beyond NYC to other cities with public 311 APIs (Chicago, LA, SF, Boston all publish equivalent open datasets).
- Expand the council district dataset from a sample set to all 51 NYC districts now that detection is automatic instead of hardcoded.
- Add outcome tracking - letting users mark a complaint "resolved" so the timeline predictor's accuracy improves over time from real user outcomes, not just historical city data.
Built With
- css
- gemini-2.5-flash
- geojson
- google-gemini
- javascript
- mapbox-gl
- nyc-open-data
- react
- react-map-gl
- sessionstorage
- socrata
- turf.js
- vite
Log in or sign up for Devpost to join the conversation.