Tech behind Tech

Raw information. No finesse :)

Compojure Demystified with an example – Part 3

with 19 comments

In part2 we saw how to setup a skeleton project with Compojure. In this part we will see how to add static files to a Compojure project.

For our application, we will use JQuery as front end and Clojure as a backend. I will concentrate more on Compojure.

1) Create folders for static files.

mkdir public
mkdir public/css
mkdir public/js

It is better to have static files under a seperate directory that way you could use your webserver to serve these files. For now we will use Compojure to serve these files.

2) Create index.html under public folder

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xmlns="" xml:lang="en">
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>My Address book</title>
		<script type="text/javascript" src=""></script>

  <body id="main">
      My Address Book

3) Start your server

lein repl src/address_book/core.clj

4) Access index.html

Go to http://localhost:8080/index.html . You will get “Page not found” instead of “My Address Book”. This is happening because we have not told compojure about our static files folder.

Route helper functions in Compojure

In Compojure we have two route helper functions. We have seen one already in core.clj file.

1) not-found :

This function is used to capture all other routes that are not defined in Compojure. As we still have not defined index.html we got “Page not found”.

2) files :

This function is used to inform Compojure where static files are present.

Lets change our core.clj to handle static files

(ns address_book.core
  (:use [compojure.core]
  (:require [compojure.route :as route]))

(defroutes example
  (GET "/" [] "<h1>My Address Book!</h1>")
  (route/files "/" {:root "public"})
  (route/not-found "Page not found"))

(run-jetty example {:port 8080})

Restart your server (there is a way to avoid restarting using futures. I will show that in a later blog) and access http://localhost:8080/index.html . Now you should see “My Address Book”.

In this part we saw how we can handle static files. In next part we will implement Add , View and View All functionalities.

PS: Using Hiccup you can create HTML and css in clojure. I will try to cover this in future blogs.

Source code is now available at github . Created branches for each part.

Checkout PART4

Written by Siva Jagadeesan

August 16, 2010 at 9:04 pm

Posted in Clojure

Tagged with , ,

19 Responses

Subscribe to comments with RSS.

  1. Yes, very good tutorial, and I am translate it to chinese at, link:, Would not you mind it?
    Waiting the next…



    August 20, 2010 at 12:15 am

  2. Sorry, The actual link is


    August 20, 2010 at 12:17 am

    • That is great … please go ahead … I am working on next part ( it is kind of big one) so should be out in 1 or 2 days

      Siva Jagadeesan

      August 20, 2010 at 12:19 am

  3. More compact way of creating multiple directories

    mkdir -p public/{css,js}

    .. and you might as well update to clojure 1.2

    looking forward to the next part :-)


    August 20, 2010 at 12:54 am

  4. Hi Siva

    Great introduction to compojure, thanks a lot! I can’t wait for your next posts.

    — Ben


    August 21, 2010 at 6:46 am

    • Thanks Ben.

      The next part should be out by this weekend.

      — Siva Jagadeesan

      Siva Jagadeesan

      August 21, 2010 at 8:40 am

    • Hi Siva

      Just a very quick note: I’ve been looking with a lot of interest to the Clojure HTML templating system called Enlive. It looks amazingly flexible. There a good introduction here:

      Hope this could help and inspire!

      — Ben


      August 24, 2010 at 12:47 am

      • I plan to refactor Siva’s next part to use enlive. The changes will be available on github. Let’s get a bit of social coding going here :-)

        Clojure, compojure, ring, enlive, hiccup .. everything is moving fast and many of the tutorials currently available simply woun’t work with the newest versions of the different libraries.


        August 24, 2010 at 1:17 am

      • Yah Klang. They are moving fast.

        Yah go ahead and refactor my code to use enlive. I would like to contribute too.

        Siva Jagadeesan

        August 24, 2010 at 8:56 am

  5. Hi klang, lovely, I would love to see that I must say I’m fairly excited with compojure and enlive too.

    Please let us know about your work klang.

    Siva, I hope you don’t mind I’ve translated your tutorial in French. The (temp) address is:

    You’re fully credited of course. Actually I’ve a few questions for you Siva while translating your posts and that’s the topic of my first section: “TODO Questions”. The two main points being:

    1. why do you have an address entry on the same level of the rest of the stuff? I guess what you meant was: an address is defined by: name, street1, street2, etc.

    2. I would suggest to switch to Clojure 1.2 as the new release is now out. What would you say about that? do the dependencies work correctly?

    Kind regards,

    — Ben


    August 24, 2010 at 2:47 am

    • Hi Ben:

      Go ahead … the more people this tutorial reaches the better it is.

      Address being in same level as other fields is a formatting issue. Thanks for pointing out I will fix it.

      Siva Jagadeesan

      August 24, 2010 at 8:58 am

  6. oops my bad, your source already contains:
    :dependencies [[org.clojure/clojure “1.2.0”]
    Thanks Siva!


    August 24, 2010 at 3:11 am

    • No problem.

      I am working on next part. It is taking more time than I expected. Sorry for the wait

      Siva Jagadeesan

      August 24, 2010 at 8:58 am

  7. Hey since you’ve now posted part 4, you should add a link to it here on part 3! Thanks for writing this!


    August 27, 2010 at 2:26 am

  8. please indicate where to create the “public” subfolder: in the project folder, at the same level as the “src” and “lib”


    September 20, 2010 at 3:21 am

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.

Join 147 other followers

%d bloggers like this: