Skip to content
Ribhav Hora

Projects

Step In

Building
Role
Solo: product & engineering
When
2026
Stack
SwiftUI, MapKit, MTA GTFS, iOS

Source

I like to walk, and I take the subway, and those two facts fight each other. The train drops you as close to your destination as it can, which is exactly the wrong thing if what you actually want is to walk twenty minutes on the way home.

Step In resolves the fight. You give it a destination and a goal (“walk 20 minutes” or “4,000 steps”), and it tells you which stop to get off at to hit it.

Step In's input screen in Minutes mode: from 315 W 33rd St to 100 5th Ave, with the walk goal set to 20 minutes and a Plan my walk button. The same input screen in Steps mode, with the walk goal set to 4,000 steps.
Tell it where you're going and how far you want to walk, in minutes or steps.

From 315 W 33rd St to 100 5th Ave, 20 minutes: take the C, get off at 23 St instead of W 4 St, a 22 minute walk.

Step In's result: get off at 23 St instead of W 4 St-Wash Sq, about 24 minutes total, 22 minutes of walking, 1,992 steps. A map shows the C train from Penn Station down to 23 St, then the walking route to 100 5th Ave.
The recommendation: get off a stop early, with the ride, the walk, your steps, and the total time mapped end to end.

The insight that makes it work

My first instinct was backwards, and testing on real trips caught it. I started by trying to find the stop that minimized the remaining walk, then stretch it. But minimizing the walk is the opposite of the point. When you’ve asked to walk twenty minutes, a long final walk is the goal, not a cost.

The version that works anchors on the origin: find the line you’d genuinely board, nearest you and heading toward your destination. Then walk backward along that line from the stop you’d normally use, stop by stop, until the real walking distance from an earlier stop matches your target. The recommendation is always a line you’d actually take, just gotten off one or two stops early.

Building the transit brain

The obvious approach would be to lean on Google Maps, but you can’t build inside a closed app, and Apple’s MapKit turns out not to do transit routing at all (MKDirections simply errors on transit requests, which I verified before designing around it).

So Step In carries its own transit knowledge. A Python script downloads the official MTA subway GTFS feed and distills it into a compact bundled JSON: every station, every line’s stop sequence, express versus local preserved. It’s about 72 KB, ships inside the app, and needs no network and no API keys at runtime. MapKit still does what it’s good at, the real walking times and distances for the final leg and the map, through MKDirections walking routes.

How it’s built

The planners are pure logic over a subway graph, with the walking-time estimator injected rather than called directly. That one decision means the routing brain is testable without a simulator or a network connection: the unit tests feed it known trips and assert the stop it picks. For a solo project it’s the difference between “seems right when I try it” and knowing it’s right.

v1 handles single-line trips, which covers most short Manhattan commutes. Transfers, real-time arrivals, and HealthKit-based stride personalization are the natural next steps.