Beginner Clojure web app using Luminus template

You don’t have to know much about coding to get started!

ClojureHub
7 min readDec 1, 2021

Are you a beginner trying to understand web apps, and all the confusing pieces that have to come together to get things working? This post is for you. Why am I writing this? Because just a few months ago I was in your shoes. Many tutorials online assume some coding knowledge already, or they go very deep into specific beginner concepts. Want to bring it all together, build a basic foundation and just see how everything connects? This post is for you!

Before we get started, I’m going to assume you have all the prerequisites downloaded (Java JDK 8+, Leiningen, Clojure, PostgreSQL, Node.js), and have a text editor set up. If you have questions on that stuff, keep an eye out for future posts where I will walk through all that.

Now, on to creating a very basic, beginner friendly web app with all the necessary pieces. Note that we are not going to be adding any features at this point. Just using a template to piece together the basic parts & make sure they are all connected and working.

There are a few templates for creating web apps using clojure, and we’re going to use the Luminus template. We’re also going to end up adding some useful dependencies like Shadow-cljs to use ClojureScript. We’re also going to use PostreSQL as our database.

Getting a basic app started

We’re going to start by opening the terminal window and typing the following:

lein new luminus cool-app-2 +shadow-cljs +postgres +http-kit

Note that this generates a Luminus project with the latest version. At the time of writing this, the latest version that was generated was 4.20. If you want to follow along with the exact same version that I used, then you will want type the following command instead:

lein new luminus cool-app — template-version 4.20 +shadow-cljs +postgres +http-kit

Now we have a simple app that’s generated and we’re adding a few useful dependencies. We have Shadow-cljs for Clojurescript, and we have Postgres for the database, and http-kit is for transporting webpage data. We can always add more dependencies manually to the project.clj page, but lately I’ve been adding a few at the beginning that I know I’ll want to use.

At this point, now that we’ve made the app, we want to make sure that in the terminal, we are in that directory.

cd cool-app

Now, let’s see what the template has generated for us:

lein run

We get an error:

ERROR cool-app-2.core — Database configuration not found, :database-url environment variable must be set before running

This is because I added a database connection already, so the compiler is looking for a database. However, we don’t have a database set up yet. Let’s go ahead and add that really quick.

Creating and connecting a database

Something to note about Postgres is that the names must contain only letters and underscores. So, instead of calling a database cool-app, we have to change it to cool_app. Also, PostgreSQL names appear to be case sensitive and I believe it’s most common to have them be lowercase. So I’m going with that.

Let’s create the database. I’ve already downloaded PostgreSQL, and I clicked on the App in my Applications folder, and it’s currently running. To check if it’s running, you can look at the Elephant (Postgres logo) in your top right menu and see if you have a green checkmark with a “stop” button. This means it’s running. Otherwise if you don’t have a Postgres shortcut in the menubar you can click on it from your Applications folder from Finder and check on it there.

I’m going to open another terminal window and type psql. I didn’t change the directory from the default. Now I want to create a database with a user and password. This information I’m going to put in the dev-config.edn file in my cool-app folder.

Right now the file looks like this:

;; WARNING;; The dev-config.edn file is used for local environment variables, such as database credentials.;; This file is listed in .gitignore and will be excluded from version control by Git.{:dev true:port 3000;; when :nrepl-port is set the application starts the nREPL server on load:nrepl-port 7000; set your dev database connection URL here; :database-url “postgresql://localhost/cool_app_2_dev?user=kittykat&password=db_user_password_here”}

The last part is where we’re going to put the new information. But, first things first. Let’s create a new user and then a new database.

Go to your terminal and type in psql to be able to write commands for Postgres. Of course feel free to change the username, database name and password to whatever you want.

CREATE USER cool_user WITH PASSWORD ‘cool_password’;CREATE DATABASE cool_database WITH OWNER cool_user;

Remember to use the semicolons with psql commands, because without a semicolon, the command won’t be run.

Alright, now we have a database set up for our app, with a special user and password. This information will get fed into our project’s dev-config.edn file:

;; WARNING;; The dev-config.edn file is used for local environment variables, such as database credentials.;; This file is listed in .gitignore and will be excluded from version control by Git.{:dev true:port 3000;; when :nrepl-port is set the application starts the nREPL server on load:nrepl-port 7000; set your dev database connection URL here:database-url “postgresql://localhost/cool_database?user=cool_user&password=cool_password”}

Notice that we uncommented the last line by removing the semicolon, and then substituted some of the information with the specific names of our new database, user and password.

Now if we type lein run into the terminal that’s in the cool-app-2 directory, it works. (Unless it doesn’t work… it worked for me, but if you get an error please comment because I’m curious and can potentially help sort it out).

Now, we can go to localhost:3000 in the browser, and we can see a webpage. It’s telling us another warning. We haven’t compiled our ClojureScript yet. Time to do that!

Getting Clojurescript up and running

Since we’re using Shadow-cljs, we need to install node-modules. You can type npm install into the terminal will install all modules listed as dependencies in package.json. However, it looks like it’s preferred that the install is done globally. I think this has to do with running some of the commands from the terminal, later. To do this, you simply add -g to the command. Similarly, since we’re using Shadow-cljs, we’ll specify that, too.

This next part might not be totally necessary right away, but installing node modules is another step that is generally needed when we start using Shadow-cljs.

npm install -g shadow-cljs

If you get an error that you don’t have the right permissions, then try this: https://stackoverflow.com/questions/51967335/npm-install-permission-denied-macos

sudo chown -R $USER /usr/local/lib/node_modules

Now in order to run Shadow-cljs, we will type in the following:

npx shadow-cljs watch app

The watch app part of it means that it will reload when we make changes to our files, instead of only compiling once. This will be super convenient moving forward. Otherwise, if you just want to compile it once for now, since we aren’t making any other changes for this part of the tutorial, you can simply have the command:

npx shadow-cljs compile app

I don’t know if this is best practice, but I usually will have two terminal windows open. One that is running lein run and another one, that is secondly running npx shadow-cljs watch app. If I only run the Shadow-cljs command, the app will be compiled, but localhost won’t connect. And if I only run the lein run command, then the ClojureScript elements won’t appear. So, I have both running at the same time. I think if you just compile the app instead of using the watch command, you don’t have to have anything running for Shadow-cljs and can just do lein run when you’re done with that.

When I was first learning this, I had a lot of errors at this step. I didn’t have any this time around. But if you have any, let me know. There are a lot of little things that can go wrong. Not being in the right directory, having a typo, having another process running that is trying to use the same port, and so on. Once identified, these things can usually be solved pretty quickly.

Bringing it all together

Now let’s see what we have after all this set up.

A webpage that simply says “Welcome to cool-app.” This might not look like much, but it means the Clojurescript compiled correctly.

If I hadn’t added Clojurescript, I would’ve seen a nice static website that walks you through the basics of the Luminus template. But, alas, Clojurescript will be worth having. If you’re curious, I suggest creating a new Luminus app without the add-ons and exploring what that looks like.

Our web app might not look super impressive right now, but that’s because we haven’t done much work yet. But, the important basics are covered, the foundation is set up, and now we can start building on top of this!

Coming up next we will start adding some features like a navigation bar, static webpages and more! Comment if you have any questions or requests.

Want to see more posts like this? Check them out at my pet web project here!

--

--

ClojureHub

Follow us for beginner Clojure web app tutorials & content. See more at clojurehub.com!