<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Craig Carlyle</title>
    <description>The latest articles on Forem by Craig Carlyle (@craigcarlyle).</description>
    <link>https://forem.com/craigcarlyle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F173850%2F12a9d5a2-c97f-433d-aa4c-13da8f2d03fa.jpg</url>
      <title>Forem: Craig Carlyle</title>
      <link>https://forem.com/craigcarlyle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/craigcarlyle"/>
    <language>en</language>
    <item>
      <title>Show DEV: I built a dashboard to track my life</title>
      <dc:creator>Craig Carlyle</dc:creator>
      <pubDate>Sun, 15 Mar 2020 23:46:03 +0000</pubDate>
      <link>https://forem.com/craigcarlyle/show-dev-i-built-a-dashboard-to-track-my-life-55pl</link>
      <guid>https://forem.com/craigcarlyle/show-dev-i-built-a-dashboard-to-track-my-life-55pl</guid>
      <description>&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; check it out at &lt;a href="http://craigcarlyle.me" rel="noopener noreferrer"&gt;http://craigcarlyle.me&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Intro
&lt;/h2&gt;

&lt;p&gt;Several years ago I started on a weight loss and health journey. I was introduced to the quantified self community with Fitbit and MyFitnessPal. After losing over 50 pounds, I was hooked on the idea of personal data tracking.&lt;/p&gt;

&lt;p&gt;Fast-forward to the present and I’m tracking more than ever. Not because I believe in optimizing every aspect of my life, but because it helps me balance it. Haven’t exercised in a few days? Time to hit the gym. I’ve been eating 4,000 calories a day this week? I should eat clean for a while. Haven’t meditated or read in a while? Let me grab my Kindle.&lt;/p&gt;

&lt;p&gt;Lots of fantastic tracking tools are available for mobile devices (&lt;a href="https://dev.to*_Gyroscope_*"&gt;Gyroscope&lt;/a&gt; has been my personal favourite), but I wanted something for the desktop/iPad where I could see more data at once over a longer period of time. I couldn’t find anything that did what I wanted, so I built a solution myself. You can see it &lt;a href="https://www.craigcarlyle.me" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvkx0xavzdx3220gr4tzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvkx0xavzdx3220gr4tzg.png" alt="Main Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve set up my data (since January 2019) to appear in a calendar view. Each date will contain the data from the following sources:&lt;/p&gt;

&lt;h4&gt;
  
  
  Data tracked and imported from external sources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Heart rate &amp;amp; HRV &lt;em&gt;via Apple Health&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;⚖️ Weight and body fat percentage &lt;em&gt;via Apple Health&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;👟 Steps and distance travelled &lt;em&gt;via Apple Health&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🧘‍♂️ Meditation sessions &lt;em&gt;via Apple Health&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🔥 Calories consumed &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🍱 Macronutrients (carbohydrates, fat, and protein) &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;☕️ Caffeine (coffee, tea, and pre-workout) &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;💊 Supplement intake &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;✅ Number of tasks completed (work and personal) &lt;em&gt;via &lt;a href="https://todoist.com" rel="noopener noreferrer"&gt;Todoist&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🏋 Workouts &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🧖 Sauna sessions &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;💆‍♂️ RMT sessions &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;👩‍⚕️ Chiropractor sessions &lt;em&gt;via &lt;a href="https://www.myfitnesspal.com" rel="noopener noreferrer"&gt;MyFitnessPal&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🛫 Places I'm travelling to &lt;em&gt;via &lt;a href="https://nomadlist.com" rel="noopener noreferrer"&gt;Nomad List&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🏊‍♂️ Dives I've completed &lt;em&gt;via &lt;a href="https://scubaearth.com" rel="noopener noreferrer"&gt;ScubaEarth&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🦉 Duolingo XP &lt;em&gt;via &lt;a href="https://duolingo.com" rel="noopener noreferrer"&gt;Duolingo&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;👨‍💻 Productivity &lt;em&gt;via &lt;a href="https://www.rescuetime.com/" rel="noopener noreferrer"&gt;RescueTime&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🐙 GitHub Contributions &lt;em&gt;via &lt;a href="https://www.github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;📖 Reading progress &lt;em&gt;via &lt;a href="https://www.goodreads.com/" rel="noopener noreferrer"&gt;Goodreads&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Data entered manually into a Google Sheet
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;🆙 How long I'm using my standing desk&lt;/li&gt;
&lt;li&gt;🔬 Thyroid-stimulating hormone (TSH) results&lt;/li&gt;
&lt;li&gt;🏆 Accomplishments&lt;/li&gt;
&lt;li&gt;🤒 Sickness&lt;/li&gt;
&lt;li&gt;🤕 Injuries&lt;/li&gt;
&lt;li&gt;🌴 Vacation&lt;/li&gt;
&lt;li&gt;📝 Bucket list&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fetching the data (the technical stuff)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  From Apple Health
&lt;/h3&gt;

