+Lots of folks have been interested in ClojureScript lately, but have had a hard time figuring out what a CLJS app actually looks like. So today I [recorded] myself building an [Overtone] controller (that I use on an iPad) using [noir], [fetch], [jayq], and [crate]. In the end, it looks like this:

+

+![overtone controller](/images/overtoneController.png)

+

+Since I don't narrate in the video, I figured I'd give a breakdown of some of the main ideas below. If you want all the gory details though, you can watch the [screencast][recorded] or look at the [code]. Now to the fun part.

+

+##Getting started

+

+The first step is to generate a new noir project using lein-noir (if you're new to noir, check out [noir's website][noir])

+

+{% highlight bash %}

+lein noir new overtoneinterface

+{% endhighlight %}

+

+Now to set up our project we just need to include our dependencies, which with the wonderful [lein-cljsbuild] means you do what you always do - add them to your project.clj. ClojureScript dependencies don't really work any differently than Clojure ones do:

+

+{% highlight clojure %}

+(defproject overtoneinterface "0.1.0-SNAPSHOT"

+ :description "FIXME: write this!"

+ :dependencies [[org.clojure/clojure "1.3.0"]

+ [overtone "0.6.0"]

+ [jayq "0.1.0-SNAPSHOT"]

+ [crate "0.1.0-SNAPSHOT"]

+ [fetch "0.1.0-SNAPSHOT"]

+ [noir "1.3.0-alpha10"]]

+ :cljsbuild {:source-path "src"

+ :compiler

+ {:output-dir "resources/public/cljs/"

+ :output-to "resources/public/cljs/bootstrap.js"

+ :optimizations :simple

+ :pretty-print true}}

+ :main overtoneinterface.server)

+{% endhighlight %}

+

+You see here that we also added a cljsbuild key that defines some properties for how we want out ClojureScript to be generated. They simply tell lein-cljsbuild where to find our source and where to place the output. To then get that into our app, we just need to include the generated javascript file and jquery in our views.common/layout function.

+Then just modify welcome.clj to get rid of the getting-started content, change /welcome to /, and add a div#piano so we have a container to put our buttons in.

+

+{% highlight clojure %}

+(ns overtoneinterface.views.welcome

+ (:require [overtoneinterface.views.common :as common])

+ (:use [noir.core :only [defpage]]

+ [hiccup.core :only [html]]))

+

