How to serve html files with Ring/Compojure, without Leiningen?

Hi, what is a usual way to serve html files with Ring and Compojure?

I have been working on this for a couple of evenings without success so some advice would be great. I’m one week into learning Clojure, about halfway through the book Living Clojure. As an exercise I’m doing some parts of the book differently, including using the Clojure CLI tools instead of Leiningen.

In a basic web project, normal Compojure routes work, but I can’t serve html files – I always hit the routes/not-found Compojure route.

If I start a cljs repl and server with Clojure CLI, I can browse to the html file.

From what I’ve read there are a few ways to serve html in this scenario:

I’ve tried all these with no luck, but it’s very possible I’ve mixed up things along the way. So far I’ve tried putting my html file in the project root, in ./resources/public, in ./public, and in ./resources.

For reference here is my main .clj file.

Thanks in advance for any clarity!

I made some progress, though it doesn’t exactly answer the original question.

Looking at this useful demo,, they put the resources directory in :paths of the deps.edn, and that fixed my issue.

Looking at cljs it seems like their web server is different than the Jetty server that Ring uses, so that explains the difference there.

I think Lein by default adds the resources dir via :resources-paths, so this is why I have to add it manually.


Using the defaults via wrap-defaults and site-defaults, the correct location for serving static files should be $project-root/resources/public. The fact that you are using these defaults means that your setup looks to be correct.

The only other thing is to ensure your resources directory is on your classpath, which adding it to :paths in your deps.edn should do.

To check what is included in your classpath, go to the root directory of your project and run:

clj -Spath | sed 's/:/\n/g'

clj -Spath will return the classpath as a :-separated string, the sed portion will format it nicely. You can also pipe the above through grep resources and that will tell you whether your resources directory is on the classpath or not.

By this I assume you mean that the web server included with I’m guessing figwheel is different from Jetty? Strange, as I always thought that figwheel uses a ring server, which by default uses Jetty.

1 Like

I think you’re right, by cljs I meant core Clojurescript – if you start it with something like clj -M -m cljs.main, that seems to use a non-jetty webserver, or at least non-Ring.

I’ve never actually launched a web server that way, so you are probably correct that it is a non-Ring/Jetty web server, which might explain the issues you were facing.

Once you’re up to it, I would recommend trying either figwheel or shadow-cljs. I’ve been using figwheel-main for years now and once you learn how to set it up, it just works without you having to play around it with much subsequently.

1 Like