Hugo is the static site generating content management system that I use to publish this website. It works really well, and has some deep functionality that I’m not even touching. For instance, it can parse data files while generating the site - including JSON and XML - and can use the content of those files to display information on web pages.

I was going to follow some recipes that I found online, but they involved converting the OPML file into JSON to be read by Hugo. I didn’t want to do that if possible. So, time to roll my own solution using built-in functionality in Hugo…

And OPML is just XML, and Hugo can do stuff with XML. So…

⚠️ - Warning

This approach works for me, but I have no idea if it’s anywhere near the best way to do this, or even if it’s safe or reliable or whatever. I’m not a Hugo programmer. Heck, I haven’t had the chance to actually write code in years now. But, this solution scratches my itch. Your mileage may vary.

Step 1 - export your RSS subscriptions

Export your feed reader’s RSS subscriptions as an .opml file. I use NetNewsWire, and its export tool is at File > Export Subscriptions.

Copy that into your Hugo site’s data folder (create one if you don’t have one there yet). Rename the file to “data/blogroll.xml” - Hugo can parse XML files, but has no idea what to do with the .opml file extension.

Step 2 - create a shortcode to render the subscriptions

I created a shortcode called “opmlblogroll” (at layouts/shortcodes/opmlblogroll.html), containing this Hugo template code: (I’ve added a space between the {{ characters so Hugo won’t choke while rendering this page. If you copy/paste the code into your own shortcode or whatever, be sure to remove the spaces between { { )

{ {< range $.Site.Data.blogroll.body.outline >}}
	<h2>{ {< index . "-text" >}}</h2>
	<ul>
	{ {< range index . "outline" >}}
		<li><a href='{ {< index . "-htmlUrl" >}}'>{ {< index . "-text" >}}</a> (<a href='{ {< index . "-xmlUrl" >}}'>feed</a>)</li>
	{ {< end >}}
	</ul>
{ {< end >}}

That’s a hardcoded template that looks for the file “/data/blogroll.xml” (you don’t need the file extension). It then iterates through the outline items at the root of the document - these are the “folders” of feeds in NetNewsWire - and then displays the name of the folder and iterates through its contents. It creates an unordered list for each folder, creating a hyperlink to the website (htmlUrl), displaying the title (text), and linking directly to the feed. Note that these are attributes of an XML outline element, and Hugo grabs attributes by prepending “-”, so the “text” element becomes “-text”.

Note - there is no error or sanity checking in this template. It just expects outlines to be nested as I see them in NetNewsWire, and expects them to have all content filled in. I don’t know what would happen if it gets bad or missing data. It’d probably throw an error and refuse to build the site until it’s fixed.

Step 3 - add the shortcode to a page or something

I created a new page, creatively titled “Blogroll”, and added the shortcode to it ala:

{ {< opmlblogroll >}}

That will cause Hugo to render the blogroll file as content on the page, replacing the shortcode.

I also put a copy of the blogroll.opml file into static/blogroll.opml so it’s web-visible if anyone wants to use the OPML file directly.

To update the blogroll page, I just need to re-export the blogroll.opml file from NetNewsWire and save it into data/blogroll.xml (and also save a copy into static/blogroll.opml if needed - I may look at setting up a symlink or something to make that automatic…)

Step 4 - clean up your subscriptions

I have 168 subscriptions and they’ve been carried through different RSS readers over the years. The subscriptions themselves haven’t been visible, so I haven’t worried about folder names or whatnot. Now that they’re somewhat visible, I’ll need to spend some time cleaning things up.

For now, the " ★★★★★" folder is my must-read folder. If I only have a couple of minutes to check feeds, that’s the one that gets read. Then I mostly work down the list of folders in alphabetical order. Some feeds are in the wrong folders. Some could be in several. I’ll reorganize them over time, but not right away. If you see your feed in the wrong place, it’s ok. It’ll get to the right folder eventually, and I see all feed items anyway.