Skip to content

Syncing workout data from iOS to Statamic

In my post <activity-graph> (Web) Component I described my New Year's resolution to do some kind of workout 5 times a week and my journey to visualize it with the following graph:

20242025
January February March April May June July August September October November December January
Monday 01/01/2024 – Activities: 101/08/2024 – Activities: 101/15/2024 – Activities: 101/22/2024 – Activities: 101/29/2024 – Activities: 102/05/2024 – Activities: 002/12/2024 – Activities: 102/19/2024 – Activities: 002/26/2024 – Activities: 003/04/2024 – Activities: 103/11/2024 – Activities: 003/18/2024 – Activities: 003/25/2024 – Activities: 004/01/2024 – Activities: 004/08/2024 – Activities: 104/15/2024 – Activities: 104/22/2024 – Activities: 104/29/2024 – Activities: 005/06/2024 – Activities: 005/13/2024 – Activities: 005/20/2024 – Activities: 005/27/2024 – Activities: 006/03/2024 – Activities: 006/10/2024 – Activities: 006/17/2024 – Activities: 006/24/2024 – Activities: 007/01/2024 – Activities: 007/08/2024 – Activities: 007/15/2024 – Activities: 007/22/2024 – Activities: 007/29/2024 – Activities: 008/05/2024 – Activities: 008/12/2024 – Activities: 008/19/2024 – Activities: 008/26/2024 – Activities: 009/02/2024 – Activities: 009/09/2024 – Activities: 009/16/2024 – Activities: 009/23/2024 – Activities: 009/30/2024 – Activities: 010/07/2024 – Activities: 010/14/2024 – Activities: 010/21/2024 – Activities: 010/28/2024 – Activities: 011/04/2024 – Activities: 011/11/2024 – Activities: 011/18/2024 – Activities: 011/25/2024 – Activities: 012/02/2024 – Activities: 012/09/2024 – Activities: 012/16/2024 – Activities: 012/23/2024 – Activities: 012/30/2024 – Activities: 0
Tuesday 01/02/2024 – Activities: 001/09/2024 – Activities: 101/16/2024 – Activities: 101/23/2024 – Activities: 001/30/2024 – Activities: 102/06/2024 – Activities: 102/13/2024 – Activities: 002/20/2024 – Activities: 202/27/2024 – Activities: 103/05/2024 – Activities: 003/12/2024 – Activities: 203/19/2024 – Activities: 103/26/2024 – Activities: 104/02/2024 – Activities: 104/09/2024 – Activities: 004/16/2024 – Activities: 004/23/2024 – Activities: 004/30/2024 – Activities: 105/07/2024 – Activities: 105/14/2024 – Activities: 005/21/2024 – Activities: 005/28/2024 – Activities: 006/04/2024 – Activities: 006/11/2024 – Activities: 006/18/2024 – Activities: 006/25/2024 – Activities: 007/02/2024 – Activities: 007/09/2024 – Activities: 007/16/2024 – Activities: 007/23/2024 – Activities: 007/30/2024 – Activities: 008/06/2024 – Activities: 008/13/2024 – Activities: 008/20/2024 – Activities: 008/27/2024 – Activities: 009/03/2024 – Activities: 009/10/2024 – Activities: 009/17/2024 – Activities: 009/24/2024 – Activities: 010/01/2024 – Activities: 010/08/2024 – Activities: 010/15/2024 – Activities: 010/22/2024 – Activities: 010/29/2024 – Activities: 011/05/2024 – Activities: 011/12/2024 – Activities: 011/19/2024 – Activities: 011/26/2024 – Activities: 012/03/2024 – Activities: 012/10/2024 – Activities: 012/17/2024 – Activities: 012/24/2024 – Activities: 012/31/2024 – Activities: 0
Wednesday 01/03/2024 – Activities: 001/10/2024 – Activities: 001/17/2024 – Activities: 001/24/2024 – Activities: 201/31/2024 – Activities: 102/07/2024 – Activities: 002/14/2024 – Activities: 102/21/2024 – Activities: 002/28/2024 – Activities: 103/06/2024 – Activities: 003/13/2024 – Activities: 103/20/2024 – Activities: 003/27/2024 – Activities: 004/03/2024 – Activities: 004/10/2024 – Activities: 104/17/2024 – Activities: 104/24/2024 – Activities: 105/01/2024 – Activities: 005/08/2024 – Activities: 105/15/2024 – Activities: 105/22/2024 – Activities: 005/29/2024 – Activities: 006/05/2024 – Activities: 006/12/2024 – Activities: 006/19/2024 – Activities: 006/26/2024 – Activities: 007/03/2024 – Activities: 007/10/2024 – Activities: 007/17/2024 – Activities: 007/24/2024 – Activities: 007/31/2024 – Activities: 008/07/2024 – Activities: 008/14/2024 – Activities: 008/21/2024 – Activities: 008/28/2024 – Activities: 009/04/2024 – Activities: 009/11/2024 – Activities: 009/18/2024 – Activities: 009/25/2024 – Activities: 010/02/2024 – Activities: 010/09/2024 – Activities: 010/16/2024 – Activities: 010/23/2024 – Activities: 010/30/2024 – Activities: 011/06/2024 – Activities: 011/13/2024 – Activities: 011/20/2024 – Activities: 011/27/2024 – Activities: 012/04/2024 – Activities: 012/11/2024 – Activities: 012/18/2024 – Activities: 012/25/2024 – Activities: 001/01/2025 – Activities: 0
Thursday 01/04/2024 – Activities: 101/11/2024 – Activities: 101/18/2024 – Activities: 201/25/2024 – Activities: 102/01/2024 – Activities: 002/08/2024 – Activities: 102/15/2024 – Activities: 202/22/2024 – Activities: 002/29/2024 – Activities: 103/07/2024 – Activities: 103/14/2024 – Activities: 003/21/2024 – Activities: 103/28/2024 – Activities: 104/04/2024 – Activities: 004/11/2024 – Activities: 004/18/2024 – Activities: 004/25/2024 – Activities: 005/02/2024 – Activities: 105/09/2024 – Activities: 105/16/2024 – Activities: 005/23/2024 – Activities: 005/30/2024 – Activities: 006/06/2024 – Activities: 006/13/2024 – Activities: 006/20/2024 – Activities: 006/27/2024 – Activities: 007/04/2024 – Activities: 007/11/2024 – Activities: 007/18/2024 – Activities: 007/25/2024 – Activities: 008/01/2024 – Activities: 008/08/2024 – Activities: 008/15/2024 – Activities: 008/22/2024 – Activities: 008/29/2024 – Activities: 009/05/2024 – Activities: 009/12/2024 – Activities: 009/19/2024 – Activities: 009/26/2024 – Activities: 010/03/2024 – Activities: 010/10/2024 – Activities: 010/17/2024 – Activities: 010/24/2024 – Activities: 010/31/2024 – Activities: 011/07/2024 – Activities: 011/14/2024 – Activities: 011/21/2024 – Activities: 011/28/2024 – Activities: 012/05/2024 – Activities: 012/12/2024 – Activities: 012/19/2024 – Activities: 012/26/2024 – Activities: 001/02/2025 – Activities: 0
Friday 01/05/2024 – Activities: 101/12/2024 – Activities: 101/19/2024 – Activities: 001/26/2024 – Activities: 002/02/2024 – Activities: 102/09/2024 – Activities: 102/16/2024 – Activities: 002/23/2024 – Activities: 103/01/2024 – Activities: 103/08/2024 – Activities: 003/15/2024 – Activities: 103/22/2024 – Activities: 103/29/2024 – Activities: 104/05/2024 – Activities: 104/12/2024 – Activities: 104/19/2024 – Activities: 104/26/2024 – Activities: 105/03/2024 – Activities: 105/10/2024 – Activities: 005/17/2024 – Activities: 105/24/2024 – Activities: 005/31/2024 – Activities: 006/07/2024 – Activities: 006/14/2024 – Activities: 006/21/2024 – Activities: 006/28/2024 – Activities: 007/05/2024 – Activities: 007/12/2024 – Activities: 007/19/2024 – Activities: 007/26/2024 – Activities: 008/02/2024 – Activities: 008/09/2024 – Activities: 008/16/2024 – Activities: 008/23/2024 – Activities: 008/30/2024 – Activities: 009/06/2024 – Activities: 009/13/2024 – Activities: 009/20/2024 – Activities: 009/27/2024 – Activities: 010/04/2024 – Activities: 010/11/2024 – Activities: 010/18/2024 – Activities: 010/25/2024 – Activities: 011/01/2024 – Activities: 011/08/2024 – Activities: 011/15/2024 – Activities: 011/22/2024 – Activities: 011/29/2024 – Activities: 012/06/2024 – Activities: 012/13/2024 – Activities: 012/20/2024 – Activities: 012/27/2024 – Activities: 001/03/2025 – Activities: 0
Saturday 01/06/2024 – Activities: 101/13/2024 – Activities: 001/20/2024 – Activities: 101/27/2024 – Activities: 102/03/2024 – Activities: 002/10/2024 – Activities: 002/17/2024 – Activities: 002/24/2024 – Activities: 103/02/2024 – Activities: 103/09/2024 – Activities: 203/16/2024 – Activities: 003/23/2024 – Activities: 103/30/2024 – Activities: 104/06/2024 – Activities: 104/13/2024 – Activities: 104/20/2024 – Activities: 004/27/2024 – Activities: 105/04/2024 – Activities: 005/11/2024 – Activities: 005/18/2024 – Activities: 105/25/2024 – Activities: 006/01/2024 – Activities: 006/08/2024 – Activities: 006/15/2024 – Activities: 006/22/2024 – Activities: 006/29/2024 – Activities: 007/06/2024 – Activities: 007/13/2024 – Activities: 007/20/2024 – Activities: 007/27/2024 – Activities: 008/03/2024 – Activities: 008/10/2024 – Activities: 008/17/2024 – Activities: 008/24/2024 – Activities: 008/31/2024 – Activities: 009/07/2024 – Activities: 009/14/2024 – Activities: 009/21/2024 – Activities: 009/28/2024 – Activities: 010/05/2024 – Activities: 010/12/2024 – Activities: 010/19/2024 – Activities: 010/26/2024 – Activities: 011/02/2024 – Activities: 011/09/2024 – Activities: 011/16/2024 – Activities: 011/23/2024 – Activities: 011/30/2024 – Activities: 012/07/2024 – Activities: 012/14/2024 – Activities: 012/21/2024 – Activities: 012/28/2024 – Activities: 001/04/2025 – Activities: 0
Sunday 01/07/2024 – Activities: 101/14/2024 – Activities: 101/21/2024 – Activities: 101/28/2024 – Activities: 002/04/2024 – Activities: 102/11/2024 – Activities: 202/18/2024 – Activities: 102/25/2024 – Activities: 103/03/2024 – Activities: 003/10/2024 – Activities: 103/17/2024 – Activities: 103/24/2024 – Activities: 103/31/2024 – Activities: 104/07/2024 – Activities: 204/14/2024 – Activities: 104/21/2024 – Activities: 204/28/2024 – Activities: 105/05/2024 – Activities: 105/12/2024 – Activities: 205/19/2024 – Activities: 005/26/2024 – Activities: 006/02/2024 – Activities: 006/09/2024 – Activities: 006/16/2024 – Activities: 006/23/2024 – Activities: 006/30/2024 – Activities: 007/07/2024 – Activities: 007/14/2024 – Activities: 007/21/2024 – Activities: 007/28/2024 – Activities: 008/04/2024 – Activities: 008/11/2024 – Activities: 008/18/2024 – Activities: 008/25/2024 – Activities: 009/01/2024 – Activities: 009/08/2024 – Activities: 009/15/2024 – Activities: 009/22/2024 – Activities: 009/29/2024 – Activities: 010/06/2024 – Activities: 010/13/2024 – Activities: 010/20/2024 – Activities: 010/27/2024 – Activities: 011/03/2024 – Activities: 011/10/2024 – Activities: 011/17/2024 – Activities: 011/24/2024 – Activities: 012/01/2024 – Activities: 012/08/2024 – Activities: 012/15/2024 – Activities: 012/22/2024 – Activities: 012/29/2024 – Activities: 001/05/2025 – Activities: 0
Less (0)
Activities: 0
Activities: 1
Activities: >2
More (>1)

