duct

adamfrey 2025-09-28T03:09:42.184609Z

I just wanted to say thank you James for your recent work on Duct. 🙏 I have never used it before today, but by reading the http://duct-framework.org docs I was able to convert a hiccup-based static site over to duct in just one day. A couple more details in the thread.

adamfrey 2025-09-28T03:18:52.588909Z

because I'm generating static content I leaned into pre-generating my hiccup components into the config:

;; elements.edn

{:navbar    #ig/ref :mysite.hiccup/navbar
 :footer    #ig/ref :mysite.hiccup/footer
 :head-tags
 [[:link {:type "text/css" :href "/css/reset.css" :rel "stylesheet"}]
  [:meta {:charset "UTF-8"}]
  [:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}]]}
;; routes.edn
[["/" {:get :mysite.routes/home}]
 ["/about-us" {:get :mysites.routes/about-us
               :title "About Us"}]
 ...
 ]
;; duct.edn
{
  ...

  ;; my navbar component wants the canonical list of routes passed to it
  :mysite.hiccup/navbar
  {:routes #duct/include "routes.edn"}

  :mysite.hiccup/footer
  {}

  :mysite.hiccup/home-page
  {:elements #duct/include "elements.edn"}

  :mysite.routes/home
  {:page-hiccup #ig/ref :mysite.hiccup/home-page}
;; mysite/routes.clj

(defmethod ig/init-key ::page-handler [_ {:keys [page-hiccup]}]
  (constantly page-hiccup))

(derive :mysite.routes/home     ::page-handler)
(derive :mysite.routes/about-us ::page-handler)
I thought I'd mention it because a static site is probably not the main use case for duct, but it worked great for me following this little pattern. It's cool to see all of my generated pages re-built from scratch on calling (user/go)

weavejester 2025-09-28T15:52:11.303039Z

Glad it worked out for you! Out of interest, what made you consider using Duct for a static site?

adamfrey 2025-09-28T16:14:07.533989Z

It’s an infrequently updated site, so I kind of hate coming back to it six months later and having to grep around the code base for the small number of inputs that need to change. I believe in the Arachne , Zen-lang, and seemingly Duct philosophy that many of the important parts of our app can live in static EDN files.

adamfrey 2025-09-28T16:15:17.041959Z

And even though I’ve done it before I don’t get joy from wiring up all of the HTTP handler router middleware refresh stuff myself

weavejester 2025-09-28T16:16:53.885169Z

Thanks for explaining. I hadn't considered that as a use-case, but I can see why Duct might be useful in that case.