+(defpage "/" []

+ (common/layout

+ [:div#piano]))

+{% endhighlight %}

+

+I always end up creating a src/myapp/client/ directory where I keep my CLJS. So if you put the following in a main.cljs in there and fire up lein-cljsbuild, you'll see a nice little alert box:

+

+{% highlight clojure %}

+(ns overtoneinterface.client.main)

+

+(js/alert "hey!")

+{% endhighlight %}

+

+Now we're off to the races.

+

+##Using crate and jayq

+

+[crate] is a ClojureScript implementation of the HTML generation library [Hiccup], which represents html as Clojure vectors and maps. We use a special macro called `(defpartial ..)` to create a function that will create dom objects for us.

+One thing to note here is that there's a special directive for requiring macros in CLJS. Also, any namespace used by that macro must be required as well, or otherwise that code won't end up in the generated file. Now to do something with it, we'll use jayq.

+

+[jayq] is a simple ClojureScript jQuery wrapper that I wrote, which makes it easy to do all your standard dom manipulations like you're used to.

+It does, however, add some interesting bits. One of which, is that dom elements created with crate can be referenced by the function that was used to create them. This is actually immensely useful, because it basically gives you named controls for free. For example, we end up adding a click handler for all our buttons like so:

+

+{% highlight clojure %}

+(def $body ($ :body))

+

+(delegate $body button :click

+ (fn [e]

+ (.preventDefault e)

+ (js/alert "clicked!")))

+{% endhighlight %}

+

+Time to make that handler a bit more interesting. We're here to make music afterall.

+

+##Interacting with the server - fetch

+

+[fetch] is the next piece of the puzzle which helps us by removing the barrier between the server and the client. In this case, we're going to use remotes, which are functions defined on the server that are then called by the client. Normally, these would look something like this:

+

+{% highlight clojure %}

+(letrem [result (some-remote-func 2 3 4)]

+ (.log js/console result))

+{% endhighlight %}

+

+But since we want to call these dynamically based on whatever action our button is created with, we'll need to drop down one level and use `(fetch.remotes/remote-callback remote-func params)`. To do this however, we also need to be able to get a reference to the dom element that was clicked. In jQuery, you usually use `this`, but in ClojureScript "this" is a symbol just like anything else. For us to get at the js "this", we'll simply use the macro `(this-as some-symbol-meaning-this ... )`

+

+{% highlight clojure %}

+(ns overtoneinterface.client.main

+ (:require [crate.core :as crate]

+ [fetch.remotes :as remotes]) ;; add fetch.remotes

+ (:use [jayq.core :only [$ append delegate data]])

+ (:use-macros [crate.macros :only [defpartial]]))

+

+...

+

+(delegate $body button :click

+ (fn [e]

+ (.preventDefault e)

+ (this-as me

+ (let [$me ($ me)

+ action (data $me :action)

+ param (data $me :param)

+ params (if (= param "")

+ []

+ [param])]

+ (remotes/remote-callback action params)))))

+{% endhighlight %}

+

+What that does is extract the action and param attributes from our button and then tells fetch to call the remote function whose name is the value of action with the params we give it. On the Noir side, you then just needs to do two things - add the wrap-remotes middleware in server.clj (make sure you restart the server!):

+

+{% highlight clojure %}

+(ns overtoneinterface.server

+ (:require [noir.server :as server]

+ [noir.fetch.remotes :as remotes]))

+

+(server/load-views "src/overtoneinterface/views/")

+(server/add-middleware remotes/wrap-remotes)

+

+(defn -main [& m]

+ (let [mode (keyword (or (first m) :dev))

+ port (Integer. (get (System/getenv) "PORT" "8080"))]

+ (server/start port {:mode mode

+ :ns 'overtoneinterface})))

+{% endhighlight %}

+

+And define a remote in views/welcome.clj

+

+{% highlight clojure %}

+(ns overtoneinterface.views.welcome

+ (:require [overtoneinterface.views.common :as common]

+ [overtoneinterface.models.dubstep :as dubstep])

+ (:use [noir.core :only [defpage]]

+ [overtone.live]

+ [overtone.inst.sampled-piano]

+ [noir.fetch.remotes :only [defremote]]

+ [hiccup.core :only [html]]))

+

+(defpage "/" []

+ (common/layout

+ [:div#controls]

+ [:div#wobble]

+ [:div#notes]

+ [:div#piano]))

+

+(defremote play-note [n]

+ (sampled-piano n))

+

+;;play-note is also just a regular function, meaning you could use

+;;it in your clj code like normal..

+;;(play-note 60)

+{% endhighlight %}

+

+If this is the first time your server has loaded overtone.live, it may take a few seconds for it to refresh as it has to startup supercollider and a few other things. Also, if this is your first time ever using the sampled piano, it has to download a pretty large set of samples (this can take an hour). Assuming you have both of those though, clicking the button will cause a tone to be played. In the video, this happens at [11:20](http://www.youtube.com/watch?v=lcRQFGtFiyE&feature=youtu.be&hd=1#t=11m20s).

+

+##Adding a bit more.

+

+At this point the fundamentals of the app are there, the rest is just icing on the cake. I clean up the code so that it's easy to add a bunch of buttons to a container and create more piano keys for us to click:

+

+{% highlight clojure %}

+(def piano-notes (for [note (range 40 60)]

+ {:label (str note) :action "play-note" :param note}))

+

+(defn populate [container buttons]

+ (doseq [b buttons]

+ (append container (button b))))

+

+(populate $piano piano-notes)

+{% endhighlight %}

+

+Then I grab the code from the dubstep example in the [Overtone] repository and drop it in, create a couple more remote functions and we then have the ability to fully control our little dubstep machine. The final welcome.clj looks like this:

+My first experiences with ClojureScript culminated in [Pinot] a library the provided the basic building blocks for creating websites in CLJS. It was, however, a monolithic conglomeration of all the random things I built along the way. To cure this, I broke Pinot apart into the following libraries:

+

+#[jayq]

+

+Pronounced "jake" is a jquery wrapper that makes jquery objects work just like normal clojure collections.

+

+{% highlight clojure %}

+(ns myapp

+ (:use [jayq.core :only [$ css inner]]))

+

+(def $interface ($ :#interface))

+

+(-> $interface

+ (css {:background "blue"})

+ (inner "Loading!"))

+{% endhighlight %}

+

+#[waltz]

+

+A state management library that lets you build very complex interactions without ending up in the tar pit.

+

+{% highlight clojure %}

+(def me (state/machine "cool")

+

+(defstate me :loading

+ (in [] (show $loading))

+ (out [] (hide $loading)))

+

+(defstate me :normal

+ (in [v]

+ (inner $value v)

+ (wait delay #(transition me :update))))

+

+(deftrans me :update []

+ (state/set me :loading)

+ (store/latest [:metrics (:metric params)]

+ #(transition me :set %)))

+

+(deftrans me :set [v]

+ (state/unset me :loading)

+ (state/set me :normal v))

+

+(transition me :update)

+{% endhighlight %}

+

+#[fetch]

+

+A library to make client/server interaction painless. Includes the pinot.remotes stuff as well as the start of a lazy-store implementation that works like a map where the values are fetched from the server lazily.

<a href="http://iwbyp.chris-granger.com">iwbyp</a> is a service where I build a web prototype of your idea in two weeks using Clojure. If you have wireframes and an idea, I can build it for you at fixed cost.

+[Korma] is a domain specific language for Clojure that takes the pain out of working with your favorite RDBMS. Here's a basic example:

+

+{% highlight clojure %}

+(defdb prod (postgres {:db "korma"

+ :username "db"

+ :password "dbpass"}))

+

+(defentity address)

+(defentity user

+ (has-many address))

+

+(select user

+ (with address)

+ (fields :firstName :lastName :address.state)

+ (where {:email "korma@sqlkorma.com"}))

+{% endhighlight %}

+

+Korma bring composability and reuse to SQL by turning queries into maps that can be built up over time. This make it much more expressive than SQL is naturally and gives you the full power of Clojure to construct queries in interesting ways.

+[Noir](http://webnoir.org) is a micro-framework that allows you to rapidly develop websites in Clojure. It looks like this:

+{% highlight clojure %}

+(ns my-app

+ (:use noir.core)

+ (:require [noir.server :as server]))

+

+(defpage "/welcome" []

+ "Welcome to Noir!")

+

+(server/start 8080)

+{% endhighlight %}

+

+By default, it uses an HTML generation library called Hiccup, which represents tags as clojure vectors. This allows you to compose your views in very interesting and powerful ways using the functions you know and love from Clojure:

- <dd>After about two years, I left Microsoft to start a company with my good friend <a href="http://nathanhammond.com">Nathan Hammond</a>. Nathan and I have known each other since high school, we both worked at Skookum and MODE together, and have always wanted to strike out on our own. Currently, we're working on several ideas, the first of which, a <a href="http://www.typewire.io">live-blogging service</a>, is now in beta. It's been an insane <a href="http://radian.org/notebook/wp-content/uploads/2008/04/20080404-img_2281.jpg">roller coaster ride</a> so far, but it's undoubtedly one of the best learning experiences I could ever have.</dd>

- <!--

- <dt>

- <span>Along the way, I learned.</span>

- 1987-Current

- </dt>

- <dd>

- Throughout all of this, I've developed a <a href="http://www.amazon.com/Linchpin-Are-Indispensable-Seth-Godin/dp/1591843162" target="_blank">unique skillset</a>. My eclectic background and general passion for solving problems and learning new things means I approach situations from angles most people haven't even dreamed of yet. I admit, I'm different (how many German majors do you know at Microsoft?), but I promise it's for the best.

- </dd>

- -->

+ <dd>After about two years, I left Microsoft to start a company with my good friend <a href="http://nathanhammond.com">Nathan Hammond</a>. Nathan and I have known each other since high school, we both worked at Skookum and MODE together, and had always wanted to strike out on our own. Together, we built a <a href="http://www.typewire.io">live-blogging service</a> called Typewire. It was an insane <a href="http://radian.org/notebook/wp-content/uploads/2008/04/20080404-img_2281.jpg">roller coaster ride</a> and undoubtedly one of the best learning experiences I've had, but in the end, it didn't work out. So thereafter, I joined up with the guys at <a href="https://www.readyforzero.com">ReadyForZero</a> to help combat the growing debt epidemic. As their first engineering hire, I've helped rewrite an old Django site into a new one built entirely on <a href="http://webnoir.org">Noir</a> and <a href="http://clojure.org">Clojure</a>.</dd>