&lt;p&gt;In iOS 12, Apple added  &lt;a href="https://support.apple.com/en-il/HT209055" rel="noopener noreferrer"&gt;Siri Shortcuts&lt;/a&gt;  which allows for some powerful scripting. I wrote a script that goes through my Health Samples, formats the data as valid JSON, then saves the file to my server via SSH. Unfortunately at the time of writing, Apple doesn’t allow these shortcuts to  be triggered automatically, so I usually run them manually when I arrive at work in the morning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5sww5uxrfp3nuv08gywd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5sww5uxrfp3nuv08gywd.png" alt="iOS Shortcuts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  From MyFitnessPal
&lt;/h3&gt;

&lt;p&gt;I could have leveraged the same Siri Shortcuts to upload my nutritional data, but MyFitnessPal is notorious for having missing or duplicated entries when synced with Apple Health.&lt;/p&gt;

&lt;p&gt;MyFitnessPal also has an invite-only API. I’ve been on a waiting list for years, but have never heard anything.&lt;/p&gt;

&lt;p&gt;I came across this &lt;a href="https://www.npmjs.com/package/mfp" rel="noopener noreferrer"&gt;mfp&lt;/a&gt; module which loads a user’s &lt;a href="https://www.myfitnesspal.com/reports/printable_diary/aeacad" rel="noopener noreferrer"&gt;printable diary&lt;/a&gt; and scrapes the data from there using &lt;a href="https://cheerio.js.org" rel="noopener noreferrer"&gt;cheerio&lt;/a&gt;.  I’ve modified it to scrape exercise, caffeine consumption, supplements, and RMT sessions. I collect this data every 10 minutes with a Node.js task run with &lt;a href="https://devcenter.heroku.com/articles/scheduler" rel="noopener noreferrer"&gt;Heroku Scheduler&lt;/a&gt; and save it on my server as a JSON file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leveraging IFTTT
&lt;/h3&gt;

&lt;p&gt;Conveniently, Google Sheets are  &lt;a href="https://coderwall.com/p/duapqq/use-a-google-spreadsheet-as-your-json-backend" rel="noopener noreferrer"&gt;importable as JSON objects&lt;/a&gt;. &lt;a href="https://ifttt.com" rel="noopener noreferrer"&gt;IFTTT&lt;/a&gt; has plenty of applets that add a new row to a spreadsheet when triggered by an action. A new row is created whenever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I mark a task as complete on Todoist&lt;/li&gt;
&lt;li&gt;My reading progress is updated on Goodreads&lt;/li&gt;
&lt;li&gt;A daily productivity summary is created by RescueTime&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No APIs, No Problem
&lt;/h3&gt;

&lt;p&gt;Recently I’ve fallen in love with scuba diving. I use &lt;a href="https://www.scubaearth.com/Default.aspx" rel="noopener noreferrer"&gt;ScubaEarth&lt;/a&gt; to track my dives, but unfortunately there’s no API. Again using Heroku Scheduler, I launch an instance of &lt;a href="https://pptr.dev" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt; to log in to my account and collect the page’s data from my logbook. The data is parsed into a JSON object  using &lt;a href="https://cheerio.js.org" rel="noopener noreferrer"&gt;cheerio&lt;/a&gt; and then uploaded to my server.&lt;/p&gt;

&lt;p&gt;Duolingo has an API, but it’s undocumented and (as far as I can tell) doesn’t have exactly what I need. Using the same Puppeteer instance, I go to my &lt;a href="https://duome.eu/craigcarlyle/" rel="noopener noreferrer"&gt;duome&lt;/a&gt; profile and collect my recent XP. The new XP JSON objects are added to the existing array of XP objects and uploaded as a file to my server.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Easy Stuff
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://twitter.com/levelsio" rel="noopener noreferrer"&gt;Pieter Levels&lt;/a&gt;  of  &lt;a href="https://nomadlist.com/" rel="noopener noreferrer"&gt;Nomad List&lt;/a&gt;  is awesome and allows anybody to access their data as JSON. All that’s required is a simple fetch of  &lt;a href="https://nomadlist.com/@craigcarlyle.json" rel="noopener noreferrer"&gt;https://nomadlist.com/@craigcarlyle.json&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pushing Further
&lt;/h2&gt;

&lt;p&gt;I thought it’d be cool to map out my travels and dives, so I added another page that does that. The data is listed and visualized with &lt;a href="https://www.mapbox.com" rel="noopener noreferrer"&gt;Mapbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faqmjenvjsotfwrps2xz2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faqmjenvjsotfwrps2xz2.png" alt="Travel + Dives"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also thought it’d be cool to share my bucket list. This is just a simple Google Sheet that’s imported as a JSON object.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc5wk2wrs4oc1iua94zry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc5wk2wrs4oc1iua94zry.png" alt="Bucket List"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Although it’s far from elegant this has been a fun project to hack away on. Not only have I built an app that I needed in my life, but it helped me get over my imposter syndrome (something we all have). One of my goals was to teach myself React as I’ve mostly been working in AngularJS and vanilla JavaScript/TypeScript for the past 6+ years. Although it’s not perfect, I’m now comfortable working with React.&lt;/p&gt;

&lt;p&gt;At any point I could have said “oh, this is too hard", or "there’s no API so it can’t be done”. Finding creative solutions (like using Puppeteer to scrape data) has helped boost my confidence as a developer.&lt;/p&gt;

&lt;p&gt;If anyone has any questions, please don’t hesitate to reach out. I’d be happy to answer them. Thanks for reading!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
