What this project is really about
Every major route planning tool works the same way. You enter a start point, a distance, maybe a bike type. The algorithm finds the most efficient path between the constraints. Then it offers you three variations of the same route.
The problem is not the technology. It is the model. These tools treat personalization as a filter, a layer you add after the route exists. odo inverts this: rider intent is not a constraint on the route, it is the origin of the route. Scenery, surface, shade, wind, safety. Not preferences you toggle, but the inputs the route is generated from.
That changes the job. It is not a routing problem, it is a translation problem: turning a rider's intent into API parameters, weighted signals, and output a cyclist can verify. The design challenge was never the interface. It was the pipeline behind it, and making that pipeline legible enough to feel like a recommendation instead of a black box.
Cyclists don't want the fastest route. They want the right one for the ride they're in the mood for. Existing tools are technically robust but treat personalization as secondary: the output is minor path variations, not meaningfully different rides.
Designed an intent-to-route translation system: rider preferences for scenery, surface, shade, wind, and safety become weighted routing constraints, processed through live environmental APIs. The result is a set of named route profiles that generate genuinely different loops, not one route with slight variations. Grounded in research with 116 cyclists before design began.
A functional vertical slice prototype running on live APIs: OpenRouteService for routing and surface data, Shademap for time-based shade, custom elevation processing for gradients. The pipeline works with real data, not synthetic inputs. Differentiation against Garmin, Komoot, and Strava confirmed through a Blue Ocean analysis.
A market full of tools, none of them personal.
Cyclists plan rides in two settings. Familiar terrain runs on memory and habit. For unfamiliar terrain, a new region or a route beyond the usual range, they turn to digital tools. That is where the planning gap lives.
The existing tools are built for athletic tracking and for navigation during the ride, not for planning. Komoot filters by terrain type, Strava serves segment data to athletes, Outdooractive aggregates trails, Wikiloc crowdsources routes. All of them share the same underlying model: optimize for distance and time, then let the rider filter the results.
The result is a specific frustration that cyclists described consistently in our research: the tools give you options, but the options feel arbitrary. You don't know why the app chose this route, whether the scenic option is actually scenic, or which loop still has shade at 10am. Trust requires explanation. The current generation of route planners does not explain.
What 116 cyclists actually told us.
We started with a survey of 116 cyclists and nine in-depth interviews. Not as a formality: the results shaped the direction of the project, and in one case overturned an assumption we had walked in with.
The overturned assumption: we expected riders to be roughly split between loops and point-to-point routes. Instead, 82 of 116 preferred loops, across every rider type. That is not a small detail. Existing tools are built around paths. odo had to be built around loops from the ground up.
The priorities were just as clear: scenery and safety ranked highest, well above surface type and distance, for casual riders and athletes alike. Scenery, which almost no existing tool addresses meaningfully, is not a nice-to-have. It is often the reason people ride.
The interviews added the texture. Friction clusters around three moments: uncertainty about conditions before the ride, the inability to compare routes on the dimensions that matter during planning, and the effort of reconfiguring everything when the ride intent changes.
Profiles over parameters.
After research, the question was not which features to build. It was which model of personalization would actually work.
We explored three directions: adventure-driven routing built on novelty and discovery, safety-first routing that minimizes traffic exposure, and inspiration-driven routing curated by community and editorial input. All three had appeal. None captured what the research kept surfacing: ride intent changes day to day. The same cyclist wants a challenging mountain loop on Saturday and a flat scenic loop after work on Tuesday. A system built around a single intent cannot serve them both.
Route profiles were the answer. A profile is not a set of filters. It is a named intent, Scenic, Safe, Challenging or Balanced, that maps to its own combination of weighted signals, routing constraints, and avoidance criteria. Switching profiles does not reconfigure a form. It generates a different route from a different premise.
One tradeoff was deliberate: explainability over sophistication. An opaque scoring system would have been easier to build, but a rider who cannot understand a recommendation will not trust it on an unfamiliar ride. Every signal we use, shade at a given time, surface per segment, gradient, wind direction, is one a cyclist can verify. That verifiability is the trust mechanism.
The pipeline behind the profile.
The interface is simple. The system behind it is not, and the design work that matters is the data architecture. A route profile is a specification: select Scenic, and odo translates that intent into weighted API parameters. Maximize shade coverage, prioritize unpaved surfaces where available, minimize main road exposure, favor continuous elevation change over flat terrain. OpenRouteService generates candidate routes against those constraints.
The raw output is then enriched. Shademap computes actual shade coverage for the planned start time from topographic and building data. Elevation becomes per-segment gradient metrics in four tiers that match how cyclists think about climbs. Surface type comes from OpenStreetMap and maps to plain labels: paved, gravel, compacted dirt, technical trail.
Wind is the most behaviorally interesting signal. Cyclists care about wind direction relative to their route, not absolute speed. A tailwind out and a headwind home is a very different ride than the reverse. odo processes wind direction and route geometry together into a per-segment visualization: green above the axis for tailwind, red below for headwind. A rider can see, before starting, which sections will feel easy and which will hurt.
The output is not a score. It is labeled, segmented data the interface can show in plain terms. The system explains itself continuously, not as a disclaimer but as the product.
Stack
Next.js · React-Leaflet / Leaflet · OpenRouteService (routing, surface) · Shademap (time-based shade) · Custom elevation processing (gradient, segment classification)
Two flows, real data, live APIs.
We designed two entry flows for two planning realities the interviews kept describing: the rider with five minutes and the rider who wants to spend an hour.
Quick Start opens on the three profiles most differentiated for the current moment, each carrying one loop route regenerated daily against live conditions. Three meaningfully different rides every morning, no configuration. This is the five-minute flow.
Custom Ride is full control. Onboarding captures rider type, bike type, preferences and avoidances, a time window, and a starting point, then generates profiles for deep comparison before committing. This is the flow for planning a long weekend route in an unfamiliar region.
The prototype validated both flows on live API calls. No mocked data, no placeholder responses: routes came from real OpenRouteService queries, shade from Shademap against real topography for the query time, including edge cases where API constraints produced route geometries we had to design around. The pipeline works with real signals in real places. The concept is not theoretical.
Plan. Navigate. Improve.
The product loop has three phases, designed as a cycle rather than a one-shot experience. In the plan phase, the rider reviews the route before committing: difficulty, distance, elevation gain, duration, start time. The preview divides the route into segments with weather, surface, and gradient for each, highlighted on the map as the rider scrolls.
The navigate phase is a handoff. odo is a planning tool, not turn-by-turn navigation: a deliberate scope decision. odo generates the route, the bike computer runs the ride, and odo never competes with hardware where Garmin and Wahoo have deep advantages.
The feedback phase drives the long-term value. Post-ride, the rider rates segments and adjusts preferences, and the profile learns through explicit signals the rider controls, not opaque machine learning. Rate gravel sections poorly and they appear less. The profile updates the same way it recommends: visibly.
The architecture is the differentiation.
The most important thing we validated was not the interface. It was the feasibility of the underlying system.
Shade at a given time, surface per segment, gradient per section, wind relative to route geometry: every signal odo needs can be sourced from existing APIs and translated into labels a rider can trust, without proprietary data.
That is the core claim. Not a nicer route planner, but proof that intent-based routing works with available data, at consumer scale, without a data moat.
Blue Ocean differentiation
odo differentiates on four dimensions no existing tool covers simultaneously: intent-based routing instead of filters, visible signals instead of opaque scores, loops instead of paths, and profiles that adapt to rider feedback over time.
Control beats automation every time.
The clearest finding across the research: cyclists do not want the system to decide for them. They want to understand what it is doing, adjust it, and trust the output because they can trace it back to their own preferences.
That pushed explainability from feature to design principle. Every signal is visible, every label defined, every recommendation traceable. Harder to build than an opaque score, and meaningfully more trustworthy.
The second lesson is scope. A vertical slice, one city, four profiles, two flows, validated deeper than a broad prototype ever could. Depth beats width when the claim you are testing is feasibility.
Explainability is the feature.
Personalization only works when users understand why the system recommends what it does. The pipeline is the product. The interface is how you make it legible.


