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 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. 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"
},
// ...
}
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 to fetch our JSON file. We could use a library like node-fetch
, but
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. Eleventy handily has its own plugin for this exact purpose: @11ty/eleventy-fetch
(formerly @11ty/eleventy-cache-assets
).
In your terminal, in eleventy-from-scratch
, run the following:
npm install @11ty/eleventy-fetch
Once that’s installed, create a new file inside your _data
folder called studio.js
and add the following to it:
const EleventyFetch = require('@11ty/eleventy-fetch');
/**
* 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 {
let url = 'https://11ty-from-scratch-content-feeds.piccalil.li/media.json';
const { items } = await EleventyFetch(url, {
duration: '1d',
type: 'json',
});
return items;
} catch (err) {
console.log(err);
return [];
}
};
What this does is fetch that remote data from our URL and cache it for some amount of time. Because this is a feed of images, it probably won’t change much, so we have it set to 1 day. When that cache expires, it’ll go ahead and grab the remote data again. Additionally, by setting the type to json
, Eleventy Fetch will parse the JSON for us.
If you haven't dealt with async
/await
before, don't worry. We use async
to declare an asynchronous function (async function someName(){...}
).This lets us use the await
keyword to pause the execution of our async
function until thePromise
is "resolved", or completed, which is when we get our data back.
You can read more about it here.
You also might be unfamiliar with the try
/catch
syntax. This is a way to handle errors in JavaScript; it attempts to run the code inside the try
block, and if that fails, it runs the code inside the catch
block. You can read more about it here.
Now we can access this data using {{ studio }}
in our templates. Pretty rad, right?
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.
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 and scroll down, you should see something that looks like this:
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.