Photo Location Guard

Reads a photo's EXIF and XMP before upload and offers one-tap location removal, so a picture doesn't reveal where and when it was taken.

StopsPhoto leaked my home location

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/photo-location-guard.json

The files land in your project. They're yours to edit.

Usage

photo-location-guard-usage.tsx
import { PhotoLocationGuard } from "@/components/ui/photo-location-guard"

<PhotoLocationGuard label="Add a photo to your post" value={photo} onValueChange={setPhoto} describeLocation={placeName} />

What it catches

  • GPS coordinates, with how precise they are
  • Capture time and time zone
  • Camera serial number and owner name
  • Embedded preview that can show the uncropped original
  • XMP location fields

Props

PhotoLocationGuard props
PropTypeDefault
value

Controlled photo.

File | null—
defaultValue

Initial photo when uncontrolled.

File | nullnull
onValueChange

Called with the chosen photo, and with the cleaned copy after "Remove location".

(file: File | null) => void—
describeLocation

Optional reverse geocoder, e.g. `(lat, lon) => "Shivajinagar, Pune"`. Without it only coordinates are shown.

(latitude: number, longitude: number) => string | Promise<string>—
mapUrl

Map link for the coordinates. Return "" to hide it.

(latitude: number, longitude: number) => stringosm
locale

Locale for the capture time.

string—
quality

JPEG quality of the cleaned copy, 0–1.

number0.92
label

Visible label.

string"Photo"
chooseLabel

Button text to choose a photo.

string"Choose a photo"
changeLabel

Button text to pick a different photo.

string"Change"
title

Heading over the findings when the photo has a location.

string"This photo shows where it was taken"
detailsTitle

Heading when there's no location but other details.

string"This photo carries hidden details"
removeLabel

Button text to remove location data.

string"Remove location"
removeHint

Explains what removing does.

string"Also removes the time, camera details and hidden preview."
removingLabel

Button text while removing.

string"Removing…"
removedText

Shown after location is removed.

string"Location removed. Checked the new file: nothing left to …
cleanText

Shown when nothing revealing is found.

string"No location or camera details in this photo."
errorText

Shown when the file can't be read.

string"Couldn't clean this photo. Try exporting it without loca…
unsupportedText

Shown for a file type it can't read.

string"Only JPEG photos are checked for location."
labels

Row names and small texts in the findings list.

Partial<typeof DEFAULT_LABELS>—

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • File input has a visible label and buttons to choose or change
  • Findings are in a polite live region; the details list is labelled
  • Remove shows aria-busy while working; errors use role=alert

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Strip metadata on the server too before publishing uploads; a client-side strip can be skipped.

  • Reads JPEG metadata; other formats show an unsupported notice
  • Re-encoding drops all metadata and slightly changes image quality
  • Can't remove location visible in the picture itself (street signs, landmarks)

What it stops

Photo leaked my home location

Also known as

exif · gps · photo upload · image metadata · privacy · location · avatar upload · marketplace photos

Field type

Dependencies

Pairs well with