Dynamic content with Eleventy and Netlify

Few weeks ago, I added my current Fitbit activity in the about me section of the blog. And I found a solution using Eleventy's javascript data files and Github Actions.

My weekly activity sample

Since Eleventy is a static site generator, fetching dynamic content at runtime with JS can do the job. In this scenario, the data is fetched every time a user lands into the website. But if you don't need to show that data in real-time, you have anther solution to get the same result. In Eleventy, any javascript file within the _data folder will be executed at build time. So, you can use it to get anything you need from an API, because the data returned from these files will be accessible in your templates.

In this case, I've created an _activity.js file that returns my latest Fitbit activity:

// ./src/_data/_activity.js

async function activity({ now, fitbitAccessToken, fetch }) {
  const url = `https://api.fitbit.com/1/user/-/activities/list.json?beforeDate=${now}&offset=0&limit=6&sort=desc`;
  const options = {
    duration: '1d',
    type: 'json',
    fetchOptions: {
      headers: { Authorization: `Bearer ${fitbitAccessToken}` },
    },
  };

  const { activities } = await fetch(url, options);

  return activities.map((activity) => {
    return {
      name: activity.activityName,
      duration: activity.duration,
      date: activity.startTime,
    };
  });
};

module.exports = async () => activity({
  now: Date.now(),
  fitbitAccessToken: process.env.FITBIT_ACCESS_TOKEN,
  fetch: require('@11ty/eleventy-fetch'),
});

Note that Eleventy executes the data files every time you change the app's code. In order to avoid unnecessary API calls, they provide you a library called @11ty/eleventy-fetch to cache the queries. This way, you won't get banned.

Then, you can access to the generated info using the name of the data file as a variable in your code. In this example we're iterating the _activity we've created avobe.

<!-- ./src/about-me.njk -->

{% for log in _activity %}
<li>
  <span>Activity: {{log.name}}</span>
  <span>Date: {{log.date}}</span>
  <span>Duration: {{log.duration}} mins.</span>
</li>
{% endfor %}

Everytime we deploy using Netlify, the application builds and updates the data. You can trigger this by using Netlify's dashboard or via CLI using a build hook:

curl -X POST -d {} https://api.netlify.com/build_hooks/YOUR_BUILD_HOOK_ID

Easy steps to configure your build hook here.

The final part is to chronify this trigger to stop doing it manually, cause' we're not robots right? 👀 I'm using Github Actions for this, but any other CI/CD service will do the job:

# .github/workflows/main.yaml

name: Trigger Netlify Build

on:
  schedule:
    - cron: '0 0 * * *'

jobs:
  build:
    name: Trigger deploy
    runs-on: ubuntu-latest
    steps:
      - name: Curl request
        run: curl -X POST -d {} ${{ secrets.NETLIFY_BUILD_URL }}

The only thing that changes here is that you must provide your NETLIFY_BUILD_URL. And I recommend you to use Github secrets for this instead of hard coding it. Go to: Your repository > Settings > Secrets to configure your own secret.

And this is it. Easy peasy.