Secure Bike Parking: Scoring Where to Lock Up
Published by Dan Richardson at https://freepdx.com/deep-dives/secure-bike-parking
- Team
- Two-person hackathon origin; production build-out led by Dan
- My contribution
- Production build-out owner
- Outcome
- A five-hour prototype became a public map and moderated data platform.
- Status
- Production: Expanding across US & Canada
- Constraints
- The ranking has to degrade safely when crime, imagery, or geocoding sources fail.
- Human review gates user reports and data imports before they affect public scores.
- The collaborator contributed to the hackathon origin; Dan owns the later production build-out.
The Problem
Some racks are theft magnets, some are safe. That knowledge lives in riders’ heads, not anywhere you can look it up. What if you could quickly say where you want to go, and then find the most secure place to park your bike when you got there?
What I Built
A map-driven guide that scores each parking spot by theft risk, visibility, and street-level imagery, and lets riders add spots of their own. Two surfaces: a public map and an admin moderation portal. It started as a two-person, five-hour hackathon build and grew into a roughly 500-commit platform.
Tech Stack
- TypeScript/TSX
- SQL
- JavaScript
- React 19
- Vite
- React Router
- Cloudflare Pages Functions
- Cloudflare Workers
- Cloudflare D1
- Cloudflare KV
- Cloudflare R2
- Cloudflare Queues
- browser localStorage
- npm workspaces
- Wrangler
- Cloudflare Pages preview branches
- Worker cron and queue consumer
- Anthropic Claude Haiku 4.5 for NL parsing
- explanation generation
- submitted-photo vision judging
- Vitest
- Playwright
- Node test runner
- TypeScript project references
- OpenAPI codegen drift check
- Leaflet
- leaflet.markercluster
- jose
- openapi-typescript
- exifr
- heic2any
- fflate
How It Works
The recommendation pipeline fuses several mismatched sources - Nominatim geocoding, OSM and Overpass spots, PortlandMaps crime data, Google Street View and Mapillary imagery - and scores each one. Claude vision judges the spots; a lighter model parses trip requests in plain language. User submissions run through a human-in-the-loop ingest pipeline. Both front ends generate their types from the same OpenAPI spec, and a codegen drift check fails if those types fall out of sync. Playwright separately covers the public and admin UI paths.
What Made It Hard
Fusing messy, mismatched geodata into one score a rider can trust. Building a moderation pipeline a human can actually review at speed. Keeping two independent front ends aligned with the same API through generated types, a codegen drift check, and end-to-end UI tests.
The Throughline
A civic tool for my own city: take scattered, hard-won local knowledge and make it usable in ten seconds by anyone. The shared API, generated types, codegen drift check, and UI tests let it grow without the public site and admin portal drifting apart.
Status
Live at securebikeparking.org, grown from the hackathon demo into a working platform.