Skip to content
Menu

Application case study · Cycling route planner

SikadNow PH

Planning the ride before the first pedal stroke.

A cycling route planner for riders in the Philippines. I built ordered route editing, cycling directions, terrain exploration, and private route storage, with a map-first workspace that connects the route to its elevation profile.

My role
Solo full-stack developer
Stage
In-development MVP
Intended audience
Cyclists planning rides in the Philippines
Scope
Route editing, provider integration, terrain, persistence, and rider profiles
SikadNow PH product presentation showing a cycling route map, private route dashboard, and mobile landing page.
A presentation of SikadNow PH's route-planning experience and product direction. Modeled effort mentioned in the artwork is planned, not an integrated feature. Displayed route numbers are examples, not validated terrain-accuracy claims.
On this page

Project status and evidence

Feature status is based on the supplied project documentation and its account of repository implementation. This portfolio review did not independently audit the application repository or production behavior. Effort analysis and AI coaching remain planned; no adoption or fitness outcomes are claimed.

Understand the route before riding it.

I built SikadNow PH as a solo full-stack project to help cyclists in the Philippines understand a route before riding it. The current implementation combines ordered stops, cycling-specific directions, terrain visualization, private route storage, and rider-profile management.

The longer-term product adds deterministic effort estimates and AI-written coaching. Those features remain planned: calculations will establish the numbers, while AI will explain them. The current project is an in-development MVP, not a completed integrated analysis product.

A ride is more than a start and finish.

A cycling plan can include a meeting point, water stops, climbs, and a finish location. A line between two points does not explain how those stops connect or what the terrain looks like. SikadNow's documented motivation is to bring cycling-specific routing and terrain information into one private planning workspace.

This is product framing rather than a formal comparison of mapping providers or a validated research persona. The application is a pre-ride planner: live GPS tracking, recorded ride activity, social feeds, native mobile apps, offline maps, and group planning are outside the current MVP.

Make stop order explicit
Let riders add, label, reposition, remove, and reorder the locations that define the ride.
Connect terrain to place
Show elevation and gradient information alongside the route, with controls that connect a chart point to a location on the map.
Keep future estimates transparent
Effort analysis needs an explicit rider target and clearly labeled assumptions. A route alone cannot determine how hard someone will ride.

One shared model, two editing experiences.

I owned the full-stack implementation, including page and component structure, route-editing interactions, routing-provider integration, persistence, authorization, rider profiles, and supporting tests. I separated the editable route from its calculated geometry and terrain so changed inputs and stale results could be handled explicitly.

The saved-route redesign makes the map the main workspace. A floating panel keeps route identity, save state, directions, and stops close to the route they affect. Desktop uses a utility rail; mobile uses a bottom sheet to preserve map context.

The new-route page retains its document-style editor. Both layouts share the editor controller rather than duplicating validation, save, and conflict behavior. The product's green and warm-yellow accents remain distinct from the portfolio's visual system.

SikadNow PH map-first route workspace with ordered stops, cycling directions, and terrain information beside a mobile presentation.
Route controls and terrain information stay close to the map they describe. Numbers in the presentation illustrate interface content; they are not independently verified route measurements.

Build, inspect, and return to the plan.

The current journey starts with Google sign-in and a private route collection. The rider names a route, adds and refines ordered stops, saves the draft, and then requests cycling directions in the saved-route workspace. They can inspect distance, elevation gain and loss, and gradients before returning to edit the plan.

Terrain charts and the map share a route cursor. Point selection, a range slider, and play/pause controls support exploration without relying solely on hover. Playback moves through terrain samples; its animation duration is not a modeled ride time.

Route history lists saved plans, not recorded rides. Loading states, field errors, save feedback, conflict recovery, and unsaved-change protection keep the next action visible when something goes wrong.

