Hiccup Makes Writing HTML Fun
At $work, I’ve been writing a web application that is server-side rendered via Go’s html/template
package.
I’ve been writing a toy application in Clojure with a similar approach: server rendered HTML with Tailwind for styling and AlpineJS for a hint of interactivity.
With the introduction of Go’s new embed
package in 1.16, I was tempted to port the application to Go.
I was imagining being able to embed the templates and assets in a static binary.
And I could still do that! But I hesitated as soon as I reached the portion of rewriting my templates in Go, and for good reason: Go’s template syntax isn’t great, and Clojure has Hiccup.
Hiccup #
Hiccup is a library for writing HTML in Clojure. Writing HTML in Hiccup is a dream:
- Unlike HTML, Hiccup automatically closes tags.
- Hiccup doesn’t require that you remember the proper way to close an HTML element.
- Hiccup has shortcuts for adding an
id
orclass
attributes.
And, more than anything, Hiccup is written within your regular Clojure functions, which makes it incredibly easy to interweave logic with your templates.
A <form>
in Hiccup might look like this:
[:form {:action "/add-address"
:method "POST"}
[:label {:for "label-input"} "Label"]
[:input {:type "text"
:id "label-input"
:name "label"
;; for now, label is required
:required true}]
[:label {:for "street-input"} "Street"]
[:input {:type "text"
:id "street-input"
:name "street"}]
[:label {:for "city-input"} "City"]
[:input {:type "text"
:id "city-input"
:name "city"}]
[:label {:for "state-input"} "State"]
[:input {:type "text"
:id "state-input"
:name "state"}]]
;; …
The beauty begins when you start to weave in the logic:
(def disabled-classes "text-gray-500 …")
(defn button
[id classes disabled?]
[:button {:id id
:class (if disabled?
(merge classes disabled-classes)
classes)
:disabled disabled?}])
In this way, Hiccup is similar to the JSX syntax while writing React — and this approach has been taken to the ClojureScript side via the Reagent library. (A more thorough example of Reagent-style Hiccup code can be found in my seven-guis project).
And, when you pair Hiccup with Parinfer + Conjure, the DX is too good to pass up. While I love writing Go, the conciseness, simplicity and the REPL of Clojure have drawn me in. It’s magical.
🪄