Inspiration
Two numbers stayed with us. On a single night in January 2025, 745,652 people in the United States were experiencing homelessness (HUD 2025 AHAR), 2,024 of them in Baltimore (Baltimore City 2025 PIT count). And among young adults aged 18 to 25, roughly 1 in 10 experienced some form of homelessness over a 12-month period, including couch surfing (Chapin Hall).
Behind each of those numbers is the same pair of questions. Where can I get help? How do I get there?
The first question has an answer. 211 directories, shelter lists and nonprofit websites all exist. The second one doesn't. Nobody tells you that the shelter you found closes intake at 8 PM, that it needs a referral you don't have, that the bus fare is more than the $10 in your pocket, or what to do when you finally arrive and they're full. Directories tell people what help exists. Lighthouse is built to tell them how to reach it, and to stay with them when the plan breaks.
What it does
You describe your situation in one sentence, typed or spoken. Lighthouse pulls out what you need (a bed, a meal, longer-term help) and what you're working with (age, money, ID, how you can travel), then checks every real option against it: is it open when you'd arrive, does it take walk-ins, does the bus fare fit, is it within reach on foot.
What comes back is a timed plan, not a list. 6:00 PM, call for a referral. 6:05 PM, walk 20 minutes. 6:25 PM, check in before the 9 PM cutoff, dinner is served there. 7:00 AM tomorrow, the health center for longer-term help. Every step carries the address, the phone number, what to bring and how long the leg takes, and the whole route is drawn on a map from where you're standing.
It bends to you, not the other way around. Before planning, every extracted detail is on screen and editable: add or remove a need, change the deadline, set whether you have ID, switch between walking, bus, rideshare or your own car, adjust your budget. After planning, you get up to three routes to choose from, Recommended, Fastest and Lowest cost, each with a one-line trade-off ("6 fewer travel minutes; photo ID needed at some stops"), and you can see exactly why every other place was not chosen.
Right now shows the single next action with the address, phone number, intake cutoff and what to bring. Tap it done and the next step comes up.
Something changed? is where Lighthouse is different from a directory. You say what happened in your own words: "I missed the bus", "they said they're full", "I lost my ID", "I'm at Mount Vernon now". A Gemini-powered agent works out what that means for the plan, applies it, and rebuilds the route from where you are and what you've already finished. If a shelter fills up, you get the next one that still fits your night, not a fresh list to start over with.
Help card puts your situation in large print so you can hand your phone to a staff member instead of explaining it again. It can read itself aloud, and so can the whole plan. We built this with ElevenLabs because a plan you can't read is not a plan: someone in crisis may be exhausted, may not read English well, may have low vision, or may just be standing on a sidewalk at night. Speaking your situation in and hearing your steps out makes Lighthouse usable in those moments.
When nothing fits, it tells you why (everything closed by the time you'd arrive, every shelter needs an ID you don't have, nothing within walking distance) and what would unblock it.
How we built it
- Understanding. Gemini structured output turns the sentence into a fixed schema (needs, age, budget, ID, household, transport). A rule-based parser produces the same schema when the model is unavailable, so the app keeps working.
- Planning. A Python planner filters places by eligibility and status, builds a NetworkX travel graph with walking, bus and transfer options, then simulates every combination of stops against opening hours and intake deadlines. Survivors are scored on travel time, cost and how sure we are about the requirements. Unmet needs always outrank score, so a plan can never win by quietly dropping something you needed. The same search runs three times with different tie-breaks to produce the Recommended, Fastest and Lowest cost routes.
- The disruption agent. "Something changed?" is a tool-calling agent built on Gemini function calling. The model reads the plan (steps, places, bus routes, what's already done) and the person's message, and chooses from six state-changing tools: shift time, mark a place full, report a bus delay, set location, mark a step done, update a constraint. Each call is validated against known places and routes, applied to state, and the planner reruns from the person's current position and progress. The agent changes the inputs; it never chooses the route.
- Voice. ElevenLabs Scribe for dictating your situation, ElevenLabs text-to-speech for reading the plan and the help card.
- Frontend. Next.js and React, Leaflet with OpenStreetMap, geolocation for the starting point.
Challenges we ran into
- Time windows break shortest-path thinking. Whether a shelter works depends on when you arrive, which depends on where you ate first, which depends on the bus you caught. A shortest-path algorithm can't express "intake closes at 8 PM". We simulated every combination of stops through the evening instead, and attached the reason to every rejected option so the plan can explain itself.
- Drawing the line between the model and the planner. We wanted Gemini's understanding of messy human language without letting it make decisions about where someone sleeps. That meant designing a strict boundary: structured output with a fixed schema on the way in, function calling with a small validated toolset for changes, and a deterministic planner in between. Getting the tool descriptions right so the model calls "shift_time" rather than inventing a new place took several rounds.
- What "I already ate" actually means. Replanning from progress sounds simple until you define it. A finished shelter check-in also covers dinner if that shelter serves meals. A finished step means the clock can't go backwards. A place you've already been to shouldn't show up in the "removed from your plan" banner. Each of those was a bug we found by walking through the flow as the person would.
- Every hard limit is a person you turn away. Our first walking cutoff was 3 km. From the university campus, that meant no plan at all. We replaced it with a soft limit: long walks are allowed but flagged, the app asks whether that's OK, and "that's too far" lowers the limit and replans. The same idea shaped the whole product. When something doesn't fit, ask or explain; don't return nothing.
Accomplishments that we're proud of
- A plan you could hand to someone in crisis and they could follow it, built from real organizations with sourced hours and rules.
- Replanning that continues from where you are, driven by plain sentences, with the model kept out of the routing.
- Choice without overload: three routes with honest trade-offs, every detail editable, every rejection explained.
- Voice in and voice out, so the plan works for people who can't or shouldn't be reading a screen right now.
- The help card. It's small, but it's the piece that turns "I typed my situation" into "I asked for help at a desk".
What we learned
- The most useful thing an LLM did for us was not plan. Keeping it at the edges (understanding input, interpreting "something changed") made the system explainable, testable and trustworthy.
- Rejection reasons are a feature. "Why not this shelter?" turned out to matter as much as the plan itself.
- Accessibility is not a mode. Voice, large print and one-step-at-a-time guidance changed the product for everyone, not just the people we first had in mind.
- Every threshold in the code is a decision about a person. Ask instead of refusing.
What's next for Lighthouse
- Partnerships with shelters and service providers. The biggest gap between Lighthouse and a real service is live availability. We want to work directly with Baltimore shelters and the Mayor's Office of Homeless Services so that a bed count comes from the provider, a referral can be requested from inside the plan, and eventually a spot can be held before the person starts walking.
- Plans that watch themselves. Today the person tells us when something changed. Next, Lighthouse checks the plan on its own: if a shelter reports full or a bus is running late while you're still on the way, you get a message with the new route before you find out at the door.
- Learning from what actually happened. Whether people were admitted, turned away, or arrived late is the most valuable data we could have. Feeding those outcomes back into the resource records would make every next plan more accurate.
- A copy that survives a dead phone. A printed or texted version of the plan.
- Any language in, any language out. Someone should be able to describe their night in the language they think in and hear the plan back the same way. The extraction and voice layers already support this; the interface needs to follow.
Built With
- elevenlabs
- fastapi
- gemini
- google-gemini-api
- leaflet.js
- networkx
- next.js
- openstreetmap
- pydantic
- python
- react
- tailwind
- typescript
Log in or sign up for Devpost to join the conversation.