The BIG List

of Neocities RSS feeds

An Atom feed from scratch

a starter’s guide by sorbier

This article goes through setting up an Atom feed by hand from scratch.

Why?

Before we get into the details, you may wonder about the point of this whole exercise. Why set up an Atom feed, and why by hand from scratch?

Atom (and RSS) feeds are a pillar of indie web! Readers can subscribe to these feeds, like following someone’s feed from your favourite social media site. The difference is that you make the feed yourself, instead of having the social media platform generate one automatically for you. Atom feeds are decentralised, which means no single platform has control over them. Instead, each website’s webmaestro (you!) maintains their own feed(s). That means you’re responsible for updating the feed, but you also get to decide exactly what goes in the feed.

But why build the feed by hand? Well, the same reason you’d build your website by hand! You get intimate with your feed, you know exactly how it works, and it’s fun! Like most early web technologies, Atom feeds are straightforward. If you know some HTML, the Atom feed’s structure will be nothing new. (Over time, if your feed gets more complicated, or if you’re maintaining multiple feeds, then it may be worth setting up an automatic feed builder — but it’s overkill when you’re just starting out.)

A template

Let’s start with a sample feed.

<?xml version="1.0" encoding="utf-8"?>
<feed>
    <title>My Book Website</title>
    <id>https://www.fakebookwebsite.com/</id>
    <updated>2025-12025T12:00:00Z</updated>
    <author>
        <name>Bookworm in chief</name>
    </author>
    <link href="https://www.fakebookwebsite.com/feed.xml" rel="self" type="application/atom+xml"/>

    <entry>
        <id>https://www.fakebookwebsite.com/austen.html</id>
        <title>Jane Austen’s oeuvre</title>
        <updated>2025-12-25T12:00:00Z</updated>
        <author>
            <name>Bookworm in chief</name>
        </author>
        <link>https://www.fakebookwebsite.com/austen.html</link>
        <summary>In which I review every single book Austen ever wrote</summary>
    </entry>

    <entry>
        <id>https://www.fakebookwebsite.com/eyre.html</id>
        <title>I loved Jane Eyre</title>
        <updated>2024-12-25T12:00:00Z</updated>
        <author>
            <name>Bookworm in chief</name>
        </author>
        <link>https://www.fakebookwebsite.com/eyre.html</link>
        <summary>Was so good that I’ve decided to read only Jane-related books from now on.</summary>
    </entry>
</feed>

This feed is for the (totally real) website https://www.fakebookwebsite.com. We’ll use this feed to explain how to build up an Atom feed. Feel free to copy it, then edit it to create your own feed!

The feed

Just like webpages on your website likely share a “skeleton template” into which you put your content, the Atom feed also has a general structure. The first line tells the reader (or browser) what kind of file it’s dealing with. You don’t need to change anything about this line but make sure to include it. It declares that the Atom file is an XML file, and its encoding.

Then, we get into the feed itself. The contents of the feed are wrapped in a <feed> tag. The Atom feed uses tags, just like HTML. Everything inside the tag belongs to the tag: here, everything in the feed tags is part of the feed!

The feed begins with an “introduction” of sorts, that establishes some basic info. There are three required pieces of info that you must provide: the title, the “id”, and the date of last update.

<title>
The title should be the name of your feed: what’s displayed in a person’s feed reader to distinguish it from other feeds. The title or name of your website is a good choice.
<id>
The “id” of the feed should be a unique URL (technically, a URI, but let’s not get technical). Your website’s URL is the standard choice.
<updated>

The date and time of last update needs to be in a special format so that the feed reader can understand it. To break it down, let’s take a look at the timestamp in our example feed: 2025-12-25T12:00:00Z.

The first chunk, 2025-12-25, describes the date. To the happiness of all non-Americans out there, the order goes year, month, then day. You can see that the last update to our feed was Christmas day of 2025.

When you write out the date, use four digits for the year (e.g. 1999, 2008, 2025), two digits for the month (e.g. 12 for December, 01 for January), and two digits for the day.

The next chunk, T12:00:00Z, describes the time. (Truthfully, since I rarely update more than once a day, I always set noon and am done with it.)

The T signals “time”, after which we have the hour, the minute, and then the seconds. Each of these should also be two digits, so you’d write T08:00:00Z for 8AM. The hour should be in 24h time, so for 8PM you’d write T20:00:00Z.

Finally, the Z stands for UTC (the time zone which includes London, Lisbon, and so on). So all together, our feed was updated on Christmas day 2025, at noon London time.

The easiest way to deal with time zones is just to convert to London time. If you are dead set on writing the time using a different time zone, see the extra details end of this article.

You can see that our sample feed has a few more components, on top of these three required ones. It also has the <author> and <link> tags. These are recommended, so readers know whose feed they’re getting and how to get to the original source for the feed.

<author>
The author tag in turn includes more tags which each describe a trait of the author. There are several pieces of information you can include about the author; in our example, we have included only the author’s <name>; but, if you’d like, you can in the same way include the author’s <email> and <uri> (the author’s personal website homepage).
<link>
This link provides the URL of the Atom feed itself, so a reader can find their way back to the feed. That’s why it has the attribute "self", to signal that this link is the Atom feed’s own URL.

