Inspiration

Most people who see a problem in their neighborhood never report it. That might be a pothole, an aggressive loose dog, illegal dumping, or someone sleeping outside on a cold night. Usually they don't know who to call. Does it go to 311, the police non-emergency line, Animal Services, or a shelter network? Each one has its own app, form or phone tree. On the other side, agencies get reports that are incomplete, duplicated and sometimes fake, and staff spend hours sorting them by hand.

We wanted reporting to be as easy as texting a friend. You send one number, with no app and no account, and it works on any phone. You also hear back when something is actually done.

What it does

A resident texts what they see. Community4You then:

  1. Asks at most two follow-up questions: the location if it's missing, then the one detail that matters for that kind of problem (for example, "Is the dog contained, or running loose right now?"). It replies in the resident's language.
  2. Routes the report to the right agency (one of five mock LA agencies) and prioritizes it as LOW, MEDIUM, HIGH or CRITICAL, with a reason.
  3. Flags spam and suspicious reports so they never reach an agency's queue.
  4. Groups reports about the same real-world event into one incident, even when people describe it differently, and raises its priority as more neighbors confirm it.
  5. Replies "CALL 911 NOW" right away to life-threatening keywords, even if the AI is down.

Agency staff work incidents on a live dashboard. When they press Confirm or Resolve, every resident who reported that incident gets a text.

How we built it

  • SMS: An Android phone with a SIM runs SMS Gateway for Android in Cloud mode and acts as the bot's phone number. Incoming texts hit our backend as HMAC-signed webhooks.
  • Backend: Next.js (TypeScript) on Vercel. A rule-based conversation engine handles the flow (follow-ups, STATUS, NEW) and calls the AI only where judgment is needed.
  • AI: Google Gemini (Flash-Lite, with Flash as backup). Every response must follow a JSON schema and is checked with Zod, so a bad generation can't corrupt a report.
  • Database: Supabase Postgres with Realtime. Row Level Security lets browsers read and only lets the backend write.
  • Dashboard: Vite + React. It subscribes to Supabase Realtime, so new reports appear live with a notification sound.

The AI picks the priority level, and corroboration adds to a sort score so that, within a level, incidents more people have reported rise to the top:

$$ \text{score} = B(\text{priority}) + \min\big(10\,(n - 1),\ 30\big) $$

where $B$ is 100, 70, 40 or 10 for CRITICAL, HIGH, MEDIUM or LOW, and $n$ is the number of reports on the incident.

To keep replies fast, the resident gets an answer first. Incident matching, summary merging and re-prioritization run in the background after the reply is sent. Running database queries in parallel cut reply time from about 4.5 s to about 2.5 s.

Challenges we ran into

  • Getting a real phone number to text from. Twilio's trial only sends template messages, and US carrier registration (10DLC or toll-free verification) takes days to weeks, which is far longer than a hackathon. Scripted iMessage sending broke on the latest macOS. In the end we turned a spare Android phone into our SMS gateway. It worked, but only after we dealt with Android 15 SMS permissions, turned off RCS, and learned that the webhook only syncs while the app is online.
  • Grouping duplicates without merging unrelated reports. "Dog chasing kids on Elm" and "loose pit bull near the elementary school" are the same incident, but two potholes on the same street are not. Getting the prompt to match on same physical problem, same place, any wording took a lot of iteration.
  • Understanding texts after a report is filed. A resident's next message could add detail, describe a new problem, or just say "thanks". We added a dedicated classifier so new problems don't get merged into old reports and a "thanks" doesn't open a new ticket.
  • AI reliability. Free-tier rate limits and frequent 503 errors forced us to add a fallback model. We also kept safety-critical behavior, such as the 911 intercept, out of the AI path entirely.
  • Working in parallel. One of us built the backend while the other built the dashboard, so we had to keep both connected to the same live API as it changed.

What we learned

  • Carrier rules shape SMS products more than code does. Even an "easy" text-message app runs into anti-spam regulation right away.
  • LLMs are most useful with tight constraints: structured output, schema validation, and a small, well-defined job at each step (triage, follow-up classification, incident matching).
  • For a public-service tool, closing the loop matters as much as intake. A text saying "it's fixed" is what makes people willing to report the next problem.

What's next

  • Geocoding addresses so we can verify locations, match incidents by distance, and show a hotspot map on the dashboard.
  • Letting agencies publish confirmed incidents as public alerts.
  • Piloting with a real neighborhood council or university campus.

Built With

Share this project:

Updates

Submission history