Tagged as website

Written by Lily Carpenter on 2014-11-24


After many years of my domain leading to an "Under Construction" page, I decided that it was time for me to actually sit down and write a website. I decided I wanted to use Clojure since it was my new favorite language to play with and started down my usual route of a MVC based site. As I played with Compojure and Korma I realized that for a simple blog/portfolio based site MVC was overkill.

I scrapped my original idea and researched static site generation in Clojure. I quickly found a blog post by Christian Johansen on using Stasis and other Clojure libraries (see this site's gitlab for a full list[no longer accurate since site has been rebuilt]) to setup a basic static site with a developer server.

However, this basic template was not complete enough for my site as-is. Primarily, I needed more dynamic control over the site layout/templating. For instance I wanted the site title to be generated based on a formatted version of the file name of the page. The formatting itself was easily accomplished:

(defn format-title [title]
  (str/join " "
            (map str/capitalize
                  (str/replace title #"(.*/|\.html)" "")

I did find myself with a small problem. I ended up needing to map over a hash-map and format the key then pass the formatted key to a function along with the value. I didn't find a function that already does this, so I imagine there was a different way to do it. In the end, I ended up with this function to perform this:

;; This is probably a case of me not knowing a better way to do this...
;; my-map is a hash-map
;; key-func takes a key and returns a key
;; val-func takes the formatted key and the val and returns a key
(defn map-map-with-funcs [key-func val-func my-map]
  (apply merge (map (fn [[k v]]
                      (let [new-key (key-func k)]
                        (hash-map new-key (val-func new-key v))))

I ended up using this function like this, where pages is a hash-map with the key being the filename and the value being the contents of the file:

(defn partial-pages [pages]
  (map-map-with-funcs #(str/replace % #"\.clj$" "")
                      #(fn [req]
                         (layout-page req %1 (load-string %2)))

I am new to clojure so I imagine this is neither idomatic nor efficient (for instance, my map-map-with-funcs function may be better written as a macro). However, it is certainly working for my purposes.

The best part of all of this is that in the end, what I have is a bunch of minimized html/css/js that is easily served by Nginx making a very low resource site that easily runs on my small Linode instance. I also got some practice using Clojure.

My next steps are to include some kind of hosted comments (I need to research options) so that I can get feedback from the readers of the site and continue to write blog posts (and talk at local meetups).