This video is available to students only

Project structure

Enough talking, let's create a new repository and set up a project from scratch, using Shadow CLJS.

In the last few lessons, we learned about the language and build tools. We are now ready to create our first project.

You might find typing out S-Expressions odd at first. But don't worry, we'll soon learn how to use Paredit, a tool to help manage S-Expressions.

Shadow CLJS Project#

All projects start with a configuration file. The name and syntax of the file are different for different build tools. The ideas however remain the same. If you understand one build tool, you can easily use all others.

For Shadow CLJS (or Shadow), this file is called shadow-cljs.edn. edn stands for extensible data notation. It's a format similar to JSON.

Shadow projects are a mix of npm and CLJS projects, so you'll also need a package.json file. This allows us to install NPM packages directly.

There are multiple tools to scaffold your projects for you, but to gain insight into how things work, we'll set up the Shadow project manually. Getting used to Shadow configuration will help us later when we start using advanced features like code-splitting. After we walk through setting up projects manually, we'll learn about the tools that can automate this process.

Create an empty directory#

This directory will hold our project. In our case, the name is going to be First Project. Let's create the directory using a terminal:

The name of the topmost directory is conventionally "kebab-cased". Most Clojure libraries hosted on Clojars follow this convention.

Create the shadow-cljs.edn file#

Open this file in the editor of your choice. This is what your configuration should look like:

Don't worry if this doesn't make sense. We'll walk over each key-value pair in detail. You should however notice the use of keywords, maps, and vectors.

Source paths#

Source paths specify the directories your source code lives in. In our example, we have added two directories: src and resources.

The src folder is for ClojureScript code whereas the resources folder holds supporting assets, like configuration files, images, stylesheets, etc. These names could be anything, however, having an src folder is a very strong convention.

The directory named resources is used by Java's IO module, and by extension, also by Clojure's IO module. It's highly recommended to use conventional names.

Some large projects might have code in multiple dialects of Clojure. One popular combination is ClojureScript on the frontend and Clojure on the backend. In cases where multiple dialects exist simultaneously, the src path could be set to src/cljs and src/clj. Again this is just a convention. If you follow the convention, your Clojure code goes to src/clj folder and your ClojureScript code goes to src/cljs folder.

However, you can break the convention if you wish to. It's legal to define the source path as src/clj and put ClojureScript code inside that folder. The build tool will not complain as long as the path exists.

Since these folders don't exist yet, let's create them:

Once done, the first-project directory should look as follows:

Project dependencies#

This key-value pair is used to define the JVM dependencies of the project.

You might be wondering why Shadow, a build tool for ClojureScript (Clojure targeting JavaScript) has support for JVM dependencies? It's because Clojure has support for macros which can be written in JVM Clojure and used inside ClojureScript. Some libraries that need both Clojure and ClojureScript are distributed via Maven (or Clojars).

Shadow also has support for NPM dependencies but those go to the standard package.json file which we will create in a while. This :dependencies key in the case of Shadow refers to JVM dependencies hosted on Maven.

Since we don't need any external libraries for our first project, the value is an empty vector. If we had any dependencies, the vector would look like this:


This page is a preview of Tinycanva: Clojure for React Developers

Start a new discussion. All notification go to the author.