Benchspot.xyz
A community-driven bench discovery app
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