 Up |  Home

I Joined The Craftering

Date: [2025-04-25 Fri]

With some encouragement from Shom, a member of the System Crafter's community, I have decided to join their webring. Specifically, the System Crafter's own webring: Craftering.

The underlying technology for the Craftering is called ringfairy. In the ringfairy repository, it states:

"A webring is a collection of websites linked together in a loop. Each website contains links to the previous and next websites in the ring. If you navigate far enough, eventually you end up back where you started!"

It also states that webrings were a popular mechanism for discovery in the early Internet era. I can barely recall these things existing. As more of the popular Internet is dominated by huge tech companies, I feel like webrings are an amazing way to bring things back to the grass roots a little bit. The Craftering is a community of like-minded hackers that feels like a good fit for me.

Preparing to join the Craftering

There were a few preparation steps to join the Craftering. All of them are detailed in the Craftering website. In addition to those requirements, I felt like my website needed an RSS feed. Though they are not strictly required, I think RSS feeds are the best way to consume decentralized blog content. The Craftering creates an aggregate OPML file to subscribe to all of its members. I want to be in that list of feeds.

To do this, I leveraged the org-publish-rss package. It made it super easy to streamline the generation of my rss feed.

(setq org-publish-project-alist
      '(("blog" ; these entries among all my other entries
         :base-directory "./content/blog"
         :publishing-directory "./public/blog"
         :publishing-function org-html-publish-to-html
         :html-link-home "https://trevdev.ca/blog/"
         :base-extension "org"
         :exclude "index.org"
         :with-toc nil
         :section-numbers nil
         :auto-rss t
         :rss-title "Trev's Blog"
         :rss-description "Sometimes I write about the things that I enjoy."
         :rss-with-content all
         :completion-function org-publish-rss)
        ("blog-static"
         :recursive t
         :base-directory "./content/blog"
         :publishing-directory "./public/blog"
         :publishing-function org-publish-attachment
         :base-extension "png\\|jpg\\|gif\\|xml")))

To insert the required Craftering links into the postamble of this website, I used a bit of esxml.

(div ((class . "content craftering"))
     (a ((href . ,(concat craftering
                          "/@trevdev/previous")))
        "󰒮 previous")
     (a ((href . ,craftering))
        " crafters")
     (a ((href . ,(concat craftering
                          "/@trevdev/next")))
        "next 󰒭"))

With a little bit of CSS, I had the links looking decent.

.craftering {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

For a more complete view of how I generate this website, its content and the RSS feed, the source code is linked in the footer.

Subscribing to the Craftering's RSS feeds

My RSS reader is elfeed in Emacs. I can use the elfeed-load-opml function to load the OPML file into the elfeed-feeds variable.

I had some questions to answer first:

  • What if I don't have the opml file downloaded?
  • What if I ever want to easily update the file?
  • What if the Craftering isn't the only opml file I ever hope to download and add to my reader?

To solve these problems I decided to hack some Elisp to make it all happen. The first step was to create a list of opml sources and destinations.

(defvar td-opml-files
  '(("https://craftering.shom.dev/Craftering.opml"
     . "~/.emacs.d/elfeed/craftering.opml"))
  "A list of OPML files to load into elfeed.")

Next, create a function to update these files

(defun td-update-opml-files ()
  "Update the collection of `td-opml-files'."
  (interactive)
  (dolist (opmlf td-opml-files)
    (let ((source (car opmlf))
          (file (cdr opmlf)))
      (delete-file file)
      (url-copy-file source file))))

I needed to get and install the opml files in the event that they did not already exist on the system, and load them with elfeed-load-opml. I used a helper function called td-file-from-internet. I used it to bootstrap numerous things throughout my configuration.

(defun td-file-from-internet (file url)
  "Get a `FILE' from the internet at some `URL'."
  (when (not (file-exists-p file))
    (make-directory (file-name-directory file) t)
    (url-copy-file url file)
    (message "Dependency %s was installed from %s" file url)))

(dolist (opmlf td-opml-files)
  (td-file-from-internet (cdr opmlf) (car opmlf))
  (elfeed-load-opml (cdr opmlf)))

Lastly, I added non-opml subscriptions to the elfeed-feeds variable.

(dolist (feed '(("https://systemcrafters.net/rss/news.xml" emacs guix)
                ("https://git.sr.ht/~taingram/org-publish-rss/log/rss.xml" sourcehut)))
  (add-to-list 'elfeed-feeds feed))

Now I can run M-x elfeed-update and go view all of my blog subscriptions.

If you haven't done this already, go play with the Craftering links at the bottom of this website. That is, of course, if you didn't get here via the Craftering in the first place ;)