Build an ordered route
Place and label stops, move markers, and use move-up or move-down controls to define the intended route order.
Inspect cycling terrain
Choose a cycling profile, calculate directions, and explore synchronized elevation and gradient information.
Reopen and revise
Return to privately saved routes, resolve stale-edit conflicts, save changes, or delete a plan after confirmation.
SikadNow PH private route dashboard with saved route previews, alongside a laptop displaying a cycling route map.
The private route collection lets a rider return to saved plans. Route history represents planned routes, not recorded ride activities.

A calculation must belong to the current route.

Mapbox GL JS provides the interactive basemap; OpenRouteService supplies cycling directions and elevation; Recharts visualizes terrain. Next.js and React connect the interface to authenticated services, Auth.js manages Google sign-in, and Prisma with PostgreSQL persists owned routes, pins, profiles, and derived calculations. TypeScript and Zod define and validate the boundaries.

The architecture distinguishes editable input from derived output. Numeric analysis and future AI prose have separate records so narrative regeneration cannot overwrite calculations. Provider failures are surfaced as actionable states rather than substituted route or elevation data.

Stop order is domain data
Application validation checks contiguous order, reads sort explicitly, and database constraints protect uniqueness. Route and pin changes use transactions.
Conflicts are recoverable
Updates include an expected timestamp. Newer stored edits produce a conflict instead of a silent overwrite, while changed pins invalidate derived calculations transactionally.
Cache identity is correctness
Input hashes, routing profiles, and calculation versions govern reuse. A result is rejected if the route changes while the provider request is running.
Terrain normalization is explicit
Duplicate-distance samples are combined, interior elevation samples are smoothed, and gradients require a minimum baseline. These rules make processing testable, not a guarantee of real-world terrain accuracy.

Make assumptions and ownership visible.

Routes and rider profiles are private. Reads and mutations derive ownership from the active session rather than accepting a client-supplied owner identifier. Runtime schemas validate external input, and server-only provider and database credentials remain outside client modules.

Profiles store weight, experience, bike type, and optional FTP. Measured, user-entered, estimated, and unknown FTP remain distinct states. An optional coarse estimate requires confirmation and source attribution; it is not a substitute for an FTP test, and unknown FTP does not block route planning.

The planned effort layer requires a power, speed, or duration target. Deterministic, versioned calculations will establish estimates; the planned AI layer will explain them without revising numeric results. Cycling-profile output is not a guarantee of road safety or surface suitability.

A working foundation, with the roadmap in view.

The supplied documentation describes repository implementations and tests for route editing, persistence, directions, terrain, profiles, and supporting boundaries. Those are implementation outcomes, not evidence of planning-time savings, improved fitness, production use, or user satisfaction.

Verification covers pin-order rules, terrain normalization, cache identity, ownership, conflict recovery, and interface behavior. Some browser tests use fixture directions, so they demonstrate UI integration rather than live routing-provider behavior. Database and provider-dependent checks require their configured environments.

Implemented in the repository
Google authentication, ordered route editing, private persistence, cycling directions, terrain visualization, rider profiles, and supporting tests.
Incomplete or pending verification
Verified email/password authentication and rider-facing account recovery are incomplete. Complete live-provider, database, accessibility, and device acceptance still need recorded evidence.
Planned analysis
Modeled effort, ride time, calories, FTP zones, and Anthropic coaching are not yet an integrated feature. They remain separate from the current route-planning foundation.

Trust comes from the relationship between input and output.

The project showed me that a trustworthy route planner depends on the relationship between user input and derived data. A fast calculation is only useful when it still belongs to the current route. Shared map and chart context, explicit ordering, and recoverable conflicts make that relationship understandable.

The next steps are completing authentication, implementing deterministic effort analysis, and validating the integrated planning experience before adding narrative coaching. Observing riders complete the workflow would provide evidence about where they hesitate or misunderstand terrain; that validation has not yet been claimed.

Technologies used

  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • shadcn/ui
  • Auth.js
  • Prisma
  • PostgreSQL
  • Mapbox GL JS
  • OpenRouteService
  • Recharts
  • Zod