The first version of Zetpin's discovery surface shipped with a 5 km radius. We picked it the way most teams pick defaults — it felt reasonable. The map looked balanced. The feed didn't go empty. On paper it worked.
It was wrong.
A week after launch we had two clusters of feedback that, at first, looked contradictory. One group of users — mostly in dense urban areas like Kochi and Bangalore — said the feed was noisy. Too many pins from too many strangers. The other group, in smaller towns, said the feed was empty. They could see three pins, all from the same coffee shop.
The problem wasn't that 5 km was the wrong default. The problem was that there is no right default. "Nearby" is not a distance — it's a relationship to a place. In a dense neighborhood, nearby means the block you walk every morning. In a smaller town, nearby is the next two villages over, because that's where your people are.
We rebuilt discovery around the user's own definition of "nearby." A slider, persistent across sessions, lets each person tune their own radius from 500 m to 50 km. Every screen that depends on location — the feed, the map, alerts, the people-near-you carousel — listens to the same source of truth. There's no longer a "default" we have to argue about in design review.
A few things we learned doing this.
The slider is not the feature. The feature is the moment a user changes it. We instrument every slider drag — not because we need the analytics, but because the drag is a signal that the product is being used the way a person uses a radio dial: scanning, exploring, settling. If a user has never moved the slider, we treat it as a soft failure of the onboarding.
Empty states are part of the radius, not exceptions to it. When the radius is small enough that the feed has nothing in it, we don't show a "no results" placeholder. We show what's in the next ring out, dimmed, with the actual distance. This nudges the user to widen — but quietly, without us forcing it.
Geohash buckets, not raw lat/long queries. Every pin is stored with a geohash prefix. When we widen the radius, we widen the prefix match. This means our feed query is an indexed string prefix lookup, not a haversine-distance scan. On the read path it's cheap enough that we can serve the feed at the same latency at 500 m as we can at 50 km.
The map is a confirmation, not the interface. We used to think the map was the product. It isn't. Most people open Zetpin to see the feed, scroll once or twice, and close it. The map matters when something looks interesting — the user taps a pin, the map snaps to it, the spatial relationship resolves. Treating the map as a confirmation layer let us collapse the bottom tabs into a single feed-with-map-on-tap, which got the time-to-first-pin under two seconds on cold start.
The radius should remember itself. Each user's last-used radius is stored server-side, tied to their account, restored on every device. This sounds obvious. We didn't do it for the first month. The first month was full of complaints about "the radius keeps resetting." It never reset — we just didn't sync it across devices.
The biggest shift from this rebuild wasn't UX. It was internal. We stopped arguing about defaults. The slider made the default invisible; the user picks. Every time a stakeholder asks "what should the default radius be?" the answer is now "it doesn't matter — the user will tell us in the first 20 seconds." That's the kind of question hyperlocal products are supposed to stop asking.
ZetpinHyperlocalUXProduct
Have something ambitious in mind?
We reply to every email within 48 hours. Call or async, whichever you prefer.