Syndication Feeds

This guide covers generating syndication feeds for your markata-go site: Sitemap, RSS, Atom, and JSON Feed. Each format serves different consumers - search engines, feed readers, and JavaScript applications.

Quick Reference

Format File MIME Type Use Case
Sitemap sitemap.xml application/xml Search engine indexing
RSS 2.0 rss.xml application/rss+xml Traditional feed readers
Atom atom.xml application/atom+xml Modern feed readers
JSON Feed feed.json application/feed+json JavaScript apps, APIs

Prerequisites

Before generating syndication feeds, ensure your markata-go.toml has the required site metadata:

[markata-go]
title = "My Blog"                      # Required for all feeds
description = "A blog about things"    # Used in RSS/Atom/JSON
url = "https://example.com"            # Required for absolute URLs
author = "Jane Doe"                    # Used in Atom/JSON feeds

1. Generate a Sitemap

The sitemap plugin automatically generates a sitemap.xml file containing all published posts and feed index pages.

Enable the Sitemap

The sitemap is generated automatically when the sitemap plugin runs. No additional configuration is required for basic usage.

Output: /sitemap.xml in your output directory

Example Sitemap Output

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>https://example.com/</loc>
        <lastmod>2024-01-15</lastmod>
        <changefreq>daily</changefreq>
        <priority>1.0</priority>
    </url>
    <url>
        <loc>https://example.com/my-first-post/</loc>
        <lastmod>2024-01-15</lastmod>
        <changefreq>weekly</changefreq>
        <priority>0.8</priority>
    </url>
    <url>
        <loc>https://example.com/blog/</loc>
        <lastmod>2024-01-15</lastmod>
        <changefreq>weekly</changefreq>
        <priority>0.6</priority>
    </url>
</urlset>

Customize Sitemap Values via Frontmatter

Override changefreq and priority per-post in your markdown frontmatter:

---
title: "Important Announcement"
date: 2024-01-15
published: true
sitemap:
  changefreq: daily      # Options: always, hourly, daily, weekly, monthly, yearly, never
  priority: 0.9          # Range: 0.0 to 1.0
---

Default Sitemap Values

Page Type changefreq priority
Home page daily 1.0
Posts weekly 0.8
Feed index pages weekly 0.6

Exclude Posts from Sitemap

Use skip: true in frontmatter to exclude a post from the sitemap:

---
title: "Draft Post"
skip: true
---

2. Generate RSS Feeds

RSS 2.0 feeds are the most widely supported format for feed readers.

Enable RSS for a Feed

markata-go.feeds
slug = "blog"
title = "My Blog"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true                  # Enable RSS output

Output: /blog/rss.xml

Example RSS Output

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>My Blog</title>
    <link>https://example.com</link>
    <description>A blog about things</description>
    <language>en-us</language>
    <lastBuildDate>Mon, 15 Jan 2024 12:00:00 +0000</lastBuildDate>
    <atom:link href="https://example.com/blog/rss.xml" rel="self" type="application/rss+xml"/>

    <item>
      <title>My First Post</title>
      <link>https://example.com/my-first-post/</link>
      <description>This is the post description...</description>
      <pubDate>Mon, 15 Jan 2024 12:00:00 +0000</pubDate>
      <guid isPermaLink="true">https://example.com/my-first-post/</guid>
    </item>
  </channel>
</rss>

RSS Configuration Options

Control RSS behavior via feed defaults:

[markata-go.feed_defaults.syndication]
max_items = 20              # Maximum items in RSS feed (default: 20)
include_content = true      # Include full content or just description

RSS with Full Content

To include full post content instead of just the description:

[markata-go.feed_defaults.syndication]
include_content = true

When include_content = true, the <description> element contains the rendered HTML content (truncated to 500 characters). When false, it uses the post's description frontmatter field.


3. Generate Atom Feeds

Atom feeds (RFC 4287) provide richer metadata than RSS and are well-supported by modern feed readers.

Enable Atom for a Feed

markata-go.feeds
slug = "blog"
title = "My Blog"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true
atom = true                 # Enable Atom output

Output: /blog/atom.xml

Example Atom Output

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>My Blog</title>
  <id>https://example.com/blog/atom.xml</id>
  <updated>2024-01-15T12:00:00Z</updated>
  <link href="https://example.com" rel="alternate" type="text/html"/>
  <link href="https://example.com/blog/atom.xml" rel="self" type="application/atom+xml"/>
  <author>
    <name>Jane Doe</name>
  </author>

  <entry>
    <title>My First Post</title>
    <id>https://example.com/my-first-post/</id>
    <updated>2024-01-15T12:00:00Z</updated>
    <published>2024-01-15T12:00:00Z</published>
    <link href="https://example.com/my-first-post/" rel="alternate" type="text/html"/>
    <summary type="text">This is the post description...</summary>
    <content type="html">&lt;p&gt;Full post content...&lt;/p&gt;</content>
  </entry>
