Tercio de Melo

New website!

New website is coming along!!

We now even have multiple paragraphs...

No JavaScript

This website is made without any javascript.

Though the website itself is HTML and CSS only, it is generated from clojure code. I have previously used Hugo to generate static website, but it is too cumbersome. I wanted something simple, but with powerful features such as hot reloading and custom logic for building the pages.

Clojure for the rescue

Of course a Lisp would be the best tool for the job, code and data is the same, for being a homoiconic language; and Clojure is currently my flavor of Lisp.

Below is a snippet of the clojure code that for now generates this index.html file:

src/main.clj
(ns main
  (:gen-class)
  (:use [hiccup.core])
  (:require [clojure.java.io :as io]
            [clojure.core.async :refer [go]]
            [juxt.dirwatch :refer [watch-dir]]
            [clojure.string :as string]
            [dev.server]
            [components.components :as components]))

(defn head [should-refresh]
  [:head
   [:link {:rel "stylesheet" :href (str "index.css?" (if should-refresh (rand 1000)))}]
   [:title "Tercio de Melo"]
   [:meta {:http-equiv "Content-Type" :content "text/html;charset=utf8"}]
   (if should-refresh
     [:meta {:http-equiv "refresh"  :content "2"}])])

(defn body [page]
  (let [module  (symbol (str "pages." (string/replace page "_" "-")))
        content (symbol (str module "/content"))]
    (require module)
    [:body
     (components/header page)
     ((resolve content))]))

(defn pages [base-dir]
  (let [directory (io/file (str base-dir "/src/pages"))]
    (->> (.list directory)
         (filter #(string/ends-with? % ".clj"))
         (map #(string/replace % #"\.clj$" ""))
         vec)))

(defn -main [& args]
  (doseq [page (pages (System/getProperty "user.dir"))]
    (let [output-file (str "tercio.com.br/" page ".html")
          sysargs     (set args)
          is-dev-env  (contains? sysargs "--environment=dev")]
      (println "Generating " output-file)
      (with-open [wtr (io/writer output-file)]
        (.write wtr (html {:mode :html} [:html (head is-dev-env)
                                         [:body (body page)]]))))))

(defn watch-in-cider []
  (let [class-path (System/getProperty "java.class.path")]
    (if (.contains class-path "/cider-nrepl/")
      (do
        (println "Starting dev server on port 8000")
        (go (dev.server/start 8000))

        (println "Watching page changes")
        (watch-dir
         (fn [& _] (-main "--environment=dev"))
         (io/file "src/pages")
         (io/file "src/components")
         (io/file "src/posts"))))))

(comment (watch-in-cider))
(comment (-main))
(comment (-main "--environment=dev"))
(comment (dev.server/start 8000))

The <meta ...> tag triggers refresh every too second. And every time I save a file, say src/pages/index.clj, in Emacs then CIDER automatically creates a new index.html. Notice that I'm using juxt.dirwatch to watch page changes locally. This watch is executed only when CIDER is in the class path, which doesn't happen when we run it with a lein run, for example.

Who already had some contact with ClojureScript might have noticed that I leverage Hiccup to generate HTML from Clojure data structures. It is a really fun and powerful tool.

If you are interested in seing the details, you will find the code in GitHub. This website is hosted in GitHub Pages.