Inspiration

“We’re all going to die one day.” I’ve heard this so many times, but I care about what we leave behind. When I first came to Houston, it took me a while to figure out the METRO. When my parents joined me for the World Cup, we spent as much on Ubers to and from the venue as we did on lunch.

That’s where Jump In! started: helping event organisers find the gaps in public transport and plan connections that make sustainable travel an easier choice.

What it does

Jump In! measures whether a World Cup host city can move people to the venue without a car — and what it takes to fix it where it can't. It scores four host cities on car-free access using real data: Census tract geometry, transit stop locations from 17 agency GTFS feeds, and household vehicle ownership from the American Community Survey. Red on the map is a gap: no transit stop within a ten-minute walk. In Houston, 28,366 car-free households live in those gaps. They aren't choosing to drive. There's nothing to choose. Then it tests the fix. A greedy maximal-covering algorithm places feeder shuttles where they connect the most car-free households. Five stops move Houston's car-free coverage from 70.5% to 74.5%. Planners can override it — place their own shuttles, see how they compare against the algorithm, see what it would add next. Every option is priced using Houston METRO's own operating cost from the FTA National Transit Database: $80.08 per vehicle revenue hour. Every assumption is a slider. An AI layer lets you ask questions in plain language. The model returns a filter, not an answer. It structurally cannot invent a number. A resident types their zip code and gets an honest answer: is my area served today, would the proposed shuttles change that, and which stop would cover me. When the answer is no, the tool says no. Two ends of responsibility. One engine.

How we built it

Batch pipeline in, Streamlit app out. Nothing computes live.

pipeline.py runs once. It pulls TIGER tract polygons, ACS demographics (tables B01003 and B25044), and stops.txt from every GTFS feed. It projects everything into the venue's local UTM zone — you can't buffer half a mile in degrees — draws the walkshed, classifies every tract, joins the demographics, runs the greedy placement, and writes Parquet. The app reads Parquet and filters. That's why the demo can't freeze.

Every threshold is documented. Every source came from the hackathon's own data catalog. The placement algorithm carries a proven guarantee: within 63% of optimal (Nemhauser, Wolsey & Fisher, 1978).

The router is three files. query.py validates the model's JSON against a fixed schema and executes it as a pandas filter. router.py makes the API call with a timeout and structured output. The app never renders model text — the description you see is generated from the validated filter, not from the model.

We built it with Claude Code in phases, with a gate at the end of each one. Audit before edit. Test after every change. Nothing moved forward until the previous phase proved itself on real data. The pipeline was frozen after the first successful run; every feature after that was an export or an app change, and index.csv had to come out byte-identical every time.

Challenges we ran into

The first NY/NJ run scored 22.3 — last of four cities. The densest transit metro in North America was reading as a transit desert. Our own diagnostics caught it: car-free coverage was below general-population coverage, which never happens where transit data is complete, because car-free households cluster near transit. The cause was missing MTA feeds. We added subway, MTA Bus, all five NYCT Bus boroughs, LIRR, and Metro-North. The score went to 92.4. Car-free households in gap tracts went from 1,722,648 to 23,738. Then we built a plausibility check so it can't happen quietly again.

We pivoted the whole project four days before the deadline. We came in with a startup pitch for a sustainable transport platform. Then we read the judging criteria. This is a data hackathon — statistically sound, spatially accurate, supported by evidence. A pitch has no maps. We rebuilt around the analysis and kept the product idea as the intervention the tool tests.

Everything else cost an hour we didn't have. Git rejected our push because raw GTFS and TIGER shapefiles were committed. Streamlit Cloud built on Python 3.14 with no geopandas. pyproj couldn't find PROJ_DATA on a MacPorts install. The cost table showed identical values in both columns — correct, because cost depends only on stop count, but it looked broken and had to be redesigned.

We cut things we wanted. Bikeshare: Houston hasn't had one since 2024, and Lime's GBFS license prohibits storing the data. Web-searched shuttle pricing: it would have broken the one claim we most needed to be true. A from-scratch LLM: no.

Accomplishments that we're proud of

The pipeline caught its own data gap and named the missing operator. Most tools present whatever comes out. Ours told us when it was wrong.

The AI cannot invent a number — by code, not by prompt. Schema validation on every field. A Seattle decoy tract in the test suite that must never leak into a Houston query. A router that rejects any response containing an error key so no model text reaches the screen.

Manual placement reproduces the algorithm exactly. Select the greedy's own five picks and you get its numbers to the household. Offline replay from the coverage table matches shuttles.parquet across all four cities. That's a correctness proof, not a smoke test.

Every ACS merge matched 100%. 6,644 study tracts across four cities. Zero unmatched.

The cost model found something we didn't design in. Cost per connected household rises with each stop — $1.01 for the first, $1.33 by the fifth. Diminishing returns fell straight out of the greedy. A planner can see exactly where to stop spending.

We found that Houston METRO cut bikeshare in 2024 and moved the money into on-demand microtransit. That is the service our tool places. The agency that would run it already chose it over the alternative.

What we learned

Instrumentation beats validation when a human is watching. Ten minutes of loud diagnostics on the first real run caught what an hour of input checking would have missed.

The judging criteria decide the product. We had a good idea and the wrong deliverable. Reading the rubric was worth more than any feature we built.

Stop density is not comparable across cities. A subway station moves ten times what a bus stop does. NY/NJ sat near our completeness threshold even with every feed loaded — because it's rail-heavy, not because data was missing. The mode-independent check — car-free coverage versus population coverage — was the reliable one. The stop-count check became advisory only.

What's next for Jump In!

resident view currently shows whether transit serves your area. The next version connects to the modes that get you the rest of the way — and shows the cheapest sustainable one.

Schedule-based routing. Today, "served" means a stop within a half-mile walk. Tier 2 uses GTFS timetables to compute real travel time and transfers to the venue, so a resident sees minutes, not just a class.

Fare comparison. Transit versus rideshare versus shuttle, per zip code. The individual view should show the cheapest sustainable option, not just whether one exists.

Micromobility, done properly. GBFS station locations where docked systems exist, with a bike-appropriate catchment instead of a walk buffer, and an equity adjustment for smartphone and payment barriers. Not folded into the access score without it.

Los Angeles, 2028. Same engine.

Built With

  • anthropic-api
  • census-api
  • claude-code
  • fta-ntd
  • geopandas
  • git
  • google-fonts
  • gtfs
  • mobility-database
  • numpy
  • pandas
  • pgeocode
  • pyarrow
  • pydeck
  • python
  • shapely
  • streamlit
  • streamlit-community-cloud
  • tiger-line
Share this project:

Updates