Why I Built a Static Site in Clojure
Contents
At a summer barbecue, a friend asked if I could build a website for his new restaurant. But what he didn't know was that I haven't built a static site in nearly a decade. However I couldn't let him spend thousands of dollars on a cookie cutter website designed by a firm that knew nothing about his restaurant.
We started coming up with ideas right away over a couple of beers. He wanted manageable content, an Instagram feed, and an easy to change restaurant menu. It quickly started sounding like a full on Content Management System and not a simple website. I had to reel in this ambitious project before it became a feature sink. So we decided to just make a beautiful static site.
I started using Wordpress
to build the website because I've used it in the past
and it's easy to expand. With a list of dream features in mind, a basic website quicky emerged.
But as it grew, themes became complicated to build. Plugins were ugly and difficult to
customize. And templates were clunky to use. I couldn't continue with the Wordpress
route.
Having been spoiled by component based systems, I decided to try Next.js.
I use React in my day job, so it's familiar ground, but I couldn't justify the
complexity for a website that didn't need dynamic content. Also, Next.js
had no CMS support.
That's when I decided to reach for hiccup, a Clojure library for generating
server side content. hiccup
let me use Clojure data structures to build my pages.
;; generating a span element with the class `foo` and content of `bar`
(html [:span.foo "bar"])
This short syntax let me express more with less code. I also had components.
;; defining an `h1` variable with the content `Welcome`
(def header [:h1 "Welcome"])
;; using `header` variable inside a `div` with an additional paragraph
(html [:div.content
header
[:p "more content"]])
I could define functions or plain variables, then use them as components in my templates.
On top of that, I didn't have to learn a special syntax for working with data. I had the full power of Clojure to interact with data and components themselves.
;; defining data for the menu
(def menu-items
["Crab Rangoon"
"Pot Stickers"
"Miso Soup"])
;; creating a function to generate a list elment from the provided `menu-item`
(defn create-menu-item [menu-item]
[:li.menu-item menu-item])
;; generating an unordered list by mapping over the `menu-items` data
(def menu
[:ul
(map create-menu-item menu-items)])
I could do all this with a concise syntax that is simpler than Wordpress templates, and shorter than React components.
The final benefit is the ease of mind provided by Clojure. I know that no matter what features we dream up, they will be possible with this general purpose language.