My Own Blog

April 15, 2014

Building a blogging system is like making your own Jedi lightsaber.

It’s not a new thing for programmers to write their own blogging platform, but it certainly appears appear to have become de rigueur of late, especially those that generate static sites.

In fact, it may have become the programmer-nerd equivalent of a Jedi knight completing his apprenticeship by fashioning his own light saber.

Not to be left out, I’ve gone and done the same thing. My reasons are probably the same as everyone else’s, but here they are anyway:

  • A static site will better handle the enormous amount of traffic I expect to receive.

  • (more seriously) I expect to put a good deal of myself into this over time, and I don’t want to be continually compromising what I produce to fit the tool, or making terrible hacks to someone else’s code.

  • I don’t want to spend any time — at all — sys admin’ing my blog …

  • … but, I also don’t want a third party owning my online content and identity.

  • It’s an irresistible challenge to any self-respecting programmer nerd. It’s simply the perfect toy problem domain, almost as good as writing a Twitter client! And everyone else’s blog engines are bloated, ugly, and have fleas.


So I built my own static blogging platform — the one you’re reading at the moment. And don’t worry, I’m not going to bore you by going on explain how great it is, instead I’m going bore you by explaining how great Clojure is for building this sort of thing.

I put my blog system forward as sweet example of something that makes me happy. Because, when it comes down to it, while some of the software we develop makes happy by its function, often this not so much the case with its form. Even our most angelic conceptions usually end up scarred and twisted after extended contact with the real world.

I’m going to illustrate why writing this blog generator made me happy with just two examples, but let me assure you it’s angels all the way down, not a demon to be seen. Well, perhaps just an imp or two.

Not A Framework In Sight

Coming from a Java background, I know a framework when I see it. So, had I written this blog in Java, when it came time to produce its RSS feed I would have reached for a comforting API or two to help me out.

But I wrote this in Clojure, and here’s the code that generates the Atom feed for this blog:

(defn atom-feed [articles]
  (xml/sexp-as-element
    [:feed {:xmlns "http://www.w3.org/2005/Atom"
            :xml:lang "en-au"}
     [:title "Sapient Pair"]
     [:subtitle "An à la carte selection of my thoughts"]
     [:id "http://sapient-pair.com/blog"]
     [:link {:href "http://sapient-pair.com/blog"}]
     [:link {:rel "self" :href "http://sapient-pair.com/blog/feed.atom"}]
     [:updated (atom-date (most-recently-changed articles))]
     [:author [:name "Matthew Phillips"]]
     (for [article (take 20 (sort-by :published descending articles))]
       (let [url (str "http://sapient-pair.com" (abs-article-path article))]
         [:entry
          [:title (:title article)]
          [:link {:href url}]
          [:id url]
          [:published (atom-date (:published article))]
          [:updated (atom-date (or (:updated article) (:published article)))]
          (if (:summary article)
            [:summary {:type "text"} (:summary article)])
          (if-let [content (atom-content (content-of article articles))]
            [:content {:type "xhtml"} content])]))]))

(defn atom-date [d]
  (format-date :date-time-no-ms d))

Rather than a series of new’s and .setThis() and .setThat(), what you see is an almost literal Atom RSS feed, shamelessly adapted from elsewhere. The only ‘API’ call is xml/sexp-as-element from the clojure.data.xml library, which generates the actual XML.

I think it would have taken me longer to install and work out how to use a Java library for RSS than it did to convert the example Atom feed to Clojure. The only thing that took any real time was working out how to generate the XHTML partial article content (done by the call to atom-content, which ended up being only another 15 lines of code).

The other library dependency is the excellent clj-time Clojure layer for the equally excellent Joda-Time Java date handling and formatting library.

The code to select the 20 newest articles for the feed is:

(take 20 (sort-by :published descending articles))

Rather than something that I would be much less happy to have to write in Java.

The most-recently-changed function, which selects — you guessed it — the most recent article either by published or updated date, is nice too:

(defn most-recently-changed [articles]
  (reduce max (concat (keep :published articles) (keep :updated articles))))

(The max function here selects the maximum of two values using the standard compare function.)

It looks especially nice compared to the equivalent in Java:

class Articles
{
  public static Article mostRecentlyChanged (List<Article> articles)
  {
    Date mostRecent = new Date (0);

    for (Date article : articles)
    {
      if (article.getPublished ().compare (mostRecent) > 0)
        mostRecent = article.getPublished ();

      if (article.getUpdated ().compare (mostRecent) > 0)
        mostRecent = article.getUpdated ();
    }
  }

  return mostRecent;
}

(And I’m not including the definition of an Article class with its fields and getter methods.)

My intent here isn’t to rag on Java, or pimp my elite Clojure skilz, but to show one way that Clojure made this more fun by not forcing me to think about anything unrelated to getting the job done.

Concise Slice And Dice

The second example is the code that generates this site’s archives page:

(defn archives-page [articles]
  (base-page "Sapient Pair - Blog Archive"
    [:div#archives.with-margin
     [:h1.title "Blog Archives"]
     (for [[year articles] (->> articles
                             (group-by (comp year :published))
                             (sort descending))]
       [:div.year-articles
        [:h1.year year]
        (for [article (sort-by :published descending articles)]
          [:div.article.row
           [:h2.article-title
            [:a {:href (str "../" (:path article))}
             (h (:title article))]]
           [:div.article-date
            (format-date "MMM dd" (:published article))]
           (if (:tags article)
             [:div.tags "Posted in: "
              (->>
                (for [tag (sort (:tags article))]
                  [:span.tag (h tag)])
                (interpose ", "))])])])]))

Once again, this is almost literally the structure of the thing that’s being generated — modulo the base-page wrapper, which adds the boilerplate HTML around every page. Here, rather than generating XML as in the first example, I’m using hiccup to take the Clojure structure and generate HTML.

The code that groups articles by year for the archives page is:

(for [[year articles] (->> articles
                             (group-by (comp year :published))
                             (sort descending))]
    ... )

It’s hard to imagine a way to write this more concisely.


Writing in Clojure tends to make me happy. There are other languages like this for me, Haskell being high on the list. But the key difference between Haskell and Clojure — static vs. dynamic typing — is also part of why I like Clojure better. With Haskell I’m also programming its type system, and it often feels more like I’m wrestling it (sometimes with good reason of course, but a lot of the time it just feels like nit-picking).

The other part I enjoy is Clojure’s total lack of emphasis on OO programming, which is why I prefer it to other dynamic languages like Python and Ruby. There’s a certain aesthetic beauty to functional Lisps in general1 that’s completely absent in the BumpyNamedClasses and new this.that ().theOther () of common OO syntax.

I began learning program just before OO became mainstream, and I remember being pretty excited when I was able to start using objects for real work using C++, and then Java. But I think I’ve come to the end of that phase, as I realise how much is forgotten, or overlooked, by the tunnel vision that comes with the everything-is-an-object mindset.

This was going to be a short post. Perhaps I’ll tl;dr it by summarising: programming in a language that doesn’t get in your way will make you happier. Who knew?

  1. When THEY’RE NOT SHOUTING AT YOU IN ALL CAPS, that is. ↩︎