January 2025. We sat down and estimated the project at
two to three months. The plan was:
- Calendar view. How hard can be?
- Plan generator. ChatGPT can write one from a single prompt, right?
- Push the workouts into Apple Fitness via whatever API Apple provides. Third-party push to Garmin all the time.
Both assumptions turned out to be wrong, in
different ways:
- Apple Fitness has no API for pushing structured workouts. No equivalent of Garmin Connect’s training API in the Apple ecosystem. To run a structured workout on Apple Watch you have to build your own Watch app that creates and executes the workout via HealthKit’s lower-level primitives. .
- Garmin Connect has an API, but it’s not free. Their workout push API is behind a paid developer program (~€ 450/year), requires applying and being approved, and uses Monkey C. We saw running apps integrating with Garmin and assumed the path was open. It is — but you pay for it.
ChatGPT-generated plans look reasonable but aren’t structurally consistent — fine for a casual user, wrong for a real training tool (full version:
The 308 Fartleks). And SwiftUI calendars are fine when you’re using one for show — the moment you need a real month-grid that scrolls, scales, marks events, and syncs with data updates from a Watch app,
you’re writing it from scratch.
Run Plan started as Katya's MVP while she was training for the Amsterdam Marathon (October 2025). I joined a few weeks later. First commit in our shared repo: April 2025. Current version on the App Store: v1.10, May 2026.
Thirteen months of evenings and weekends from a 2-person part-time team.
"Two to three months" was off by a factor of about six.
The early architecture was, generously,
"make it work." Everything sat in one big file, with UI mixed into logic and CoreData fetches inside view bodies. We had:
- A PlanUtils file that eventually grew to >2,000 lines — plan generation, distribution, AND configuration.
- A ContentViewWrapper that owned all app state via dozens of @State properties.
- JTCalendar (a UIKit OSS library) for the calendar view.
- A single Watch app target wired directly to CoreData.
It worked. It was fragile. We knew it. We didn't have time to fix it.
The story of Run Plan’s architecture is mostly the story of
paying back that early, three or four big refactors at a time.