Tagged as website
Written by Lily Carpenter on 2014-11-24
Updates
- 2015-10-21T09:21:00Z Updated published/updated timestamp to be iso8601 format.
- 2017-05-15T00:10:00Z Fix various broken links.
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/split
(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:
(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))))
my-map)))
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)))
pages))
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).