Hiccup Makes Writing HTML Fun
=============================

March 21, 2021
https://stefan.vanburen.xyz/blog/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 <abbr title="HyperText Markup Language">HTML</abbr> with [Tailwind](https://tailwindcss.com) for styling and [AlpineJS](https://github.com/alpinejs/alpine) 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](https://github.com/weavejester/hiccup) is a library for writing <abbr title="HyperText Markup Language">HTML</abbr> in Clojure.
Writing <abbr title="HyperText Markup Language">HTML</abbr> in Hiccup is a *dream*:

* Unlike <abbr title="HyperText Markup Language">HTML</abbr>, Hiccup automatically closes tags.
* Hiccup doesn't require that you remember the proper way to close an <abbr title="HyperText Markup Language">HTML</abbr> element.
* Hiccup has shortcuts for adding an `id` or `class` 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:

```clojure
[: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:

```clojure
(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 <abbr title="JavaScript XML">JSX</abbr> syntax while writing React — and this approach has been taken to the ClojureScript side via the [Reagent](https://github.com/reagent-project/reagent) library.
(A more thorough example of Reagent-style Hiccup code can be found in my [seven-guis](https://github.com/stefanvanburen/seven-guis/blob/main/src/app/main.cljs) project).

And, when you pair Hiccup with [Parinfer](http://shaunlebron.github.io/parinfer/) + [Conjure](https://github.com/Olical/conjure), the <abbr title="Developer Experience">DX</abbr> is too good to pass up.
While I love writing Go, the conciseness, simplicity and the <abbr title="Read-Eval-Print Loop">REPL</abbr> of Clojure have drawn me in.
It's magical.

🪄
