This is the first actual post that happens on this space, https://bendersteed.tech. Since I'm trying to move my infrastructure to a personal machine, it made sense to stop using my gitlab pages blog and host my blog here as well.

Since I wanted to migrate things, I also changed a few things on my blogging flow. Recently I have fallen in love with a very simple but not simplistic piece of software, haunt by David Thompson. Haunt is a static site generator written in Guile that provides just the basics and is built around the concept of builders that use representations of the notions of a site, a page or whatever needs to be built in order to abstract the whole process. This in combination with Guile, an implementation of Scheme, gives a lot of power in expressing the process in many ways and extending the system with useful capabilities. Since I contribute to Guix from time to time, the familiarity I have built with Guile is also a big plus for me.

As an example, lately I'm working on a podcast, you can check it out here – though keep in mind it's targeted at Greek speakers. One of the needs was a JSON representation of my posts to be consumed by a media player widget built with Amplitude.js. So very succinctly, I was able to define a custom builder, leveraging the json module for Guile to do what I needed:

(define (make-episode-scm post)
  (let ((enclosure (post-ref post 'enclosure)))
    `((name . ,(post-ref post 'title))
      (info . ,(post-ref post 'summary))
      (url . ,(enclosure-url enclosure))
      (cover_art_url . ,(post-ref post 'cover))
      (date . ,(date->string* (post-date post))))))

(define (make-episodes-json site posts)
  (let* ((post (car posts))
     (enclosure (post-ref post 'enclosure)))
    (make-page  "/assets/js/episodes.json"
        `((songs . ,(list->vector
                 (map make-episode-scm
                  (take-up-to 10 (posts/reverse-chronological posts))))))
        scm->json)))

Then I just appended the builder to the builders list of my site definition:

(site #:title "The Conspiracy Club"
      #:domain "theconspiracyclub.gr"
      #:default-metadata
      '((author . "bendersteed"))
      #:readers (list commonmark-reader texinfo-reader skribe-reader sxml-reader html-reader)
      #:builders (list
          (blog #:prefix "/episodes"
            #:theme tcc-haunt-theme)
          make-episodes-json
          index-page
          (atom-feed)
          (atom-feeds-by-tag)
          (static-directory "assets" "assets")))

and now every time I build the site I also build the appropriate episodes.json file. As is apparent every builder in haunt is a function that gets passed the site and posts records.

So I think you agree with me that, haunt is pretty neat. Before haunt I used hugo as my go-to static site generator, along with the wonderful ox-hugo package for emacs. The flow that these two created was excellent and a major reason why I kept to blog at somewhat frequent intervals. To learn more about what I mean, check out my earlier post on hugo and ox-hugo here. Hugo on its own is pretty great - it's fast, feature-full, has a great community and lots of resources available to achieve everything. At the same time it seemed a bit overkill for what I wanted it to do, and I think that I prefer the minimalist approach by haunt.

In the end the only things that I'm missing at my current setup are the ox-hugo package, multi-language support and the html support for the guile-commonmark library that I use to handle my posts. For the ox-hugo package I found the ox-haunt package as a possible candidate. Now it seems that it doesn't support my preferred way of managing my blog, by having all the posts in a single org-mode file. I have started working to add that functionality though, and it seems quite easy. This would also solve the guile-commonmark issues since ox-haunt emanates html code. For the multi-language issue I currently have duct-taped it by using an emacs lisp program to combine separate sites for every language. It would be interesting to implement a more proper solution, though it works for now.

The migration of old posts was quite easy, with the use of some emacs lisp code. I will expand on the migration process in a separate post, since this one is quite long already!

So that's all for now, welcome to my new space on the web and I hope to see you back.

🐢🐢🐢