# Lesson 9: Adding remote data

We talked about data in lesson 7. In this lesson, we’re going to build on that knowledge, looking at how JavaScript data files (opens new window) enable us to grab remote data and make it as accessible to our templates as static data like site.json.

Why would we want to grab remote data though? Being able to work with remote data opens all sorts of opportunities to make our site more dynamic. It lets us use Eleventy as a front-end for a content management system. This capability empowers teams to make incredibly fast front-ends for websites that have complex, heavy content systems, which were previously quite slow.

Having the benefits of both dynamic remote data and speed from static files really puts us in a good position to deliver a solid, performant user experience.

# Grabbing our data

First up, let’s take a look at the data we’re grabbing. In a new browser tab, go to https://11ty-from-scratch-content-feeds.piccalil.li/media.json (opens new window). You should see something that looks like this:

{
  "items": [
    {
      "alt": "A notepad, mechanical pencil, phone and plant on very brightly lit desk",
      "large": "https://11tyfromscratch.imgix.net/notepad.jpg?w=1700&q=60&auto=format",
      "medium": "https://11tyfromscratch.imgix.net/notepad.jpg?w=890&q=60&auto=format",
      "small": "https://11tyfromscratch.imgix.net/notepad.jpg?w=600&q=60&auto=format",
      "credit": "https://unsplash.com/photos/bU6JyhSI6zo"
    },

    // The other items ommitted for brevity
}

We’re grabbing a collection of images that show off our pretend agency’s pretend studio.

The first thing we need to do is add a library that gives our Node environment a fetch method (opens new window). That library is node-fetch (opens new window).

In your terminal, in eleventy-from-scratch, run the following:

npm install node-fetch

Once that’s installed, create a new file inside your _data folder called studio.js and add the following to it:

const fetch = require('node-fetch');

module.exports = async () => {
  try {
    const res = await fetch(
      'https://11ty-from-scratch-content-feeds.piccalil.li/media.json'
    );
    const {items} = await res.json();

    return items;
  } catch (ex) {
    console.log(ex);
    return [];
  }
};

This fetches the data from our endpoint using async/await, then when it’s loaded, it returns the items using destructuring.

Because JavaScript data files support async functions, we can still access this data, using {{ studio }} in our templates. Pretty rad, right?

This is cool, but let’s make it even cooler.

Because we’re pulling data from a remote source: every time you re-build the site, it will go and fetch it. This isn’t ideal—especially if you’re using a rate-limited API. Let’s say the API you’re pulling data from only allows 10 queries per hour. If you save your project 10 times in that hour, it’ll stop you from grabbing the data you need.

We’re going to mitigate this risk by using an even better library than node-fetch to do this for us. It’s made by Eleventy and it’s called @11ty/eleventy-cache-assets.

What this library does is fetch that remote data and cache it for a user-defined amount of time. Because this is a feed of images, it probably won’t change much, so we’re going to cache ours for 1 day. When that cache expires, it’ll go ahead and grab the remote data again.

To get this library running, we need to do some housekeeping first. Inside eleventy-from-scratch, run the following command in your terminal:

npm uninstall node-fetch

Then, run the following command:

npm install @11ty/eleventy-cache-assets

That cleans out the fetch library we were using and installs the cache library we’re going to use instead.

Now, open up eleventy-from-scratch/src/_data/studio.js again and delete everything.

Replace that deleted code with this:

const Cache = require('@11ty/eleventy-cache-assets');

/**
 * Grabs the remote data for studio images and returns back
 * an array of objects
 *
 * @returns {Array} Empty or array of objects
 */
module.exports = async () => {
  try {
    // Grabs either the fresh remote data or cached data (will always be fresh live)
    const {items} = await Cache(
      'https://11ty-from-scratch-content-feeds.piccalil.li/media.json',
      {
        duration: '1d', // 1 day
        type: 'json'
      }
    );

    return items;
  } catch (ex) {
    console.log(ex);

    // If failed, return back an empty array
    return [];
  }
};

This is essentially the same as code as before, but we destructure the items straight out of the Cache instead this time, which simplifies things a bit.

# Rendering our new data

Now we have our data, it works exactly the same as other data files. Let’s put that into practice by adding a studio feed to our home page.

First up: in your partials folder, create a new file called studio-feed.html and add the following HTML to it:

{% if studio.length %}
<article class="[ studio-feed ] [ dot-shadow panel ] [ bg-tertiary-glare ]">
  <div class="[ wrapper ] [ flow flow-space-300 ]">
    <h2
      class="[ studio-feed__heading ] [ headline ] [ md:measure-micro ]"
      data-highlight="secondary"
    >
      {{ studioFeed.title }}
    </h2>
    <p class="visually-hidden" id="studio-feed-desc">
      A collection of images from around our studio and the people who work here.
    </p>
    <div class="[ studio-feed__items ] [ flow-space-700 ]">
      <ul class="studio-feed__list">
        {% for item in studio %}
        <li>
          <img
            src="{{ item.medium }}"
            alt="{{ item.alt }}"
            draggable="false"
            class="radius"
          />
        </li>
        {% endfor %}
      </ul>
    </div>
  </div>
</article>
{% endif %}

This looks familiar, right? We first determine if the  {{ studio }} variable has a length. We do this because the function that grabs our remote data returns an empty array in its catch statement. This means there could be nothing to loop, so what we don’t want to do is render empty elements. After that check has completed, we loop through each item and render the image.

TIP

The chances that your remote data source returning nothing or throwing an error are probably quite slim, but the important message here is that we make sure our website degrades gracefully if this does happen. It’s helpful to be proactive where you see potential risk—especially with display logic like this example.

Let’s add this partial to the home page. Open up eleventy-from-scratch/src/_includes/layouts/home.html. After the featured work partial ({% include "partials/featured-work.html" %}), add the following:

{% include "partials/studio-feed.html" %}

Lastly, open up eleventy-from-scratch/src/index.md and add the following Front Matter to your existing items:

studioFeed:
  title: 'From inside the studio'

Job done. You’ve now got some remote data on your home page. If you open up http://localhost:8080 (opens new window) and scroll down, you should see something that looks like this:

The addition of various hipster studio images on the home page

# Wrapping up

You should be feeling bloody awesome right now. Pulling in remote data into a static website is cool as heck and you just did it.

Next up, a recap of where we’re at because our home page is pretty much done.

:::