ClojureScript 1.10.X - New Quick Start, Feedback please :)



The next major release of ClojureScript is looming - it’s pretty massive :slight_smile: But probably the thing we’re most looking forward to is how much easier it is to use!

We’re rewriting the Quick Start from the ground up to highlight this:

Please give it a try! We cut a pre-release (1.10.126) just for it. The Quick Start is how new users will build their first impressions so we’re very interested in making this as compelling as possible.

Looking forward to hearing your thoughts.


@dnolen this a great!

Typo spotted:

Your default web browser will open to a page that looks like the following:

the image is missing.


Yeah there’s actually a few images I have in mind, but those will come later. At the moment I’m most interested in feedback about the overall impression of the guide.


@dnolen Ah right sorry.

Here’s some feedback regarding the content (keep in mind that I’m not a ClojureScript beginner, and that I don’t know precisely what the intended audience and goals of the guide are):

I notice that the overall setup is hugely reduced compared to previous versions, which is a very good thing as it should make ClojureScript much more accessible to beginners. In a similar vein, I also really appreciate that you can get both a REPL and a browser in the very first steps.

I would add an introduction sentence stating the scope of the guide, maybe something like: “In this tutorial, we will guide you through a basic setup for running ClojureScript programs interactively on your machine”. (Or maybe something else, maybe I got the scope wrong).

I would add a short introduction to the ‘ClojureScript compiler’ section, and maybe find another title - as it is, it is a bit hard to know where we’re getting at. Maybe something like: “in this section, we will see how to run a ClojureScript program in a web page and interact with it at the REPL.”

I would maybe also strive to reduce the amount of technological prerequisites: currently, the guide seems to assume that the reader knows about terminal windows, JavaScript, compilers, NodeJs, and most importantly, implicit knowledge about what ClojureScript does. This is not a new issue of course, but now that the setup is so massively simplified, addressing it seems within reach: maybe a few additions here and there to explain what’s going on in a more vulgarised form?

And again, congratulations and THANK YOU for this new release: the fact that I consider the above issues the most important ones is a telling sign of progress.


General comments: I would use the long options in the command clj -m cljs.main -c hello-world.core -r (--main instead of -m, etc.) because they aren’t as mysterious. The paragraph that explains the long commands then becomes “if you don’t like to type, here are the short forms of the options”

Instead of creating a function named foo that duplicates an operation already built in to the language, create a function with a more meaningful name average that is nominally useful but not overly complex:

(defn average [a b]
  (/ (+ a b) 2.0))

I wasn’t able to go further, as after the reload, I got an error with foo:

TypeError: is undefined

and evaluation of (ffirst [1]) did not give me a stack trace, but a simple error: Error: 1 is not ISeqable


That’s all great feedback and I’ll definitely incorporate this into the next version.


