I wrote briefly about Fitness Tracker a few days ago, but today I would like to go into the history of the application and how it influenced some of my tooling decisions.
The very first version of Fitness Tracker was launched almost seven years ago, shortly after I got out of the hospital. A lot of bad habits lead to a week in a cardiac ward and I decided to change my life. And so, I started writing software.
Fitness Tracker was a challenge - at first it was purely manual. Then I started adding the ability to work with data from my cardiac monitor and other assorted goodies I bought to distract myself from the whole heart attack thing. In fact, I overengineered the hell out of the first two versions to distract myself from the whole heart attack thing but that’s a subject for another time (or a therapist).
But I was the only user so it didn’t matter. I had brief thoughts of turning it into a product and even wrote a bunch of content for a Hugo site but that never made it past the prototype stage (though I realized that the web was a really poor platform for this type of data).
So, when I got around to the final rewrite (so far), I had a lot of experience implementing parts of it, had a bunch of code lying around and even had a really awful looking website written for a version of Hugo released before my kid started school. They’re just finishing grade three so…it’s been a highway.
And so, I had three major challenges:
1. Merging a lot of content
Since I had a really old website and a bunch of other documents, I decided to pull out my usual text mangling stack. That’s Python in a Docker container.
This isn’t actually a great use case for Docker and if I was doing it for the first time, I wouldn’t have used Docker. But I have published (and am starting to publish again) so I have done a huge amount of work with text in my life. Using Docker for this kind of stuff is just muscle memory because it makes it easy to share things with other contributors. So I just reach for it because I always reach for it. The container is well tested and very reliable because I use it so much, but it’s not a complicated container.
While Docker was just muscle memory for this use case, Python was deliberate. When you have an old project with a lot of different things in a lot of different formats, you need a really quick but accurate way to search for content, save it as something and copy it somewhere else.
Python gives you structures like this:
# Regex to extract front matter
front_matter_pattern = re.compile(r"^---\s*\n(.*?)\n---\s*\n(.*)", re.DOTALL)
In that case, that pattern let me extract all the front matter from a large section of a Hugo site that dates back from when the 9 year old was in diapers.
2. The Application
This one threw me a big sweeping agile curveball and the jury is still out on whether I whiffed on it. Long story short, the application itself was originally done with Electron and Ant Design. Builds were large, but it worked great.
Then, I tried to push Electron into being able to generate timelapse photos. That worked fairly well…until I started simulating a user creating a timelapse of a year long fitness journey. In retrospect, that was a poor use of Electron and had I known I was going to generate timelapses, I would have used something else from the beginning. But it came up in an agile process and I just kind of dived in.
The Electron version had a few other little things that kept getting stuck in beta testing. Ant Design is incredible but it wasn’t quite the right fit for this and so I realized I had a fair bit of the front end to rewrite. So….
This version of Fitness Tracker is Rust (with Tauri) on the backend and all React with custom scss on the frontend. I rewrote timelapses yesterday and this version is much much faster.
In this case, I chose Rust for performance and am very happy with the improvements it allowed. But I’m even happier with how much time the compiler saves me having to hunt down strange problems. It’s slow…but overall it’s still a big win.
As for React, I’m not a frontend developer, I’m just productive and know how to test. I’m sure I could have made a better choice than React, but I don’t know any of the other choices I would have had on the shortlist. So React was good enough (and it’s pretty darned good).
3. Customer Support
Customers are really important to me so this part was important to get right. Fitness Tracker is designed not to track people, it collects no telemetry and only needs an internet connection for updates or tech support requests. Since privacy and experience are so important when it comes to customer support, I decided to implement two other projects within Fitness Tracker.
Siteimp-logger collects structured logs from the application. These logs are stored per session and auto delete regularly to free up space. When a customer gets an error and need support, they can click on the help button and a dialogue will appear that gives them the option to jut send a message or send a message and attach their logs.
If they choose to send their logs, another dialogue opens which shows them what data they will send and gives them the option to redact more personal data than the defaults. That’s all the formimp-sdk.
When customers send me logs, I can open them up in Siteimp and replay them. That’s the only way I will ever get any telemetry out of the applications themselves.
So why did I use Formimp and Siteimp?
When I went to business school and studied marketing, I made a point of watching a Bill Hicks routine quite often. He had some strong opinions about the marketing/advertising industry and if he were still alive, I’m sure he would sum the choice up as:
“There is no rationalization for what you do and you are satan’s little helper.”
I can rationalize why I implemented things I built myself - I have bills to pay. And while I can make some privacy arguments in favour of my solutions, other solutions make those same arguments. Most importantly though, since they’re mine and I’ve run them for years, I know exactly how much they cost and can factor my cost to run them into one time purchase software.
The Party Has Assembled
Writing this, I realized that I have a couple of Imps, Rust, React and Python. It sounds a lot like a roleplaying game and so uh, the party has assembled.
Finally, I wrote this article so that in six months or six years when I regret my choices, I can come back and update this with every single poor choice I made. I’m pretty sure the Bill Hicks reference will haunt me in three years but that’s the joy of aging - you get to look back and wish you could apply today’s maturity to yesterday’s decisions.