Skip to content

feat(api): geocode member city/region to lat/long on save #1972

@cdcore09

Description

@cdcore09

Summary

profiles already has city, region, countryId, latitude, longitude, and showOnMap columns, but latitude/longitude are never populated automatically — they exist only because someone manually wrote to them. A geocoding pipeline should run on profile address changes so map placement just works.

Requirements

  • On PATCH /me/profile (packages/api/src/routes/me.ts): when city, region, or countryId changes, enqueue or inline-call a geocoder
  • On PATCH /admin/users/:id (packages/api/src/routes/admin/users/byId.ts): same trigger when an admin edits the address fields
  • Geocoded values write to profiles.latitude / profiles.longitude; if the geocode fails (no result, rate-limited, network error) the existing lat/long stays put and we log the failure
  • A nullable profiles.geocoded_at timestamp records the last successful geocode — distinguishes "never tried" from "tried, no result"
  • Backfill script packages/api/scripts/geocode-profiles.ts for the existing roster: iterate over profiles with city + country and no lat/long
  • Geocoder choice (Nominatim vs Mapbox) decided in coordination with feat(admin): add addresses + geocoding to organizations #1969 — orgs and members should use the same one

Context

profiles.{city, region, countryId, latitude, longitude} already exist (packages/api/src/db/schema/users.ts:103-115). The map plumbing on the web app reads these — populating them is the missing link.

Pairs with #1969 (org-side addresses + geocoding) — same pipeline serves both.

Implementation Notes

Nominatim has a 1 req/sec public rate limit + a User-Agent header requirement; that's plenty for an admin PATCH but means the backfill script needs a setTimeout delay between calls. Mapbox is faster but needs an API key + budget. Decide once for both #1969 and this issue and reuse the same lib/geocode.ts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions