Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RSS feeds

Blogatto generates RSS 2.0 feeds from your blog posts. You can configure multiple feeds with different filters (e.g., one per language) and customize how posts are serialized into feed items. RSS feeds work alongside Atom feeds — both can be generated from the same build.

Basic setup

import blogatto/config
import blogatto/config/feed/rss

let rss_feed =
  rss.new("My Blog", "https://example.com", "My personal blog")
  |> rss.language("en-us")
  |> rss.generator("Blogatto")

let cfg =
  config.new("https://example.com")
  |> config.rss_feed(rss_feed)

This generates dist/rss.xml containing all blog posts with auto-generated excerpts. The excerpt length is controlled by post.excerpt_len() (default: 200 characters).

RssFeedConfig fields

Required fields (passed to rss.new())

FieldTypeDescription
titleStringChannel title
linkStringWebsite URL
descriptionStringChannel description

Optional fields (set via builder functions)

FieldSetterDefaultDescription
outputrss.output()"/rss.xml"Output path relative to output_dir
languagerss.language()NoneLanguage code (e.g., "en-us")
copyrightrss.copyright()NoneCopyright notice
managing_editorrss.managing_editor()NoneEditor email
web_masterrss.web_master()NoneWebmaster email
pub_daterss.pub_date()NoneChannel publication date
last_build_daterss.last_build_date()NoneLast build timestamp
categoriesrss.category()[]Channel category tags (prepends)
generatorrss.generator()NoneGenerator program name
docsrss.docs()NoneURL to RSS format documentation
cloudrss.cloud()NoneCloud service for update notifications
ttlrss.ttl()NoneCache time-to-live in minutes
imagerss.image()NoneChannel image
text_inputrss.text_input()NoneChannel text input field
skip_hoursrss.skip_hour()[]Hours (0-23) to skip updates (prepends)
skip_daysrss.skip_day()[]Days to skip updates (prepends)
filterrss.filter()NoneInclude/exclude posts
serializerss.serialize()NoneCustom item serialization

Filtering posts

Use the filter function to control which posts appear in a feed. The function receives FeedMetadata (from blogatto/config/feed) containing the post and its URL path:

import blogatto/config/feed
import gleam/option

// Only include English posts
let rss_feed =
  rss.new("My Blog", "https://example.com", "My personal blog")
  |> rss.filter(fn(meta: feed.FeedMetadata(Nil)) {
    meta.post.language == option.None
    || meta.post.language == option.Some("en")
  })

Custom serialization

Override how posts become feed items with the serialize function:

import blogatto/config/feed
import gleam/dict
import gleam/option.{None, Some}

let rss_feed =
  rss.new("My Blog", "https://example.com", "My personal blog")
  |> rss.serialize(fn(meta: feed.FeedMetadata(Nil)) {
    let author =
      dict.get(meta.post.extras, "author")
      |> result.map(Some)
      |> result.unwrap(None)

    rss.RssFeedItem(
      title: meta.post.title,
      description: meta.post.excerpt,
      link: Some(meta.url),
      author: author,
      comments: None,
      source: None,
      pub_date: Some(meta.post.date),
      categories: [],
      enclosure: None,
      guid: Some(meta.url),
    )
  })

Multiple feeds

Call config.rss_feed() multiple times to generate separate feeds:

let en_feed =
  rss.new("My Blog (English)", "https://example.com", "My personal blog")
  |> rss.language("en-us")
  |> rss.filter(fn(meta) {
    meta.post.language == option.None
    || meta.post.language == option.Some("en")
  })

let it_feed =
  rss.new("Il mio Blog (Italiano)", "https://example.com", "Il mio blog personale")
  |> rss.output("/rss-it.xml")
  |> rss.language("it")
  |> rss.filter(fn(meta) {
    meta.post.language == option.Some("it")
  })

let cfg =
  config.new("https://example.com")
  |> config.rss_feed(en_feed)
  |> config.rss_feed(it_feed)

FeedMetadata

The FeedMetadata(msg) type (from blogatto/config/feed) passed to filter and serialize functions:

FieldTypeDescription
pathStringURL path (e.g., "/blog/my-post")
postPost(msg)The full parsed blog post (includes excerpt field)
urlStringThe absolute URL of the post

RssFeedItem

The RssFeedItem type returned by serialize functions:

FieldTypeDescription
titleStringItem title (required)
descriptionStringItem description (required)
linkOption(String)Item URL
authorOption(String)Author email or name
commentsOption(String)Comments URL
sourceOption(String)Source feed URL
pub_dateOption(Timestamp)Publication date
categoriesList(String)Category tags
enclosureOption(Enclosure)Media attachment
guidOption(String)Globally unique identifier