Possum websites, done possumly

Part 6: Sitemaps and RSS feeds

5 minute read time / 563 words

Let's look at getting your content ready for people's newsfeeds and for search engine indexing.

Sitemap

What we're going to output will be slightly different whether it's a post or a standard text page, so we're going to need to go ahead and update both the home and about pages to tag them as a textpage.

---
title: Hello World!
layout: base.njk
tags: textpage
eleventyNavigation:
  key: Home
  order: 1
---
<p>
    This is the homepage content!
</p>

Add the same tags: textpage to the about page as well. Now create a new file called sitemap.njk in the root folder of the site and add the following code into it:

---
permalink: /sitemap.xml
eleventyExcludeFromCollections: true
siteurl: https://mysexyeleventysite.com
---

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    {% for page in collections.textpage %}
        {% set absolutePostUrl %}{{ page.url | url | absoluteUrl(siteurl) }}{% endset %}
        <url>
            <loc>{{ absolutePostUrl }}</loc>
            <lastmod>{{ page.date.toISOString() }}</lastmod>
        </url>
    {% endfor %}

    {% for page in collections.article %}
        {% set absolutePostUrl %}{{ page.url | url | absoluteUrl(siteurl) }}{% endset %}
        <url>
            <loc>{{ absolutePostUrl }}</loc>
            <lastmod>{{ page.date.toISOString() }}</lastmod>
        </url>
    {% endfor %}
</urlset>

Visit /sitemap.xml on your local dev server and you should see a perfectly-formed XML sitemap.

RSS feed

Before we can get our RSS feed running, we need to add a new plugin. Run the following in the root folder of your site to get the Eleventy RSS plugin:

npm i --save-dev @11ty/eleventy-plugin-rss

Open up our .eleventy.js config file, and import and enable the RSS plugin:

const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function(eleventyConfig) {
    eleventyConfig.addPlugin(pluginRss);
    //... all our other plugins and filters, etc
}

Now create a new file called feed.njk in the root folder of the site, and add this code into it:

---json
{
  "permalink": "feed.xml",
  "eleventyExcludeFromCollections": true,
  "metadata": {
    "title": "My Sexy Eleventy Site",
    "subtitle": "Some random words",
    "url": "https://mysexyeleventysite.com/",
    "feedUrl": "https://mysexyeleventysite.com/feed.xml",
    "author": {
      "name": "Me Me",
      "email": "me@mysexyeleventysite.com"
    }
  }
}
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>{{ metadata.title }}</title>
    <subtitle>{{ metadata.subtitle }}</subtitle>
    <link href="{{ metadata.feedUrl }}" rel="self"/>
    <link href="{{ metadata.url }}"/>
    <updated>{{ collections.post | getNewestCollectionItemDate | dateToRfc3339 }}</updated>
    <id>{{ metadata.url }}</id>
    <author>
        <name>{{ metadata.author.name }}</name>
        <email>{{ metadata.author.email }}</email>
    </author>

    {%- for article in collections.article | reverse %}
        {% set absolutePostUrl %}{{ article.url | url | absoluteUrl(metadata.url) }}{% endset %}
        <entry>
            <title>{{ article.data.title }}</title>
            <link href="{{ absolutePostUrl }}"/>
            <updated>{{ article.date | dateToRfc3339 }}</updated>
            <id>{{ absolutePostUrl }}</id>
            <content type="html">{{ article.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}</content>
        </entry>
    {%- endfor %}

    {%- for page in collections.textpage | reverse %}
    {% set absolutePostUrl %}{{ page.url | url | absoluteUrl(metadata.url) }}{% endset %}
    <entry>
        <title>{{ page.data.title }}</title>
        <link href="{{ absolutePostUrl }}"/>
        <id>{{ absolutePostUrl }}</id>
        <content type="html">{{ page.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}</content>
    </entry>
    {%- endfor %}
</feed>

The ---json Frontmatter opening section lets Eleventy know we're going to be passing a JSON object in our Frontmatter instead of the usual YAML-like format.

Because we've already updated our standard content pages to be in the 'textpage' collection, this should work now without any additional changes to our files.

Visit /feed.xml on your local dev server and you should see a perfectly-formed RSS newsfeed.