Skip to main content

Location & Nearby — Technical Reference

← Back to Location & Nearby

Where this lives

Backend

Frontend

Real bugs fixed while building this

user-location.manager.js called four methods on user-location.access-service.jsfindByUserId, getAll, getByCity, getByCountry — that did not exist on that class at all (it only had findById/findByUser/create/update/updateByUser/delete). Every manager method that touched location data (getLocation, updateLocation, deleteLocation, getNearbyUsers, searchByLocation, getPopularLocations) would have thrown TypeError: ...is not a function on first real call. Added the four missing methods as thin wrappers.

getNearbyUsers returned every user's exact coordinates with no privacy filter, even though UserLocation.isPublic defaults to false specifically so a user's location isn't shared until they opt in — a real privacy leak if this had shipped as originally written. Fixed to filter on isPublic === true.

canSeeLocation() and setLocationPrivacy() are unfinished — canSeeLocation is three // TODO comments that always return true, and setLocationPrivacy writes to a privacy_level column that doesn't exist on the UserLocation model (Sequelize silently drops unknown attributes on .update(), so it was a silent no-op). Neither is exposed by this GraphQL layer — isPublic (a plain boolean) is the only location-privacy control the model actually persists and enforces. A three-tier public/friends/private level, if wanted later, needs a real column and real enforcement in canSeeLocation first.

updateLocation previously never touched isPublic at all (always left it at the model's false default on create, never updated it) and wrote to a nonexistent accuracy column. Fixed to accept and persist isPublic.

Technical implementation checklist

  • myLocation / updateMyLocation / deleteMyLocation — wired; LocationSharingPage.tsx
  • nearbyUsers — wired, filtered to isPublic: true opt-ins only; used by LocationSharingPage.tsx's "People nearby" list and DiscoverPeoplePage.tsx's "Cerca de ti" section (RecommendationsSection.tsx also has a nearby tab, but its tab bar is currently hidden so that path isn't reachable from the UI)
  • Local feed by radius (getLocalFeed in the manager) — not exposed in GraphQL
  • Search by city/country or coordinates (searchByLocation in the manager) — not exposed in GraphQL
  • Popular locations & location stats (getPopularLocations/getLocationStats in the manager) — not exposed in GraphQL
  • Tiered location privacy (public/friends/private) — setLocationPrivacy/canSeeLocation are unfinished stubs; only a binary isPublic toggle is real today
  • Static location sharing within chat messages (shareLocation) is a separate feature that's now wired — the composer's "share location" quick action in ChatView.tsx (handleShareLocation) calls it, and MessageBubble.tsx renders the resulting location message. Live location broadcasting (updateLiveLocation/stopLiveLocation) resolvers also exist in message.resolver.js, but nothing in the frontend calls them yet and LocationInput still has no locationType field to mark a message as live; see Messages & Conversations

UserLocation model

FieldDescription
latitude / longitudeCoordinates (WGS84), DECIMAL(10,8)/DECIMAL(11,8)
city / countryHuman-readable location (optional, not reverse-geocoded server-side — the frontend doesn't send them today)
isPublicBoolean, defaults to false. The only privacy control that's actually enforced.

Sharing and updating location

mutation UpdateMyLocation($input: UpdateLocationInput!) {
updateMyLocation(input: $input) { id city country latitude longitude isPublic updatedAt }
}

query MyLocation { myLocation { id city country latitude longitude isPublic updatedAt } }

mutation DeleteMyLocation { deleteMyLocation }

UpdateLocationInput: latitude: Float!, longitude: Float!, city: String, country: String, isPublic: Boolean (defaults to false/private on first share if omitted). Call updateMyLocation again with the same coordinates to just flip isPublic without re-requesting the browser's geolocation permission.

Nearby users

query NearbyUsers($radiusKm: Float, $limit: Int) {
nearbyUsers(radiusKm: $radiusKm, limit: $limit) {
user { id username profilePicture isVerified }
distanceKm
city
}
}

Requires the caller to have shared their own location first (myLocation must be non-null) — nearbyUsers returns [] otherwise. Only returns other users with isPublic: true, sorted by distance, computed via the Haversine formula in user-location.manager.js#calculateDistance.