I had this very same issue. I figure I'll solve it a different way with every noir app I write, because, you know, why not? If every problem you solve looks the same, you might as well have fun trying different hammers.
I'll probably over explain my dorky solution, but what the hell, eh?
After digging around in the source I discovered (or misunderstood) that "include-js" can take a list of strings as well as a single string so it seemed like a good idea to have a function that takes a list of the default script and (optionally) appends the one customized for just that particular page.
List of defaults:
(def ^:private default-scripts
"/myapp/js/common.js"])
Custom script per page:
(def ^:private custom-scripts
{:user "/myapp/js/user.js"
:login "/myapp/js/login.js"
:reports "/myapp/js/reports.js"})
Then an optional conj:
(defn- javascripts
[page]
(if-let [custom (page custom-scripts)]
(conj default-scripts custom)
default-scripts)))
and in the actual layout code:
(defpartial layout-page [title page & content]
(html5
[:head
[:title title]
(apply include-js (javascripts page))
(apply include-css styles)]
(layout-body page content)))
or some such thing. Works for navigation links (highlighting the one you're on) and CSS, too, I imagine. I might have misread the source code of include-js: but apply seemed to do the trick and once it did, I moved on to something else without further exploration. After the above, I figured I could unify all these maps and lists into a simple page description kind of structure that made all the unique bits of the pages declarative, but thought I'd resist the temptation.
Keith