Runcast: finding the best time to run

September 26, 2026

View code
Find the best time to run your route. Connect Strava and set your availability so Runcast can find favorable conditions that fit your schedule.
Read the walkthrough
48-second silent video with on-screen captions. Start on Explore and open the route picker. Choose Connect Strava, open the account connection, and continue through the iOS sign-in prompt. The Strava page separates available routes from imported routes. Import Windsor Castle, then select Open to see its map and run overview. Tap the bell and confirm. On the route's watch page, open the schedule options and review the weekly planning schedule, including separate morning and evening windows. Return to the route settings and select Start watching. The route then appears in the watch list with its distance, estimated duration, and watching status.

I built Runcast because I wanted to figure out the best time to go for a run. A traditional weather app shares a stationary forecast tied to one geographical location and time. I wanted an app that estimates the conditions I would encounter along a route at different start times.

That became a project spanning weather modeling, mobile development, and backend systems. I designed and built the planning engine and the application around it, from importing routes through Strava to evaluating them against a runner's schedule. Runcast estimates conditions throughout a run and recommends when to leave, with enough of the underlying forecast visible to understand the choice.

Building a forecast around the run

The part I found most interesting was turning a route into something I could evaluate against the weather. A runner moves through both distance and time. Wind changes its effect as the route turns, hills affect when the runner reaches a location, and a later departure changes the conditions across the whole run. I built the engine around that relationship.

The model combines route geometry and elevation with expected pace, then estimates the weather at the points the runner will pass. I use Open-Meteo forecasts and interpolate measurements across location and time. On top of that, I calculate wind relative to the direction of travel and estimate sun exposure using solar position, radiation forecasts, and available tree canopy evidence. Where canopy data is missing, the model assumes open-sky exposure.

Once I could evaluate a run, I could compare possible departures within the runner's availability. The engine checks forecast coverage and hazardous conditions before ranking suitable times. Building this myself gave me control over how those decisions are made and how the app explains them. Someone can look at the weather along the route and decide whether the recommendation makes sense for them.

Making it useful during the week

I wanted Runcast to fit around the routes people already run and the time they actually have. Strava integration brings in saved routes, while a shared planning schedule gives the recommendations a practical constraint. The app also works with bundled routes and local GPX files before someone connects an account.

Route watches grew out of that idea. Once the app knows a route and when someone is available, it can keep evaluating opportunities to run. This extended the project into a system that can do useful work in the background and bring a recommendation back to the runner.

I spent time deciding how much of that complexity should appear in the app. The runner sets their availability; the application handles when to evaluate and notify. A recommendation has its own focused view, with the detailed run plan available when someone wants to understand the conditions more closely. I wanted the main decision, when to leave, to stay easy to find as the model and system became more involved.

Get a recommended time to run, with the forecast to back it up. Open the alert to explore the conditions expected along your route from start to finish.
Read the walkthrough
30-second silent video with on-screen captions. A native iOS notification appears on the black lock screen for Windsor Castle, recommending a 6:00 AM start. Open the alert to see the Run recommendation page. It shows the route's 5.09-mile distance, a 45-minute run at 8:50 per mile, and a 6:45 AM estimated finish in London time. The sample forecast shows 54°F air temperature, no estimated sun intensity, a 10% peak rain chance, and 7 mph peak gusts. Select View run plan. The detailed plan keeps 6:00 AM selected and marks it as the day's recommendation. Scroll down to Along the route. A route map sits above rows for air temperature, sun, wind, rain, and hills. The video pauses with the whole card visible.

Building the system behind it

I built the mobile app with React Native and Expo, supported by a Fastify API and PostgreSQL. One of the most useful architectural decisions was keeping the planning engine in an independent TypeScript package shared by mobile, the web client, and the backend. The same model powers interactive planning and scheduled recommendations, and I can test the calculations without involving a screen or a network request.

That separation also helps keep the app responsive. With forecast data cached, it can compare another departure locally. The backend handles data refreshes and scheduled evaluations, so trying different times in the app doesn't depend on repeatedly calling the weather provider.

Forecast changes introduced a more difficult problem: a notification can outlive the recommendation it describes. I designed evaluations as saved results, so an alert continues to open the advice that produced it. Newer results are available separately. This preserves the context of the original message while still letting the runner act on updated information. I also separated recalculation from notification delivery, with a limited follow-up policy for meaningful changes rather than an alert for every update.

Reliability required work on both sides of the connection. The backend stores pending notification deliveries in a database outbox so a worker can resume after a restart. On the device, pending edits live in durable SQLite storage. The API handles repeated requests and checks record versions so reconnecting doesn't silently duplicate an operation or overwrite a newer edit. These choices let the system recover from interruptions while keeping track of what the runner asked it to do.

I enjoyed building Runcast because I got to work through a modeling problem and turn it into an app that helps people plan their runs. I focused on two things: giving runners a fuller picture of the weather conditions along their route and presenting that information clearly. The app is still in beta, and I’m working to get more people using it so I can learn from their feedback and decide what to build next!