</feed>

Atom vs RSS: Key Differences

Feature RSS 2.0 Atom
Author info Limited Full (name, email, URI)
Content types Text only Text, HTML, XHTML
Update tracking lastBuildDate updated per-entry
Self-reference Via extension Built-in rel="self"
ID format URL (guid) IRI (more flexible)

When to Use Atom

When to Use RSS

Recommendation: Enable both RSS and Atom - let your users choose.


4. Generate JSON Feeds

JSON Feed (version 1.1) is a modern feed format designed for easy consumption by JavaScript applications.

Enable JSON Feed

markata-go.feeds
slug = "blog"
title = "My Blog"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true
atom = true
json = true                 # Enable JSON Feed output

Output: /blog/feed.json

Example JSON Feed Output

{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "My Blog",
  "home_page_url": "https://example.com",
  "feed_url": "https://example.com/blog/feed.json",
  "description": "A blog about things",
  "language": "en",
  "authors": [
    {
      "name": "Jane Doe"
    }
  ],
  "items": [
    {
      "id": "https://example.com/my-first-post/",
      "url": "https://example.com/my-first-post/",
      "title": "My First Post",
      "content_html": "<p>Full post content...</p>",
      "content_text": "Full post content...",
      "summary": "This is the post description...",
      "date_published": "2024-01-15T12:00:00Z",
      "date_modified": "2024-01-15T12:00:00Z",
      "tags": ["go", "tutorial"]
    }
  ]
}

JSON Feed Use Cases

  1. JavaScript consumption - Parse with fetch() and JSON.parse()
  2. API endpoints - Serve as a simple read-only API
  3. Static search indexes - Power client-side search
  4. Cross-origin requests - JSON has better CORS support than XML

Using JSON Feed in JavaScript

fetch('/blog/feed.json')
  .then(response => response.json())
  .then(feed => {
    feed.items.forEach(item => {
      console.log(item.title, item.url);
    });
  });

5. Combining Multiple Formats

The real power of markata-go's feed system is generating all formats from a single definition.

Complete Multi-Format Feed

[markata-go]
title = "My Tech Blog"
description = "Articles about Go, Python, and web development"
url = "https://techblog.example.com"
author = "Jane Doe"
output_dir = "public"

# Global feed defaults
[markata-go.feed_defaults]
items_per_page = 10

[markata-go.feed_defaults.syndication]
max_items = 20
include_content = true

# Main blog feed with ALL formats
markata-go.feeds
slug = "blog"
title = "Tech Blog"
description = "Latest articles about programming"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true                 # /blog/index.html, /blog/page/2/index.html
rss = true                  # /blog/rss.xml
atom = true                 # /blog/atom.xml
json = true                 # /blog/feed.json

Output Structure

public/
  sitemap.xml                    # Global sitemap (auto-generated)
  blog/
    index.html                   # HTML page 1
    page/
      2/
        index.html               # HTML page 2
    rss.xml                      # RSS 2.0 feed
    atom.xml                     # Atom feed
    feed.json                    # JSON Feed

Multiple Feeds with Different Formats

# Home page - HTML only
markata-go.feeds
slug = ""
title = "Home"
filter = "published == True"
sort = "date"
reverse = true
items_per_page = 5

[markata-go.feeds.formats]
html = true
rss = false
atom = false
json = false

# Blog - All syndication formats
markata-go.feeds
slug = "blog"
title = "Blog"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true
atom = true
json = true

# API endpoint - JSON only
markata-go.feeds
slug = "api/posts"
title = "Posts API"
filter = "published == True"
sort = "date"
reverse = true
items_per_page = 0              # No pagination - all posts

[markata-go.feeds.formats]
html = false
rss = false
atom = false
json = true

Help feed readers and browsers automatically discover your feeds by adding <link> tags to your HTML templates.

Template with Feed Discovery

Add these links to your base template's <head> section:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>

    <!-- RSS Feed Discovery -->
    <link rel="alternate"
          type="application/rss+xml"
          title="{{ site.title }} (RSS)"
          href="{{ site.url }}/blog/rss.xml">

    <!-- Atom Feed Discovery -->
    <link rel="alternate"
          type="application/atom+xml"
          title="{{ site.title }} (Atom)"
          href="{{ site.url }}/blog/atom.xml">

    <!-- JSON Feed Discovery -->
    <link rel="alternate"
          type="application/feed+json"
          title="{{ site.title }} (JSON)"
          href="{{ site.url }}/blog/feed.json">
</head>
<body>
    <!-- ... -->
</body>
</html>

