Possum websites, done possumly

Part 9: Using data

6 minute read time / 808 words

Now we know that we can chunk our content pages and templates into includes, and we can make re-usable components with macros... what's next?

Data

We already know about Frontmatter - a way to add metadata to our content and layout files. We know we can format our Frontmatter data in a YAML-y style or with JSON. But we can also use data files to do many things: store site configuration like domain name, site name, social media links. And we can use them to globally apply settings to content pages within a directory too. And we can even use data files to loop through data content and get our templates to output those using macros and logic.

Eleventy is incredibly flexible in using data. There is so much to learn, but let's start with the most common use cases.

Settings data

Let's start with global site settings, things like your site's name, the domain name and other things you might need like search engine verification meta contents.

Create a new file: /src/site/data/settings.json and add the following content:

{
    "sitename": "My Sexy Eleventy Site",
    "domain": "https://mysexyeleventysite.com",
    "xhandle": "mysexyeleventy",
    "author": "Me Me"
}

Because we've configured our data folder to be here in our Eleventy config file, any data files we place in there will be available globally in the following format:

If the file is called settings.json, the data will be available globally as {{ settings.key }}, so from our settings file we can get the sitename by calling {{ settings.sitename }}. Let's update our head and header includes to do this. First, our head include:

<meta charset="utf-8">
<title>{{ title }} | {{ settings.sitename }}</title>
<meta name="viewport" content="width=device-width">

This will take the value of settings.sitename and inject it into the page at build time. Notice how I've added {{ title }} in there as well? Now we will get our <title> attribute output nicely for each page with the current page title. So, for the homepage we'll now get: <title>Hello World! | My Sexy Eleventy Site</title>. Now for our header include:

<header>
    <a href="{{ settings.domain }}">{{ settings.sitename }}</a>

    <p>
        I made this!
    </p>
</header>

As you can see, using data files for commonly needed values is a great thing to do.

Directory/content data

You can also create what's known as a directory data file to apply common settings to all content pages within that folder. This means that you don't need to write the same values in Frontmatter over and over again if they're all just going to be the same.

If we applied this to our new and imaginary documentation folder, we know we will always need to set the same template and the same tag, so we could save some hassle and maintenance by applying these with a directory data file. We could create a new file at /src/documentation/documentation.json and any values we set in this file would be applied to all content pages in all folders from /src/documentation down.

More information

You can read more about template and directory data files over on the official Eleventy documentation site.

Data as content

For me, this feels like one of the most useful reasons to have data files. You've got a JSON file with a bunch of data that you can loop through, template it using a macro and output it onto your site - one place for content, one for the formatting.

You could apply this in many places: staff lists, lists of gallery images with associated alt text and width and height values, all your social media details, branch locations and information, testimonials, or even events on a timeline.

Let's try it out, create a new data file at /src/site/data/social.json and add the following code into it:

[
    {
        "name": "X (Formerly Twitter)",
        "url": "https://x.com/MySexyEleventy",
        "classsuffix": "x"
    },
    {
        "name": "Facebook",
        "url": "https://www.facebook.com/MySexyEleventy",
        "classsuffix": "facebook"
    },
    {
        "name": "Instagram",
        "url": "https://instagram.com/mysexyeleventy",
        "classsuffix": "instagram"
    },
    {
        "name": "Email",
        "url": "mailto:info@mysexyeleventysite.com",
        "classsuffix": "email"
    },
    {
        "name": "Telephone",
        "url": "tel:0123456789999",
        "classsuffix": "tel"
    }
]

Now let's output those social media links into our global site footer. Update our footer include to look like this:

<footer>
    &copy; Me! Because I made this.

    {% include 'social.njk' %}
</footer>

And then create a new file at /src/includes/social.njk with this content:

<nav aria-label="Social media">
    <ul>
        {%- for item in social -%}
            <li>
                <a
                    href="{{ item.url }}"
                    class="social-link social-link--{{ item.classsuffix }}"
                >
                    {{ item.name }}
                </a>
            </li>
        {%- endfor -%}
    </ul>
</nav>

Et voilĂ ! Social media links output into your global footer.