While the whole article was about how to create this component, I didn't cover how to get the data into Statamic - but I will now.

Part 1: Finding an appropriate workout app

In my previous attempts to improve my fitness, I enjoyed using "Runtastic Results", which became "Adidas Training", which unfortunately was deprecated earlier this year. I tried Apple Fitness+, but their video format with music drove me crazy. After trying many other apps, I finally settled on [Seven by Perigee] (https://seven.app) for the following reasons

  • concept (exercise, pause, exercise, pause...)
  • simple, animated instructions
  • appropriate training plans + challenges
  • customizable workouts
  • no built-in music
Screenshot of Seven app – showing an 3D animated men. On top headline "Side Leg Swings", 28 seconds and 0 calories burnt. In addition a progress ring is shown around the animation.
Screenshot of iOS App "Seven"

Part 2: Getting data from Apple Health with Shortcuts

Seven stores all of its training data in Apple Health – and I expected to be able to grab thata data with an iOS Shortcut using the "Find Health Samples" action. Actually, there's a huge list of data you can get from the Health app, from "Abdominal Crimps" to "Dry Skin" to "Zinc". But apparently there's no way to get the training data I need... so I had to buy the app Toolbox Pro, which offers a bunch of new actions – including "Get workouts from Health". 🙈
After some low code wrangling, I was finally able to set up a working filter, populate a dictionary and prepare my final step: POSTing the data to my website. (You can download the final Shortcut from iCloud.)

Overview of iOS Shortcut containing "Get HIIT workouts from Health", Repeaters and finally "Get Contents from Endpoint".
Screenshot of final Shortcut

Part 3: Setting up an API endpoint

My website is powered by Statamic which is based on Laravel. To get my data into it, I did the following:

  1. Set up a global blueprint (activity.yaml) with a replicator containing a key/value pair, where the key is the date of my workout and the value is its ID.
  2. Create a /update-trainings API route (api.php) that calls the TrainingController.
  3. The TrainingController analyzes and optimizes the data (e.g. adjust late night trainings to count for the day before) and calls...
  4. ...RefreshCacheJob, which I set up to refresh the static cache of provided pages in a background job, in this case to refresh the relevant blog articles which contain the component.

This endpoint could now be called from the Shortcut containing the correct data (see screenshot above).

Part 4: Semi-automating the sync

With iOS you can set up automations – and I wanted to synchronize the data on a daily basis. Unfortunately, I was confronted with an unfortunate message:

iOS error messages:
Shortcuts Automation encountered an error:
Could Not Run "Get Workouts"
There was an error trying to read workouts.
iOS Lockscreen showing error

Apparently Toolbox Pro is not able to get the data when the screen is locked.

Luckily I had a trick: My daughter (3 years old) often does the workout with me in slight variations. She is always in charge of pressing the big button to start the workout - and now I have given her another important task: to press the big red button on the home screen at the end of the workout to start the shortcut. Since kids love any chance to press things on touch devices, I'm 100% sure my data will be synchronized often enough. 👨‍👧

Conclusion

While I like low code, struggling with the Shortcuts interface, having to buy an additional app to get my workout data AND not being able to fully automate the sync feels weird. In comparison, setting up the Laravel API for my website was really fun and I'm pretty sure more APIs will follow 😊.

By the way: This is the first blog post I'm publishing with my new automated OpenGraph image setup, which I'll be writing about soon – follow me on Mastodon or via RSS to be informed when it's published.

Reactions on Mastodon Post:

7
1
3