If you have multiple feeds (blog, tutorials, etc.), add discovery links for each:

<head>
    <!-- Blog feeds -->
    <link rel="alternate" type="application/rss+xml"
          title="Blog (RSS)" href="/blog/rss.xml">
    <link rel="alternate" type="application/atom+xml"
          title="Blog (Atom)" href="/blog/atom.xml">

    <!-- Tutorial feeds -->
    <link rel="alternate" type="application/rss+xml"
          title="Tutorials (RSS)" href="/tutorials/rss.xml">
    <link rel="alternate" type="application/atom+xml"
          title="Tutorials (Atom)" href="/tutorials/atom.xml">
</head>

Dynamic Feed Discovery in Templates

For feed-specific pages, use template variables:

{% if feed %}
    {% if feed.formats.rss %}
    <link rel="alternate" type="application/rss+xml"
          title="{{ feed.title }} (RSS)"
          href="{{ feed.href }}rss.xml">
    {% endif %}

    {% if feed.formats.atom %}
    <link rel="alternate" type="application/atom+xml"
          title="{{ feed.title }} (Atom)"
          href="{{ feed.href }}atom.xml">
    {% endif %}

    {% if feed.formats.json %}
    <link rel="alternate" type="application/feed+json"
          title="{{ feed.title }} (JSON)"
          href="{{ feed.href }}feed.json">
    {% endif %}
{% endif %}

Also provide visible links for users who want to manually subscribe:

<footer>
    <h3>Subscribe</h3>
    <ul class="feed-links">
        <li><a href="/blog/rss.xml">RSS Feed</a></li>
        <li><a href="/blog/atom.xml">Atom Feed</a></li>
        <li><a href="/blog/feed.json">JSON Feed</a></li>
    </ul>
</footer>

Complete Example Configuration

Here's a full markata-go.toml with all syndication features configured:

[markata-go]
# Site metadata (required for syndication feeds)
title = "My Tech Blog"
description = "Articles about Go, Python, and web development"
url = "https://techblog.example.com"
author = "Jane Doe"

# Build settings
output_dir = "public"
templates_dir = "templates"

# Content discovery
[markata-go.glob]
patterns = ["posts/**/*.md", "pages/*.md"]

# Markdown extensions
[markata-go.markdown]
extensions = ["tables", "strikethrough", "tasklist"]

# =============================================================================
# FEED DEFAULTS
# =============================================================================

[markata-go.feed_defaults]
items_per_page = 10
orphan_threshold = 3

[markata-go.feed_defaults.formats]
html = true
rss = true
atom = true
json = false

[markata-go.feed_defaults.syndication]
max_items = 20                  # Items in RSS/Atom/JSON feeds
include_content = true          # Include full content in feeds

# =============================================================================
# FEEDS
# =============================================================================

# Home page - HTML only, no syndication
markata-go.feeds
slug = ""
title = "Recent Posts"
filter = "published == True"
sort = "date"
reverse = true
items_per_page = 5

[markata-go.feeds.formats]
html = true
rss = false
atom = false

# Main blog - Full syndication
markata-go.feeds
slug = "blog"
title = "Blog"
description = "All blog posts"
filter = "published == True"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true
atom = true
json = true

# Tutorials - RSS and Atom only
markata-go.feeds
slug = "tutorials"
title = "Tutorials"
description = "Step-by-step programming guides"
filter = "published == True and 'tutorial' in tags"
sort = "date"
reverse = true

[markata-go.feeds.formats]
html = true
rss = true
atom = true
json = false

# JSON API endpoint
markata-go.feeds
slug = "api/posts"
title = "Posts API"
filter = "published == True"
sort = "date"
reverse = true
items_per_page = 0              # All posts, no pagination

[markata-go.feeds.formats]
html = false
rss = false
atom = false
json = true

Generated Output

public/
  index.html                     # Home page
  sitemap.xml                    # Global sitemap

  blog/
    index.html                   # Blog page 1
    page/2/index.html            # Blog page 2
    rss.xml                      # RSS feed
    atom.xml                     # Atom feed
    feed.json                    # JSON feed

  tutorials/
    index.html                   # Tutorials page 1
    rss.xml                      # RSS feed
    atom.xml                     # Atom feed

  api/
    posts/
      feed.json                  # JSON API (all posts)

Troubleshooting

Feed URLs show https://example.com

Ensure you've set the url field in your config:

[markata-go]
url = "https://your-actual-domain.com"

Feeds are empty

Check that posts have published = true (or your filter matches):

---
title: "My Post"
published: true    # Required for most filters
---

Author missing in Atom/JSON feeds

Set the author field:

[markata-go]
author = "Your Name"

Feed not generating

Ensure the format is enabled:

[markata-go.feeds.formats]
rss = true     # Must be explicitly true

See Also