Generating RSS with FlatLake
By R. S. Doiel, 2025-08-10
One of the must have features missing from many static websites are RSS feeds. Many people produce blogs using CommonMark/Markdown documents with front matter.FlatLake produces a JSON API from front matter. The API makes it easy to generate various types of feeds. All that is needed is something to translate the JSON API documents to the feed format you want. In this post I will show a proof of concept using Deno+TypeScript to process the Flatlake generate JSON API into an RSS feed.
Requirements for your site
You need FlateLake installed. You also need to have front matter in your CommonMark/Markdown documents. No front matter, no API. I rely on front matter in my publication process for blog so FlatLake is a good fit. I only use a mimum of features in FlatLake. Here's the configuration file I use.
global:
outputs:
- "list"
collections:
- output_key: "posts"
page_size: 24
sort_key: "datePublished"
sort_direction: "desc"
list_elements:
- "data"
- "content"
inputs:
- path: "./blog"
glob: "**/*{md}"
Generating the json api
Once you have FlatLake configured generating the JSON API is as simple as running the command
flatlake
That's it. It scans the directory named "blog" in the directory where I stage my
website. The output goes to a directory called "api". If you prefer a diffent
path FlatLake has options to support that. See flatlake --help or the websiteFlatLake/docs. The verbose and logging options are
helpful in understanding what FlatLake is doing.
Short anatomy of RSS XML
The RSS XML has two parts. A channel description and the items in the feed. The items map the data about your blog posts. The channel description isn't directly available from the FlatLake generated data. The easy solution I've chosen is to describe the channel in a YAML. Here's the example I use for my blog.
title: "Robert's Ramblings"
description: "Robert's website and blog posts"
link: "https://rsdoiel.github.io"
JSON API to RSS
In my publication process the next thing I do is used a Deno+TypeScript program
to convert the JSON API into an RSS feed. I have one feed for my site contains
recent posts. The path in the api tree I use it api/posts/all/page-1.json.
Based on my configuration file this contains the most recent 24 posts sorted by
descending publication date. At this point it's just a matter of cross walking
the content of "page-1.json" into an RSS XML feed file.
Here's a TypeScript module I knock together to test out the concept.
/**
* flatlakeToRSS2.ts translate a FlatLake JSON API document to RSS2 XML.
*
* Copyright (C) 2025 R. S. Doiel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Define the structure of your input data
export interface Post {
content: string;
data: {
abstract: string;
author: string;
dateCreated?: string;
dateModified?: string;
datePublished?: string;
keywords: string[];
pubDate?: string;
title: string;
url: string;
};
}
// Define the structure of the RSS feed
export interface RSSFeed {
title: string;
description: string;
link: string;
language?: string;
copyright?: string;
managingEditor?: string;
webMaster?: string;
items: RSSItem[];
}
export interface RSSItem {
title: string;
description: string;
link: string;
pubDate: string;
author: string;
categories: string[];
}
// Function to convert JSON data to RSS feed with YAML configuration
export function convertToRSS(
posts: Post[],
channelInfo: Partial<RSSFeed>,
): RSSFeed {
const feed: RSSFeed = {
title: channelInfo.title || "My Blog",
description: channelInfo.description || "A collection of blog posts",
link: channelInfo.link || "http://example.com",
language: channelInfo.language,
copyright: channelInfo.copyright,
managingEditor: channelInfo.managingEditor,
webMaster: channelInfo.webMaster,
items: [],
};
posts.forEach((post) => {
const item: RSSItem = {
title: post.data.title,
description: post.data.abstract,
link: `http://example.com/${post.data.url}`,
pubDate: new Date(
post.data.datePublished || post.data.pubDate || post.data.dateCreated ||
post.data.dateModified || Date.now(),
).toUTCString(),
author: post.data.author,
categories: post.data.keywords,
};
feed.items.push(item);
});
return feed;
}
// Function to generate the RSS XML
export function generateRSS(feed: RSSFeed): string {
const itemsXML = feed.items
.map(
(item) => `
<item>
<title><![CDATA[${item.title}]]></title>
<description><![CDATA[${item.description}]]></description>
<link>${item.link}</link>
<pubDate>${item.pubDate}</pubDate>
<author>${item.author}</author>
${
item.categories.map((category) => `<category>${category}</category>`)
.join("")
}
</item>
`,
)
.join("");
return `<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[${feed.title}]]></title>
<description><![CDATA[${feed.description}]]></description>
<link>${feed.link}</link>
${feed.language ? `<language>${feed.language}</language>` : ""}
${feed.copyright ? `<copyright>${feed.copyright}</copyright>` : ""}
${
feed.managingEditor
? `<managingEditor>${feed.managingEditor}</managingEditor>`
: ""
}
${feed.webMaster ? `<webMaster>${feed.webMaster}</webMaster>` : ""}
${itemsXML}
</channel>
</rss>`;
}
Putting it all together
The demo program can be compiled with the follow.
git clone https://github.com/rsdoiel/flatlakeToRSS2
cd flatlakeToRSS2
deno task build
The program in the bin directory can then be used to generate the RSS XML from
your FlatLake API. Copy it to some place in your PATH.
Now I go to my website staging directory. I can take the following steps to test RSS generation from FlatLake.
cd $HOME/Sites/rsdoiel.github.io
flatlake
edit rss_channel.yaml # Create the YAML file above
flatlakeToRSS2 rss_channel.yaml api/posts/all/page-1.json >rss.xml
Lessons learned
There are some very good feed libraries out there likeDave Winer's ReallySimple. That could save using format strings to render XML. It also has the advantage that is can be use to read feeds as well.
Ideally I'd like the generation of RSS feeds to be in integrated into myBlogIt tool I am working on.
This experiment showed that inspite of the limitted documentation of the FlatLake website that it's worth exploring as an off the shelf open source solution. It might just earn a place along side PageFind and Pandoc as part of my regular web toolkit.