← Back home

Benchspot.xyz

A community-driven bench discovery app

Status Live →
Timeline 2024 — Present
Role Solo Developer

The Idea

I wanted a way to share my favorite spots in Toronto with friends — not restaurants, just quiet places to sit and think. Benches turned out to be the perfect unit for this.

Technical Highlights

Provisional bench system with spatial confirmation

Benches don't go straight to the database. They start as "provisional" and need confirmation before being promoted. The backend uses PostGIS ST_DWithin queries to find nearby submissions within a 2m radius, clusters them, and calculates the centroid when promoting to permanent status.

Direct-to-R2 uploads with presigned URLs

Instead of routing images through my server, I generate presigned S3-compatible URLs so browsers upload directly to Cloudflare R2. This keeps server bandwidth low and uploads fast.

Client-side HEIC conversion and image compression

iPhones shoot HEIC by default, which browsers can't display. The frontend converts HEIC → WebP using heic2any before upload. All images also get compressed client-side via canvas (1024px max, 70% quality) to keep storage costs down.

Deep linking for sharing

Each bench has a shareable URL (?bench=id). Opening a shared link flies the map to that bench and opens its popup automatically using Leaflet's flyTo.

PostgreSQL session store

Sessions are stored in Postgres via connect-pg-simple instead of memory, so users stay logged in across server restarts and horizontal scaling.

Tech Stack

  • Node.js
  • Express
  • PostgreSQL
  • PostGIS
  • Leaflet.js
  • Cloudflare R2
  • AWS SDK (S3)
  • Google OAuth
  • Passport.js

Features

  • Interactive map with geolocation
  • Photo uploads with HEIC support
  • 5-star rating system with PostgreSQL upserts
  • User profiles with progress rings
  • Gamification (trophies at 10, 50, 100 benches)
  • Native share sheet integration
  • Deep linking to specific benches

🪑 Visit benchspot.xyz