Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.


Lisp/Hiccup style templating for Facebook’s React in ClojureScript.


Ŝablono doesn’t declare a dependency on React anymore. Use the React dependencies from one of the ClojureScript wrappers or provide the dependencies yourself like this:

[cljsjs/react "16.6.0-0"]
[cljsjs/react-dom "16.6.0-0"]

If you want to do server rendering and use the render or render-static functions from the sablono.server namespace you need to add the following dependency as well:

[cljsjs/react-dom-server "16.6.0-0"]


Most functions from Hiccup are provided in the sablono.core namespace. The library can be used with Om like this:

(ns example
  (:require [om.core :as om :include-macros true]
            [sablono.core :as html :refer-macros [html]]))

(defn widget [data]
   (html [:div "Hello world!"
          [:ul (for [n (range 1 10)]
                 [:li {:key n} n])]
          (html/submit-button "React!")])))

(om/root widget {} {:target (. js/document (getElementById "my-app"))})

By default, Ŝablono will wrap any forms in the body of hiccup with a call to sablono.interpreter/interpret. If your code returns a React element, then you can skip the call to this function by marking the s-expression with the metadata tag :inline. For example:

[:div {}
 ^:inline (function-that-returns-react-component)]


Ŝablono only supports tags and attributes that can be handled by React. This means you can’t have your own custom tags and attributes at the moment. For more details take a look at the Tags and Attributes section in the React documentation.

HTML Attributes

HTML attributes in React are camel-cased and the class and for attributes are treated special. Ŝablono renames attributes with dashes in their name to the camel-cased version and handles the class and for special case. This is more consistent with Hiccup and naming conventions used in Clojure.

An input element with event listeners attached to it would look like this in Ŝablono:

(html [:input
       {:auto-complete "off"
        :class "autocomplete"
        :on-change #(on-change %1)
        :on-key-down #(on-key-down %1)
        :type "text"}])

Setting innerHTML of a DOM node

It is not recommended to directly set the innerHTML of DOM nodes, but in some cases it is necessary. i.e. injecting a HTML string that was generated from Markdown.

(html [:div {:dangerouslySetInnerHTML {:__html "<div>hello world</div>" }}])

You can read more at React’s special attributes.


Benchmark results can be found here.


How to run the tests?

You need to have Node.js and PhantomJS installed for the ClojureScript test.

Make sure you have all dependencies installed. The following command installs the Maven and Node.js dependencies.

lein deps

To run all Clojure and ClojureScript tests run the following command:

lein ci

For development the ClojureScript tests can be run with lein-doo. To run the tests on Node.js run the following command:

lein doo node nodejs auto

To run the tests on PhantomJS use this command:

lein doo phantom none auto

Why is there a compiler and an interpreter?

The interpreter is executed at run time, and it’s job is to evaluate Hiccup forms and produce React elements. The compiler on the other hand, is executed at compile time and can optimize certain Hiccup forms. It’s job is to evaluate Hiccup forms and produce executable code.

A good introduction to this topic can be found in Peter Seibel’s Practical Common Lisp:


This library is based on James Reeves excellent Hiccup library. The server side rendering code has been taken from


Copyright © 2013-2020 r0man

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.


Lisp/Hiccup style templating for Facebook's React in ClojureScript.




Sponsor this project



No packages published
You can’t perform that action at this time.