The Premise
Music naturally uplifts a workout. If you work out a lot you might run out of music to listen to and if you don't work out a lot it might be motivating to find some new music that gets you moving.
So the premise overall is simple: help people find new workout music to help get them going.
The app's primary hook was blending heart rate data from workouts with the music you listen to during your workout. This combination, dubbed "a musical heartbeat", is the voting mechanism for the workout tracks you listen to; this voting mechanism surfaced a weekly playlist that live updated on Spotify as well as an in-app discovery surface for new tracks.
Key App Features
- Heartbeat Voting: Each song is ranked based on the musical heartbeats attributed to it. A musical heartbeat is a beat of someone's heart during a workout while listening to a given song.
- Heart Charts: A live updating Spotify playlist that mapped to the most listened to workout tracks that week. As a user finished their workout, their heartbeat votes would change the order of tracks.
- Monthly Slaylist: A user's slaylist is a playlist that tracks the workout songs they listened to each month.
- Works in the background: Users can bring their own workout app and don't have to start a workout in our app. All dj heartbeat requires is a one-time Spotify auth and Apple Health permission. This was a key component because it's a lot to ask a user to switch from using whatever workout app they're using to use this one.
I really like this sync'd transition for tapping between this/last week's community heartbeat count, which also updated the currently displayed playlist.
Technical Overview: Primary Happy Path
Technical Bits
- Firebase worked well for this app's v1 — especially due to the out-of-the-box infra like logging, auth, and simple backend functions. Using more ad-hoc tooling would mean a bit more setup cost, as opposed to the "just works" nature of Firebase.
- SwiftUI in 2024 was maturing well. This was my second SwiftUI app and overall it was a nice experience. Using MVVM worked well for architecture. Previews are nice. I wish Apple had a built-in architecture concept of a ViewModel type like Android's; some say that's what SwiftUI offers, but it falls short of the separation of concerns that Android's ViewModel offers, e.g., testing a VM vs. loading/testing an entire SwiftUI view.
- Working with device-specific data can be a pain — e.g., here the key app flow involves HealthKit syncing and an api call to Spotify. Mocking out each layer works well, but then how to fully verify a new feature works in production? I needed to do a workout while listening to music. Sure, that is a cool test plan at first but over time it's annoying. As things progressed, I became more comfortable relying on mocks and tests, but it was still a bit manual to determine when a code change may require a full production flow. App modularization may help with these boundaries and automation of detecting when we need to verify changes in production.
- And yet this is where I find a lot of the value in apps: doing things that are necessarily stitching together APIs but really trying out how the product experience works and working with the real world constraints.
- Music API providers are quite limited: it's really just Spotify vs. Apple Music. Spotify's API offered more insight into historical listens, including timestamps. After running into issues with Spotify's API review process, I evaluated Apple Music; however, due to Apple's privacy-focus, the Apple Music API results include what time a user listened to a given track. That broke the premise of this app.
- I think Apple has a very good stance on privacy; however this is an example where it seems like they're overstretching. Specifically it feels like users should be able to approve apps to look at things like timestamp data.
Launch Story
I built the initial version of this app in a few weeks in early 2024, with a launch deadline targeting spring of 2024. Before I could launch though, I needed Spotify's review. The review didn't go through as planned because Spotify's review process was broken at the time; they refused to respond meaningfully to any inbound I sent them, including surfacing this issue in their developer forums and emailing their CEO (which triggered the only response from Spotify, an unsigned email that said they'd get back when they summer was over with updates to the review process).
I continue to work on the app, believing I'd be able to work things out with Spotify, but eventually had to give up on the app premise when Spotify refused to approve my app or work with me meaningfully. I pivoted part of the app to use Apple Music but due to privacy constraints on Apple Music the core premise around getting track listen-to timestamps didn't work.
Forum post from April 2024, three months into the review process… nine likes is a lot for these developer forums
What I'd Do Differently
Going into this app I knew the dependency on Spotify was a real risk. I still wanted to ship this app because I thought I really loved the premise and believed I'd be able to work through any hangups with Spotify, thinking they would work in good faith, if not promptly, with apps submitted to their review process. With that in mind I would have put the app into review and then moved to a different app while it was in review instead of continuing to work on it with the idea that it would get approved. That said going forward I'm taking the big learning around dependencies on third parties: If I don't have a clear path to approval or a direct contact at the company operating the review process, then I will simply not build an app for another platform.
Takeaways
- The workout ecosystem is fragmented; users have a variety of devices/app combinations they use to track.
- Interfacing with Apple's HealthKit works well here since it aggregates; however, it still doesn't cover all cases, since users may track directly into a non-Apple provider or may not have their app-of-choice syncing with HealthKit. And this data flow is still subject to device constraints: for example, HealthKit batches updates to third-party apps, meaning "realtime" HealthKit updates may be delivered up to fifteen minutes after workout completion.
- Meeting users where they're at is key, especially in health/fitness. Asking someone to change where they "press start" on their workout is a big ask, and dj heartbeat avoided that to make life easier for users.
- Stitching API data from two different providers is tricky.
- Here Apple's heartbeat data was fairly consistent whereas Spotify's API for recent listens was inconsistent. Spotify's recent tracks data could have missing songs or if I skipped a track and had it listened to for a set amount of time, it just wouldn't show up in my recent listens. Sometimes the timestamps would be slightly off on Spotify's end.
- Regardless even in the best case there would still be edge cases when syncing time stamps between two providers.
- Working on a product that is aligned with my interest is a lot of fun. It can also blend work and play.
- I enjoy working out. I enjoy listening to music. So this was a natural continuation of those interests; however at certain points I just want to work out. Maybe I don't want to listen to music and I don't want my workout to be part of the core testing flow. That was a tension that I had.
- While working on this it wasn't too bad but it's something that I wanted to keep in mind going forward. A simple fix here would just be to verify things in production independently of my workouts. For example do a walk and listen to music to simulate working out; however what I found is that you can only get so close to a real production use case if you're not doing the full thing that users do in that environment. Any attempt here to simulate a workout might lead me to miss key insights, including an edge case like: "Hey sometimes I want to pause during a workout so I can talk to someone at the gym."
- Working with 3rd party dependencies can make or break your launch.
- When I started working on this app, the Spotify developer guidance was that it could take up to eight weeks or more to get your app reviewed by Spotify. That is very long time but I figured we could make it work by strictly adhering to their guidelines and documenting my app, including a video walkthrough to assist with the review process. Eventually after three months I heard nothing. They eventually rejected it for unspecified reasons and later restricted their API to apps with 250,000+ monthly active users.
- This is especially true for media, with its strict content licensing. I didn't realize the extent that this would impact my ability to ship this product here. I thought I would be able to work with Spotify to get to an approval and that just didn't happen.
Wishlists
- It would be super cool to have a unified API for all the music you listen to and generally all the content to consume. All this stuff is in its own systems but these are very independent. For example if I listen to some music on YouTube, my Spotify algorithm has no idea about that and there's some really good music that I was discovering on YouTube.
- I feel like Apple could have a very strong stance here as acting in this unifying layer as I'm almost always listening to things on Apple. If there was some kind of universal scrobbling API, like last.fm offered, but that was built into the OS layer, that would be super cool.
- All workout services like Peloton and SoulCycle publish their per-class playlist. Peloton does this internal to its app but that's not exposed externally and so that means it's kind of tricky to navigate unless you're in their app itself. Places like SoulCycle tend to have really cool mixes from SoundCloud but don't tend to share those exact playlists.
- I think doing a lot of the work of organizing the playlist is the hard part and so systems like Peloton and SoulCycle should further their platforms so that the individual workout instructors can get even more exposure from the music they put together. Basically allow them to leverage that playlist curation that each person does. This would help the individual instructors get exposure too. A lot of instructors may have a playlist of songs they really like that they share but an automated way of doing this per class would be super cool.
- Better content rights so we apps can remix experiences. Imagine a distributed Peloton: anyone can host a class and we can let individual creators succeed by the merits of their music taste and motivation abilities. The technology is fully there to set up and is relatively simple these days; however the content prevents this, makes this dead on arrival.
- I would love to be able to make a Peloton competitor that allows individuals to curate a playlist and then host a streaming bike ride that people can join into. That'd be super cool and is pretty much dead on arrival due to content restrictions, which to me seems unfair. Further if I look at history and I see companies that have done well in this space, they've all broken the rules, for example Peloton using Spotify's music before Spotify locked down. This further makes the ecosystem worse off for indie developers because these music content platforms further lock down their stuff before opening it up to only larger corporations.