Generate Page Content From a Global Data File Using Eleventy

Posted on  • tagged with #eleventy#nunjucks#html

There are many great features to choose from when building websites with Eleventy. One feature in particular that I find very useful is the ability to iterate over a global data file and generate page content using Nunjucks.

In 11ty, when you create global data files place them inside the _data directory. The data files can then be accessed by any template in the project structure. Global data files can be stored as JSON .json or values from module.exports in a JavaScript .js file.

Use Cases

I think its safe to say when building a website, you might be faced with creating a large grid of repeating card elements (with different data) or a long listing column of values. This could be menu items on a restaurant menu, profiles on a main page, the list goes on and on.

Why sit there and type out 30 different .card containers when you can store each card elements data inside a global data file. To then iterate through that global card data and generate 30 elements from only one card containers markup. This could be data fetched from an API and stored in a .json file or by simply typing in the data needed by hand into a _data/*.json file.

The Data Cascade

Before going any further, I should mention that when building webpages using the Static Site Generator (SSG) Eleventy. Data is being merged from multiple sources before making its way to the template file that gets rendered in the site output directory _site. This is what Eleventy calls the Data Cascade and its really neat.

Data Sources

One of my favorite things about Eleventy is the fact that there isn't a prescribed way of merging data within the cascade. There is an order of priority for sources of data in the cascade but that data can defined however you would like.

Here are a few options for data sources:

Creating a Global Data File

The global data folder in Eleventy is decided by the dir.data configuration. For this article I will only focus on .json global data but you can read more about other global data available to templates if you'd like.

The example below creates an array of objects inside the cards.json global data file. Each employee card object in the array has some filler data to mimic a large page of profile cards or something of that nature.

Let's say company XYZ has many employees and you don't want to sequentially write out the HTML for each employee profile card. You can create a layout profiles.njk inside a new directory called _includes/layouts/ and begin iterating over the array of card objects in cards.json. You could also just create a profiles.html file to iterate over the global data and not use any .md files.

Filename: cards.json
[
{
"title": "Card One",
"name": "Larry",
"id": 1,
"posititon": "Systems",
"scheduled": {
"monday": true,
"tuesday": true,
"wednesday": true,
"thursday": true,
"friday": false,
"saturday": false,
"sunday": false
},
"interests": [
"Some rad stuff",
"reading rad blog posts",
"eleventy"
]
}
]

Using Global Data

Below is an example of the for loop syntax in Nunjucks.

{% for item in sequence %}
{{ item }}
{% endfor %}

This way, you only write a small amount of template HTML for one profile container. Allowing the for loop to generate the rest of the card containers markup from your global data.

I'm using Nunjucks as the templating language for examples in this article, but everything could be done in a .liquid template as well. Liquid is the default templating engine in Eleventy.

To create a loop or conditional statement use {% code %}. If you simply want to access data from front matter or in global data, use {{ variable }}.

{% for card in cards %}
<h2>{{ card.title }}</p>
<p>Hi, my name is {{ card.name }}</p>
{% endfor %}

You can access global data files in a markdown file or within a template by using the filename without its file extension. When you have a global data file thats an object, you can access the content by using {{ cards.title }} without any for loop.

If you wanted to iterate over the array of card objects in _data/cards.json and generate HTML. You can inject global data into a template file. Use something like this,

Filename: profiles.liquid
<main class="card-grid">
{% for card in cards %}
<div class="card">
<h2>{{ card.title }} - #{{ card.id }}</h2>
<p>Hi, I'm {{ card.name }} and I work in {{ card.position }}.</p>
<h3>Interests</h3>
<ul>
{% for interest in card.interests %}
<li>{{ interest }}</li>
{% endfor %}
</ul>
<h3>Schedule</h3>
<ol>
<li>Sunday: {{ card.scheduled.sunday }}</li>
<li>Monday: {{ card.scheduled.monday }}</li>
<li>Tuesday: {{ card.scheduled.tuesday }}</li>
<li>Wednesday: {{ card.scheduled.wednesday }}</li>
<li>Thursday: {{ card.scheduled.thursday }}</li>
<li>Friday: {{ card.scheduled.friday }}</li>
<li>Saturday: {{ card.scheduled.saturday }}</li>
</ol>
</div>
{% endfor %}
</main>

Using Markdown

Let's say you wanted to write an introduction paragraph in markdown underneath the main page title. To start, you would create a .md file and add some front matter data at the top of cardBanner.md inside the opening and closing document separators, ---.

Front matter in 11ty uses YAML syntax. The permalink is called a quoted scalar where the title and layout are scalars in the plain style. All the content outside of the document separators within a .md file are rendered as regular Markdown.

Including a permalink in front matter data when using 11ty allows for URIs to leave out filename extensions. The page cardBanner.md will be written to the sites output as /employees-page/index.html and accessible from the /employees-page/ URI.

Filename: cardBanner.md
---
title: XYZ Company Employee Profile Page
layout: layouts/profiles.njk
permalink: "/employees-page/"
---

Welcome to the employee home page for company XYZ.

The employee cards contain the data fields:
- name
- position
- interests
- weekly schedule

To include the markdown in cardBanner.md, we can reference it inside the template file profiles.njk using {{ content }} and the safe filter.

Conclusion

This is just one method of merging data in Eleventy and if you'd like to learn more. I suggest taking a look at some of the great features Eleventy has to offer such as Collections, Pagination and Pages from Data.

Here is a link to the live demo.