Skip to main content
Back to Projects

Photography Portfolio Site

An automated photography pipeline that extracts GPS data from images, reverse geocodes locations, optimizes for the web, and presents them in a responsive gallery

Next.jsTypeScriptSharpEXIF ReaderOpenStreetMapTailwind CSSReact Query

The Idea

Travel is how I learn about the world. Every country I visit adds a layer — a new perspective on how people live, what they value, and how places feel. I wanted a gallery that captured that: not just a folder of images, but a visual record of curiosity-driven exploration across 60+ countries.

The challenge was making it feel intentional without making it manual. I had hundreds of photos, each with GPS coordinates already embedded in their EXIF data. I wanted a pipeline that could extract that data, reverse geocode it to a real city and country, optimise each image for the web, and present them in a browsable, searchable gallery — automatically.

The Challenge

GPS Extraction at Scale

Parsing EXIF metadata from 198+ JPEG files to extract GPS coordinates, handling missing or malformed data gracefully.

Reverse Geocoding

Converting raw latitude/longitude into human-readable city and country names using OpenStreetMap's Nominatim API with rate limiting.

Image Optimization

High-resolution travel photos are often 5-10MB each. Needed a pipeline to resize and compress without losing visual quality.

Gallery UX

Building a responsive grid with category filtering, full-screen lightbox with keyboard navigation, and preloading for smooth browsing.

How It Works

1

EXIF Extraction

A TypeScript processing script reads each photo's EXIF data using the exif-reader library, extracting GPS coordinates, date taken, and camera settings.

2

Reverse Geocoding

GPS coordinates are sent to OpenStreetMap's Nominatim API to resolve city and country names. The script handles rate limiting and caches results to avoid redundant lookups.

3

Image Optimization

Sharp resizes photos to web-friendly dimensions and compresses them while maintaining visual quality. Original files are preserved; optimized versions are served to visitors.

4

Manifest & Gallery

All metadata is compiled into a JSON manifest that powers an API route. The React gallery reads from this API, rendering a responsive grid with category filtering and a lightbox viewer.

Key Features

Automatic GPS Tagging

City and country extracted from photo EXIF data automatically

Reverse Geocoding

GPS coordinates resolved to readable locations via OpenStreetMap

Category Filtering

Browse photos by country with one-click category filters

Lightbox with Preloading

Full-screen viewer with keyboard navigation and adjacent image preloading

Image Optimization

Sharp-based resize and compression for fast page loads

Responsive Grid

Adaptive layout from 1 to 4 columns based on screen size

Tech Stack

Next.js & TypeScript

Full-stack framework powering the gallery page, API routes, and processing scripts with type safety throughout.

Sharp

High-performance image processing library for resizing and compressing photos while maintaining visual quality.

EXIF Reader & OpenStreetMap

EXIF metadata extraction for GPS coordinates, paired with Nominatim reverse geocoding to resolve locations.

React Query & Tailwind CSS

Server state management for gallery data fetching, combined with utility-first styling for the responsive grid and lightbox.

What I Learned

Building this gallery taught me several valuable lessons about working with media at scale:

  • Image Optimization Pipelines: The difference between serving raw photos (5-10MB) and optimized versions (100-300KB) is night and day for user experience. Sharp made this straightforward but the configuration choices matter.
  • EXIF Metadata is Messy: Not every photo has GPS data, and the format varies between camera models. Building robust fallback handling was essential.
  • Reverse Geocoding at Scale: Rate limiting and caching are critical when hitting external APIs for hundreds of requests. Respecting Nominatim's usage policy while keeping the pipeline fast required careful throttling.
  • Lightbox UX Patterns: Keyboard navigation, image preloading, and body scroll locking are small details that make a gallery feel polished and professional.

Explore the Gallery

Browse 198+ travel photos from across the globe, automatically tagged with location data.