These are the basics to get you started, but there are many more optional tags. If you’re curious, you can see them here.

Entries

Now that we’ve set up the skeleton of our feed, let’s put some content in, shall we? The feed contains entries, each of which is like one “post” that will show up in your audience’s feed readers. You can see that our example feed has two entries, from newest to oldest. If you ignore all the XML tags, you can see that the feed looks like a social media timeline (or, more aptly, that Atom feeds were the model for social media feeds)!

Each entry follows the same format. Once you get used to it, it’s easy to add new entries to your feed! I’ll replicate the most recent entry so we can go through it line by line.

<entry>
    <id>https://www.fakebookwebsite.com/austen.html</id>
    <title>Jane Austen’s oeuvre</title>
    <updated>2025-12-25T12:00:00Z</updated>
    <author>
        <name>Bookworm in chief</name>
    </author>
    <link>https://www.fakebookwebsite.com/austen.html</link>
    <summary>In which I review every single book Austen ever wrote</summary>
</entry> 

Just like the feed, there are a three required elements: the <title>, the <id>, and the date/time last <updated>. These follow the same rules as above, but now for the entry itself. For example, you should enter the entry’s title in the <title> tag; here, we can see that this entry is a new post called “Jane Austen’s oeuvre”. The <id> is thus the post’s URL, and the date/time last <updated> is when the post itself last got an updated.

Our entry has some optional tags, including <author> and <link>, just like above, but now we put the post’s author and link. For example, if your website has multiple contributors, you may have a different author for each entry.

There are some entry-only tags which are worth describing: the <summary> and <content> tags. These are both optional, but a good feed includes at least one of these tags for each entry: it’s where your actual content goes. (Otherwise, your readers will get nothing but a stream of post titles!) The summary tag contains a summary of the update; if it’s a new post, for example, you could summarise what’s in the post so readers can get a quick idea as they skim their feeds. On the other hand, the content tag should include the full content of the update: so the body of the post itself.

A warning: all tags should include plain text only. Though the Atom feed looks like HTML, it is not an HTML file! If you include HTML, it will not be interpreted as such, and can even break your feed. It’s tempting to include HTML, especially in the <content> tag, if you’re pasting in the full body of your post. The simplest way is to remove all HTML first, before you paste in your post’s body. If you’re dead set on incorporating the HTML markup of your post, see the extra details at the end of this post.

Beyond the tags I described here, there are still other optional tags that you could include. Beginners need not worry about them, but if you’re curious what they are, you can check them out here.

You’re done!

Build a feed following the template above and you’re all set! Go forth with confidence to distribute your feed(s): long live the indie web. If you’d ever like to check your feed’s “correctness”, you can use the W3 Atom feed validator.

Extra details

I’ll cover a few extra tidbits here, which you can ignore if you’re just getting up off the ground.

CSS

You can style a XML feed with CSS, in the same way you style any HTML webpage! Each tag that displays on your Atom feed will accept CSS styling.

For example, to boldface all the entry titles, you could have the CSS rule entry title { font-weight: bold; }. To apply a stylesheet, include <?xml-stylesheet type="text/css" href="atom.css"?> before you open the <feed> tag. Change atom.css to the URL of the CSS file you’d like to apply.

Time zones

Above, I described how to encode Christmas day, 2025, at noon London time. What if you instead wanted to have noon Berlin time?

The formatting convention follows UTC, which describes time zones as offsets from the UTC zone. Berlin is one hour ahead, which is UTC+01:00 by the UTC convention. You can see how the +01:00 (the UTC offset) reflects the “one hour ahead”. Then, to denote Christmas day, 2025, at noon Berlin time, we’d write 2025-12-25T12:00:00+01:00.

In general, just look up your city’s UTC time zone: it will be +something if you’re east of London and -something if you’re west of London. Americans beware: since daylight savings time is different from Europe, your UTC offset will change during the year.

Including html in your entry

There are two steps to include HTML in your entry’s <content> tag. First, you need to tell the reader that it’s getting HTML content, instead of plain text, when you open the tag: <content type="html"> instead of <content>. Second, you need to escape all symbols that could break your feed, like < and >. It should get you most of the way there if you replace every < from your HTML markup with &lt; and every > with &gt;.

The reason we need to make these changes is that Atom feeds use these symbols to open and close tags; if you don’t want the feed to interpret them this way, you need to “trick” the feed by “disguising” them as normal text. There may be some other symbols that cause issues too: run your feed through the feed validator to check if there are any symbols causing issues. If there are, you will need to look up how to escape ("disguise") them too.

You can include HTML not only in the content tag, but also in the title and summary tags, using the same steps. The reason to include HTML, in any of these tags, is that modern feed readers will following your HTML instructions when they display your content. So, for example, if your post has HTML links, someone who subscribes to your feed would be able to click on the link from inside their feed reader.