Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 2

Clojure Project Setup: deps.edn and src

Recommended resources

Hello again! Welcome to your second lesson.

In our first session, we successfully set up your development environment by installing the Clojure CLI and configuring Emacs with CIDER. You verified everything was working by starting a REPL from a single test file.

Today, we'll move from that single file to a properly structured Clojure project. The learning outcome for this lesson is to create a new Clojure project and explain the role of deps.edn and the src directory. This is the standard way to organize any non-trivial Clojure application.

By the end of this lesson, you will understand:

  • The conventional directory structure of a Clojure project.
  • The role of the src directory and how it maps to Clojure namespaces.
  • The purpose and structure of the deps.edn file for managing project configuration and dependencies.

Let's begin.

1. Project Structure: Beyond a Single File

While using a single .clj file is fine for quick experiments, any real application requires a more organized structure. In the Clojure ecosystem, projects follow a simple and consistent layout by convention. This makes it easy to navigate and understand different projects.

The two most fundamental parts of this structure are:

  • A src directory for your main application source code.
  • A deps.edn file at the project root to define dependencies and configuration.

Let's create this structure from scratch. This manual approach will give you a first-principles understanding that is more valuable than using an automated project generator at this stage.

The following guide provides a clear walkthrough of creating the initial files and directories.

Clojure projects from scratch

This article, 'Clojure projects from scratch' by Oliver Caldwell, demonstrates how to set up a project manually. We will use its approach to create our own project structure.

Read the section 'Initial files' (starting from 'Presuming our project is called hey...'). Pay close attention to the mkdir and touch commands used to create the directory structure and the initial core.clj file. You don't need to create the test directory or its contents for now.


2. The src Directory and Namespaces

As you saw in the reading, the src directory is the conventional root for your source code. The Clojure CLI tools are configured to look here by default.

A crucial concept in Clojure is the mapping between namespaces and the file system path. A namespace is Clojure's way of organizing code into logical modules. For example, if you define a namespace (ns my-project.core), Clojure expects to find it in a file at src/my_project/core.clj.

Notice the mapping:

  • The src directory is the starting point (the "classpath root").
  • Dots (.) in the namespace name become slashes (/) in the directory path.
  • Hyphens (-) in the namespace name are converted to underscores (_) in the file or directory path.
  • The file ends with the .clj extension.

This convention is essential for the Clojure runtime to locate and load your code.

Exercise: Create Your Project

Let's apply this. Open your terminal and create a project named fx-calculator, which we will build upon in later modules.

  1. Create the project directory and navigate into it:

    mkdir fx-calculator
    cd fx-calculator
    
  2. Create the necessary directory structure for a namespace we'll call fx_calculator.core:

    mkdir -p src/fx_calculator
    

    (The -p flag tells mkdir to create parent directories as needed.)

  3. Create the main source file:

    touch src/fx_calculator/core.clj
    
  4. Open this new file in Emacs and add the namespace declaration and a simple "hello world" function:

    (ns fx-calculator.core)
    
    (defn -main []
      (println "Hello, FX Calculator!"))
    

Your project now has the basic source code layout.


3. The deps.edn File: The Project's Brain

Now for the second key component: deps.edn. This file is the heart of a modern Clojure project. It tells the Clojure CLI tools everything they need to know to run your project, manage its dependencies, and execute various tasks.

The file is written in EDN (Extensible Data Notation), which is a subset of Clojure's own syntax. This makes it easy to read and write for a Clojure developer.

The following guide is an excellent, in-depth explanation of deps.edn and the tools that use it.

Clojure CLI, tools.deps and deps.edn guide

This guide from Oleksii Kozieiev provides a detailed breakdown of the Clojure CLI and the deps.edn file. It's the best resource for understanding how project configuration works.

Please read the following sections: Start at 'deps.edn configuration files' to understand its purpose and how different deps.edn files are merged. Read the ':paths key' section to see how to tell Clojure where your source code is. Read the ':deps key' section to learn how external libraries are declared. Read the ':aliases key' section to understand how to create different configurations for tasks like testing.

Key Takeaways from the Guide

To summarize the most important points from your reading:

  • :paths: A vector of strings specifying the directories containing your source code. By default, it's ["src"]. You don't strictly need a deps.edn file if your code is just in src, but it's good practice to create one to be explicit.
  • :deps: A map where you declare your project's dependencies. Each dependency is a symbol (like org.clojure/clojure) mapped to a coordinate map that specifies its location and version (e.g., from Maven Central or a Git repository).
  • :aliases: This is arguably the most powerful feature. Aliases allow you to define alternate configurations. A common example is a :test alias that adds the test directory to the paths and includes testing-specific libraries. This keeps your main project configuration clean.

Exercise: Create Your deps.edn

Now, create the deps.edn file in the root of your fx-calculator project directory.

  1. Create the file:

    touch deps.edn
    
  2. Open it in Emacs and add the following content:

    {:paths ["src"]
    
     :deps {org.clojure/clojure {:mvn/version "1.11.1"}}
    
     :aliases {:test {:extra-paths ["test"]}}}
    

Let's break this down:

  • {:paths ["src"]}: We explicitly tell Clojure that our source code is in the src directory.
  • {:deps ...}: We declare a dependency on Clojure itself. While the CLI tools provide a version of Clojure, explicitly declaring it in your project is a best practice for reproducibility. We're using version 1.11.1.
  • {:aliases ...}: We've defined a :test alias. If we were to run a command with this alias (e.g., clj -A:test), it would add the test directory to the classpath. We haven't created this directory yet, but this is how you would configure it.

Your final project structure should now look like this:

fx-calculator/
├── deps.edn
└── src
    └── fx_calculator
        └── core.clj

This is the standard, minimal structure for a Clojure application. The image below shows a similar structure for a different project.

This image shows a standard Clojure project layout. Note the `deps.edn` file at the project root and the `src` directory containing the source code.

Conclusion

In this lesson, you've moved from a simple script to a well-structured project. You learned how to create the standard directory layout and, most importantly, you've been introduced to the deps.edn file, which is central to dependency and build management in modern Clojure.

Key Takeaways:

  • Clojure projects conventionally use a src directory for source code.
  • The file path inside src directly maps to the Clojure namespace defined within the file.
  • The deps.edn file is the primary configuration file for a Clojure CLI project.
  • The main keys in deps.edn are :paths (for source directories), :deps (for external libraries), and :aliases (for alternate configurations).

You now have a real project on your machine. In the next lesson, we will initiate a CIDER REPL within the context of this project and practice evaluating Clojure expressions directly from your core.clj source file. This will bring together your Emacs setup and your new project structure, unlocking the interactive workflow that defines Clojure development.