Followed the steps exactly (on 1.9) After defining foo and reloading ((require '[hello-world.core :as hello] :reload)), the call to it failed:

cljs.user=> (hello/foo 2 3)
TypeError: Cannot read property 'call' of undefined

It worked after I shut down the repl and restarted it.



I had the same problem with the (ffirst [1])

Compiling client js ...
Serving HTTP on localhost port 9000
Listening for browser REPL connect ...
Hello world!
To quit, type: :cljs/quit
cljs.user=> (require '[hello-world.core :as hello] :reload)

cljs.user=> (hello/foo 2 3)
cljs.user=> (inc 1)
cljs.user=> (ffirst [1])
Error: 1 is not ISeqable

I tried entering that in the repl first, not sure I was supposed to do that. I
also tried to add it to my hello-world/core.cljs file but with no luck:

(ns hello-world.core)

(println "Hello world!")

(defn foo [a b]
  (+ a b))

(ffirst [1])


cljs.user=> (require '[hello-world.core :as hello] :reload) Broken pipe (Write failed)
  at Method)

I also tried to add it to my foo function and had the same error as the repl:

(ns hello-world.core)

(println "Hello world!")

(defn foo [a b]
  (ffirst [1])
  (+ a b))
Serving HTTP on localhost port 9000
Listening for browser REPL connect ...

To quit, type: :cljs/quit
cljs.user=> (require '[hello-world.core :as hello] :reload)

cljs.user=> (hello/foo 3 2)
Error: 1 is not ISeqable

I went through the rest of the tutorial and everything else worked. Overall, this Quick Start is a lot better and simpler than the last one. Well done!


When starting the guide, I’m eager to get to the CLJS goodness. But first, I have to go through a bunch of tedious folder setup — one step at a time, with intermingled instructions for POSIX folks and Win folks.

If I were writing this guide, I’d replace most of the opening section with something like the following:

First, set up a project folder for our Hello World project. Here’s a list of the files and folders you’ll need. Note that the underscores in the names are important.

hello_world        # Our project folder
├─ src             # The CLJS source code for our project
│  └─ hello_world  # Our hello_world namespace folder
│     └─ core.cljs # Our main file
├─ cljs.jar        # (Windows only) The standalone Jar you downloaded earlier
└─ deps.edn        # (Mac/Linux only) A file for listing our dependencies

Mac/Linux users, place the following in deps.edn:

{:deps {org.clojure/clojurescript {:mvn/version "1.10.126"}}}

This change will also partly address @vvvvalvalval’s concern about “technological prerequisites” by cutting down on the amount of terminal futzing right off the start. Folks who want to live in the terminal will know how to make folders. Folks who are comfortable copy-pasting commands, but might be intimidated by…

md src\hello_world & type nul >>core.cljs & move core.cljs src\hello_world

…can comfortably get started in the Finder/Explorer.

Thanks for all your hard work on this, David!


Great suggestion. Need to see if I can do that in AsciiDoc.


I’ve updated the guide to reflect these specific suggestions.


With the Windows instructions, I get Unrecognized option: -m. Instead, java -cp "cljs.jar;src" cljs.main -c hello-world.core -r works.

When running that command for the first time without an existing “out” directory, the browser opens but “Hello World” doesn’t actually show up.

  • Loading failed for the <script> with source “http://localhost:9000/out/cljs/pprint.js”.
  • I think the browser starts before it’s finished writing all the files?
  • The REPL does fully work, including println.
  • If I refresh the browser, the message does show up.

I’m getting an error with Windows paths on any optimisation level other than ‘none’.

  • I’ve been able to use optimisations with shadow-cljs in the past - I don’t know the exact differences here.
> java -cp "cljs.jar;src" cljs.main -O advanced -c hello-world.core
Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index 2: /C:/Users/Jack/SSD/Projects/oops/out/cljs/core.js
            at sun.nio.fs.WindowsPathParser.normalize(

Can you use Maven dependencies with cljs.jar?

  • Writing deps.edn and then running the previous commands didn’t work. Does this have to wait until the CLI is on Windows?
  • The link to dependencies.adoc is broken.

Going slightly off script, I instead tried to refer to React as a Node module. ((:require [react] [react-dom])), (.render react-dom ...) The paths in main.js changed from out/goog/base.js to a badly escaped absolute Windows path:

Loading failed for the <script> with source “c:UsersJackAppDataLocalTempout592734404660296829634939245609027/goog/base.js”.

Other than this friction on Windows, it’s a good introduction to the new tooling. Is the intended workflow for most CLJS projects in future to use these commands, then to move on to a clj-based build script?


This is great, incorporating.


The latest version uses only the long form the first time a command is introduced. I agree it’s much clearer this way.


Fixed this in the latest version.


The version I’m reading incorporates all the fixes from this thread and is really great ! Awesome job @dnolen.

Here a few mistakes:

We can create a release build by setting the appropriate value for the --optimizations flag. The default optimization level is none, but this time we want to use all the optimizations provided by both ClojureScript and Google Closure Compiler - this can be done by specifying advanced. Other valid options for -O are whitespace and simple but these are less commonly used:

clj -m cljs.main --optimizations advanced -c hello-world.core

The last sentence mentions -O whereas it’s not used before. I would just use the long version since it’s what’s used in the code below. Less confusing.

We’re also using -o here for specifying the --output-to file:

clj -m cljs.main --target node --output-to main.js -c hello-world.core

No you’re not using -o but --output-to. Same mistake than above, I suggest the same fix.

Note that I haven’t tried the guide, only read it.


I fixed these cases as well. Thanks!


If you are using OS X or Linux the only dependencies required for the main part of this tutorial are a web browser and an installation of Clojure. On Windows you will need Java 8 and the standalone ClojureScript JAR.

I think we lose JS devs right about here. Sadly it’s the first paragraph!

How do they get Clojure? How do they get Java? Can we provide an install script for those?


Is there any chance that the windows issues will be fixed, such that the instructions line up for all three platforms? If so, is there any any utility in splitting the windows instructions off into a separate doc, so both docs are more consolidated and there’s less context switching between platforms? Then, when the windows issues are fixed, that separate doc and references to it could just be deleted. If that sounds useful I could take a crack at splitting out the content into separate docs.


I link to the install pages for Clojure. It’s one command on OS X and Linux.

Absolutely. Alex Miller will get to it when he has time and we will update the Quick Start so we have the same instructions across different platforms.