Using global data in 11ty
Global data is data that is accessible throughout your Eleventy project. An example of global data are JSON files that look like this:
[
{
"date": "2024-01-19",
"update": "create shortcodes to add furigana over kanji text. see it in action [here](/site-info)"
},
{
"date": "2024-01-18",
"update": "remove thin scrollbar to improve accessibility"
}
]
The code above is a snippet of my updates.json
file. Global data files are placed inside the _data
folder, which is the default directory, but you’re free to change that in your eleventyConfig
.
Each item in updates.json
has a date
and update
property, which contains the values I want to display in my changelog.
With this JSON file, I can automatically render my website’s changelog in the home page and in the changelog page without having to manually type in everything, including the HTML tags. All I need to do is update one file (updates.json
).
In the changelog page, all updates are rendered in HTML like so:
<span class="label">Jan 19, 2024</span>
<span>
<p>create shortcodes to add furigana over kanji text. see it in action <a href="/site-info">here</a></p>
</span>
Which looks like this (as of January 2024):
Instead of typing out the updates individually with HTML tags, which can be tedious and prone to errors, we can harness the power of for
loops and global data files and let the code do everything for us:
{% for update in updates %}
<span class="label">{{ update.date }} </span>
<span>{{ update.update }}</span>
{% endfor %}
The code above[1] is placed in any HTML or Markdown file; in this example: changelog.md
. When I run npx @11ty/eleventy
in the terminal, the code will loop through the updates.json
file and render the output with the HTML tags in between.
Let’s go through the code line by line:
{% for update in updates %}
The for
keyword will loop through each item in the updates
JSON file. For each item, we’ll assign it the variable name update
. That means we can now get each item’s date
and update
properties, as seen in the JSON file.
We access those properties like so:
update.date
, which contains the date, andupdate.update
, which contains the update text.
<span class="label">{{ update.date }} </span>
<span>{{ update.update }}</span>
Enclose update.date
and update.update
with {{ }}
to print the value in HTML. Then, we use HTML tags as usual, like <span>
in the example above.
Run your npx @11ty/eleventy
or npm start
or whatever, et voilà! It’ll generate your entire list of updates with just four lines! Any time you want to update the changelog, simply add a new item at the top of the JSON file.[2]
If we want to take this further, we can take only the first n
number of updates to show in the home page:
We use the keyword limit
to take only the first n
items in the JSON array:
{% for update in updates limit:4 %}
In the code above, it will take the first four updates and render that from the index.md
page. An important caveat is that the limit
keyword is only available in the Liquid templating language. For Nunjucks, you can use the slice()
function. See here for more info.
Other use cases
I use global data files for my button wall:
[
{
"title": "whiona.me",
"img": "https://cdn.some.pics/whiona/653868e25e532.png",
"url": "https://whiona.me"
},
{
"title": "hillhouse.neocities.org",
"img": "/assets/img/hillhouse-banner-2.gif",
"url": "https://hillhouse.neocities.org/"
},
{
"title": "frills.dev",
"img": "/assets/img/frills.png",
"url": "https://frills.dev"
}
]
This JSON has three properties: title
, img
, and url
. Using global data in this instance saves me the trouble of having to type out <a href=""><img src="" alt=""></a>
. And with the amount of buttons I have on my wall, my hand would’ve cramped from manually typing everything in.
Here’s a code snippet from links.md
for reference:
{% for button in button_wall %}
[![{{ button.title }}]({{ button.img }})]({{ button.url }})
{% endfor %}
or in a more readable HTML format:
{% for button in button_wall %}
<a href="{{ button.url }}">
<img src="{{ button.img }}" alt="{{ button.title }}">
<a/>
{% endfor %}
I also use it in my movie log page! I don’t have individual pages for each movie like I do with my book log[3], so I use global data instead. Here’s a sneak peek of the JSON[4]:
[
{
"Title": "The Shape of Water",
"Directors": ["Guillermo del Toro"],
"Rating": 5,
"Genres": ["Romance", "Drama", "Fantasy"],
"Year": 2017,
"DateWatched": "2024-01-11",
"Favourite": true,
"Rewatch": true
}
]
And this is how it’s rendered:
The properties Favourite
and Rewatch
are checked if true
, which then renders the SVG icons. The star rating uses custom 11ty shortcodes to render the star icons from the Rating
property.
Other than looping through global data, you can also create a metadata.json
file, which contains the site title, author, etc, which you can put in your RSS feed, among other things.
References
This is a simplified version, of course. The original uses 11ty filters to format the date and render Markdown, which is outside the scope of this post. ↩︎
This also saves you from having to sort the items in reverse chronological order… ↩︎
My book log (and the blog posts) are part of 11ty collections, which is another behemoth altogether. ↩︎
I should probably get rid of the unused properties like
Genres
, lol. ↩︎