This is a submission for Weekend Challenge: Earth Day Edition
What I Built
CommuteShare
A cycling route-matching app that help finds other commuters who share a meaningful stretch of road with you.
Why
I honestly believe that if we can make cycling as a mode of commute easier, we can the environment. Not just by reducing the fossil fuel consumption but also by reducing noise pollution. It will definitely reduce the road congestion and improve commute time when commuting for a short distance. And if we can help more people adopt cycling as mode of commute we will be helping our planet a little more.
Being an avid cyclist I have faced lots of issue during my commute ride: lack of infrastructure, lack of empathy towards cyclist, lack of shower/changing facilities in workplaces.
But the issue that I think stops quite a lot of people even after they have dipped their toes into commute by cycling is the boring nature of it. Riding twice a day for upto 5 times a week on same route day in day out can become boring and demotivating fast.
To overcome the issue of boredom I have thought of this app which can bring people to ride together and enjoy the company or just the quite confidence that someone else is there with them. That motivation is a big emotional booster.
What's new?
But most ride-sharing apps match on origin and destination. CommuteShare matches on the full route geometry — two riders are compatible if they share a real stretch of road and cycle at compatible speeds. The idea: if you're both riding the same 3km or 15 min corridor every morning, why not do it together?
How it works
- Draw your cycling route directly on the map (click to add waypoints)
- Set your speed range and departure window
- Hit Find Matches — the app finds compatible riders and highlights the exact shared road segment
- Click any match to fly the map to that route
- New rides from other users appear in real time as fuchsia dashed lines — no page refresh needed
What makes it technically interesting
Routes are stored as GPS polylines. Checking overlap isn't as simple as "do these lines cross?" — two routes can cross at a single point without sharing any meaningful road. What you actually want to know is: how long would these two riders spend side by side?
CommuteShare estimates this by sampling 50 evenly-spaced points along each candidate route and counting how many fall within 400m of the query route. That ratio gives an estimated shared distance, which converts to shared riding time at the rider's average speed. If you'd spend at least 5 minutes riding together — it's a match.
Live ride updates are powered by Server-Sent Events — a lightweight real-time push mechanism that doesn't need WebSockets. Open two browser tabs, post a ride in one, and it appears on the other map within a second.
Tech stack
| Layer | Technology |
|---|---|
| Backend | Go 1.22, chi router |
| Database | PostgreSQL 15 + PostGIS |
| Frontend | React 19, Vite |
| Map | Leaflet + react-leaflet |
| Real-time | Server-Sent Events (SSE) |
Demo
Code
How I Built It
I started with the hardest part first — the matching algorithm — and worked outward from there.
The matching algorithm
The first question was: how do you check if two cycling routes share a meaningful stretch of road?
Routes are stored as GPS polylines in PostGIS. The obvious answer is ST_Intersection — compute the geometric overlap directly. I tried it. It silently returned empty geometries. Turns out GEOS 3.9.0 (the geometry library bundled in the standard PostGIS Docker image) has a bug where ST_Intersection returns empty when a line is fully contained inside a polygon. Dead end.
The workaround: point-sampling. Instead of clipping geometries, I interpolate 50 evenly-spaced points along each candidate route and count how many fall within 400m of the query route. That ratio estimates shared distance, which converts to shared riding time. If you'd spend at least 5 minutes riding together — it's a match. Same result, no broken geometry functions.
The shared segment overlay (the white line showing exactly where two routes overlap) is built the same way — collect the close-sampled points and join them into a LineString with ST_MakeLine.
Backend
Go with chi router, three strict layers: handler → service → repository. Handlers never touch the DB. Repository never touches HTTP. This kept the code easy to reason about under time pressure.
The SSE live feed was the last piece. The hub is a simple map[chan []byte]struct{} with a mutex — new rides are pre-marshalled to JSON and fanned out to all connected subscribers non-blocking. If a client is slow, it gets dropped. For a local demo, that's fine.
One gotcha: the Vite dev proxy doesn't reliably forward SSE streams. The frontend EventSource connects directly to localhost:8080, not through the proxy — with CORS explicitly allowing localhost:5173.
Frontend
React 19 with react-leaflet. All state lives in App.jsx. The map has two modes — draw mode (click to add waypoints) and view mode (show posted ride, matches, shared segments, live rides). Switching between them is a single boolean.
The render layer order in JSX matters for z-index: live rides sit above the posted ride but below match routes, so they're visible over seed routes but don't obscure match labels.
Architecture Summary
View full architecture breakdown
Using Claude as a collaborator
I used Claude Code throughout — not to write code blindly, but as a pair programmer. I'd describe what I was trying to build, we'd work through the approach together, and I'd push back when something didn't fit. The PostGIS bug investigation, the SSE hub design, the color scheme iterations — all of that happened in conversation.
The architecture documentation you see in this post came out of those sessions too. Working with an AI that could hold the full context of the project across a weekend made it possible to ship all three features (shared segments, click-to-focus, live feed) in the time available.
Prize Categories
Not Applicable
Top comments (0)