Possum websites, done possumly

Part 3: Configuration and navigation

8 minute read time / 1046 words

In part two we looked at setting up our first collection and listing out pages in that collection on our posts landing page. What we really need now is a way to navigate around all the pages of the site... so we're going to need to set up some site navigation.

Configuration

Before we do that though, we need to become accustomed to the Eleventy settings file, .eleventy.js. This file isn't created by default because Eleventy will do all the basics we've covered already out-of-the-box with zero config. It's beautiful, right?

When you start to do things a bit more complicated, you're going to need to be able to use plugins, add filters and generally be comfortable messing with Eleventy's configuration.

Almost all the config you'll ever do on an Eleventy site is through the main settings file: .eleventy.js. Go ahead and create that file now in the root of the site. Our file structure should look like this:

./
├── _includes/
│   ├── article.njk
│   ├── base.njk
│   └── posts.njk
├── about.njk
├── index.njk
└── posts/
    ├── 2024/
    │   └── 02/
    │       └── my-first-sexy-eleventy-post.njk
    └── index.njk

This settings file allows is to do other things that are really helpful, such as setting your input and output directories, what templating languages you're using. The default folder names and locations might not suit how you want to work, and that's totally fine - you can just instruct Eleventy to find those files elsewhere!

Open up .eleventy.js and let's get some basic configuration in there. Here's the skeleton structure of the file:

module.exports = function(eleventyConfig) {
    // Our config goes here, and make sure you return something
}

addPassthroughCopy

We're going to want to add images and web fonts at some point to make things prettier, so let's add that now in preparation:

module.exports = function(eleventyConfig) {
    eleventyConfig.addPassthroughCopy({ 'public/fonts': 'fonts' });
    eleventyConfig.addPassthroughCopy({ 'public/img': 'img' });

    return {
        passthroughFileCopy: true
    };
}

For this to work, we'll need to create a 'public' folder in the root of the site, and inside there create an 'img' and a 'fonts' folder. Don't worry about putting any files in them for now.

Directories

Let's assume we're not happy with the folder setup of our site as it is. Using an output folder called '_site' doesn't make sense, we want to call it something else, right? We can do that. And we can change where our layouts, includes, and data files are kept too.

More information

You can see all the default file and folder settings on the official documentation site.
module.exports = function(eleventyConfig) {
    eleventyConfig.addPassthroughCopy({ 'public/fonts': 'fonts' });
    eleventyConfig.addPassthroughCopy({ 'public/img': 'img' });

    return {
        dir: {
            input: 'src',
            output: 'dist',
            includes: 'site/includes',
            layouts: 'site/layouts',
            data: 'site/data'
        },
        passthroughFileCopy: true,
        htmlTemplateEngine: 'njk',
        templateFormats: ['njk', 'md'],
    };
}

So far this file has now changed where our files sit into different directories, and we've told it where we're going to be putting our font and image files and that we want those copying verbatim into the output website during the build process.

Our folder structure should now look something like this:

./
├── public/
│   ├── fonts/
│   └── img/
└── src/
    ├── about.njk
    ├── index.njk
    ├── posts/
    │   ├── 2024/
    │   │  └── 02/
    │   │      └── my-first-sexy-eleventy-post.njk
    │   └── index.njk
    └── site/
        ├── data/
        ├── includes/
        └── layouts/
            ├── article.njk
            ├── base.njk
            └── posts.njk

If we now get Eleventy to build our site, we should get the build output into a folder called 'dist' instead of '_site':

./
├── dist/
    ├── about/
    │  └── index.html
    ├── fonts/
    ├── img/
    ├── index.html
    └── posts/
        ├── 2024/
        │  └── 02/
        │      └── my-first-sexy-eleventy-post/
        │          └── index.html
        └── index.html

Now that things are looking a bit more organised and logical (maybe?!), let's get that global navigation sorted. To do this, we need to get our first plugin added. Firstly, we'll need to download the navigation plugin, then we'll need to tell the project we're going to use it. In the root folder of the site, do the following:

npm i @11ty/eleventy-navigation --save-dev

When that's done, open up the .eleventy.js file. We'll need to pull in the plugin, and then tell Eleventy we're going to use it. Update the file to the following:

const eleventyNavigationPlugin = require('@11ty/eleventy-navigation');

module.exports = function(eleventyConfig) {
    eleventyConfig.addPlugin(eleventyNavigationPlugin);

    eleventyConfig.addPassthroughCopy({ 'public/fonts': 'fonts' });
    eleventyConfig.addPassthroughCopy({ 'public/img': 'img' });

    return {
        dir: {
            input: 'src',
            output: 'dist',
            includes: 'site/includes',
            layouts: 'site/layouts',
            data: 'site/data'
        },
        passthroughFileCopy: true,
        htmlTemplateEngine: 'njk',
        templateFormats: ['njk', 'md'],
    };
}

Preparing our pages

Now we're ready to get our pages prepared for being output in the menu. This is a straightforward process, and all we need to do is add some eleventyNavigation settings into the Frontmatter of every page we want to show in the global menu.

Open up our home page file, and update the Frontmatter with the navigation settings we need:

---
title: Hello World!
layout: base.njk
eleventyNavigation:
  key: Home
  order: 1
---

And in the about page, add similar values:

---
title: About us
layout: base.njk
eleventyNavigation:
  key: About us
  order: 2
---

Let's finally add the post listings page into the navigation. Open up /posts/index.njk to update the Frontmatter:

---
title: Posts
layout: posts.njk
eleventyNavigation:
  key: Posts
  order: 3
---

Adding the navigation

Now we just need to get those pages output into our base template so every page will have a global menu. Open up base.njk, and update it to the following:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My Sexy Eleventy Site</title>
        <meta name="viewport" content="width=device-width">
    </head>

    <body>
        <nav>
            <ul>
                {% set pages = collections.all | eleventyNavigation %}

                {%- for entry in pages %}
                    <li>
                        <a href="{{ entry.url }}">
                            {{ entry.title }}
                        </a>
                    </li>
                {% endfor %}
            </ul>
        </nav>

        <h1>{{ title }}</h1>
        {{ content | safe }}
    </body>
</html>

Refresh your site, and you'll now have a little menu with three links in it. Excellent, we can now navigate to all our pages easily!