Building a startup on Clojure

After first getting hooked on Clojure in 2018 I decided to build my business, Wobaka.com, on 100% Clojure the following year. That's how much I enjoyed it. I thought I'd share some of my experience and technical stack for anyone else thinking about building and running their business on Clojure.

I'll walk you through my background and parts of my experience with Clojure, but if you're just looking for my tech stack, skip to the end.

Yes, it's great (even if Java)

First of all, it's a great experience. Enjoyable. Easy to upgrade and no npm fatigue. Libraries doesn't always look as popular on Github as in other languages, but they're often of high quality.

I'm not big on Java but Clojure running on the JVM turned out to be a huge benefit. It makes it easy to run your app on any platform and you can even deploy it as a single file if you want to using uberjar.

Don't hold of starting with Clojure because of Java.

Before Clojure

Let's start with some background on what I used before coming to Clojure, so you know a little more about what I compare it too.

I've been building things on the web since around 1999. Staring with HTML, JS, Geocities 🤘, ASP, PHP and Java. More recently I've liked to work with Python using Flask or Django. I've also worked quite a bit with NodeJS and Ruby on Rails. For the frontend I've mostly used plain JavaScript, jQuery, Backbone, Angular and most recently React and Vue. The whole shebang.

I also have some (mostly academic) experience from working with distrubuted systems in Go, low level assembly and C, writing functional programs in Haskell, working on a compiler in Scala and coding proof testers in Prolog.

Alright, enough about my background, let's dig into the setup and experience of building a business on Clojure in 2022. Which is not that different from 2019, when I started building Wobaka. And that's a good thing!

Getting started

"Simple, not easy" is almost a mantra in the Clojure community by now. If you haven't watched the talk (Simplicity matters), check the footnotes [1]. To keep things simple I opted to not use a full web framework like Rails, so getting set up took a little more time. Honestly, it was mostly just finding my way around the ecosystem and finding what libraries to use for things like routing and database migrations. Tools like Leiningen makes it really easy to set things up and I wish I had this blogpost when I started out.

You can use Leiningen (a handy tool like npm + extras), and basically do lein new app <name>.

Development experience

Development experience is great once up and running. I setup everything with very few libraries so I had to write some extra code to get started. Now I have hot reloading, simple state management, very few dependencies and never have to switch language, not even for css.

Ok it's 97.8% Clojure. I do have some config files not written in Clojure.

Library support

Sometimes the documentation is great, sometimes it's not. However, the good thing with Clojure is that it's really easy to read the code. It's just functions and data. Just look at the imported namespace and see what functions there is.

Java and JavaScript interop

Interop makes it easy to tap into the host language's libraries. I almost never use interop with Java but on the frontend I sometimes need to interact with the DOM. Working with JavaScript is pretty straight forward though. For example, adding a click event handler that calls event.preventDefault() is as simple as this:

{:on-click (fn [event] (.preventDefault event))}

You basically just flip the order when calling object methods. Or you could use Clojure threading which passes down the result from functions. Look, now it's basically the same:

{:on-click (fn [event] (-> event .preventDefault))}

This makes it easy to use any JavaScript library, and since the view library I use is built on top of React, I can basically use any React library as well, if I wanted to.

Deployment options

Deploying a ClojureScript frontend is a very smooth experience. I really recommend using something like Netlify and from there it's basically a one-liner to build the application using Shadowcljs (a beautiful tool to setup and build ClojureScript projects): npx shadow-cljs release app.

The backend is also easily deployed using something like Heroku but you can also host it easily on your own server. To host it yourself you can build the entire app into a self-contained uberjar using lein ring uberjar . Now you can just run the uberjar on any system with Java and you have the backend up and running. Most likely using something like systemctl and a reverse proxy in front like Nginx.

One thing to consider is that when your project grows larger, the startup time will not be instant or really quick like NodeJS or native binaries. This means that you may have to do a little work to get zero downtime deploys. But it's nothing that can't be fixed.

The stack

This is what I use to build my SaaS on 100% Clojure. Let's start with the backend.

  • Leiningen for project / dependency management
  • Ring + Compojure for routing and REST API
  • Ring-logger for logging requests
  • Environ to manage environment variables
  • Java.jdbc + c3p0 for database connection to Postgresql
  • Ragtime for database migrations
  • Tick for date/time utils
  • Postal for sending emails
  • Buddy for cryptography
  • Clj-http for making requests
  • Cheshire for JSON parsing

That's it for the backend. I've built my own worker/job scheduling using Postgresql and clojure.core.async, which basically let's you do concurrency like in the Go programming language.

I have two frontend apps. One for the marketing page which is server rendered and hydrated on load, and another that's just an ordinary SPA. For both I use the same setup.

  • Shadowcljs to build the apps
  • Rum as a React wrapper and view component library
  • Accountant + Secretary for client side routing
  • Cljs-http for making API requests
  • Garden for writing CSS in Clojure
  • Flatpickr as date picker
  • Chartjs for charts
  • Papaparse for client side csv parsing
  • Trix as WYSIWYG editor
  • Plyr as Vimeo video player

All in all, Wobaka is a relatively large app by now but it's still simple to work with, because it's just functions and data. It's also still simple to manage and update dependencies. I default to building things myself but sometimes it doesn't make sense and I'm happy to be able to tap into the JavaScript ecosystem.

Parenthesis

I almost forgot to write about parenthesis. That's how much you care about it after getting started. They are just in different places (it's not a big deal).

Give Clojure a try

I really recommend giving Clojure a try. Especially if you like to write functional JavaScript code or enjoy working with things like React.

Clojure for the brave and true [2] is a great place to start. For a more web focused guide I'm not sure. But I hope this guide can give you some good starting points on which libraries to use. Perhaps I'll write a getting started with web development in Clojure blogpost at some point.

Building your startup on Clojure or just want to talk Clojure? Hit me up on Twitter @drikerf.

Also check out my other blogpost about things I love about working with Clojure.

How I Use Clojure to Build and Scale my SaaS
I was first introduced to Clojure in grad school where I was taking a course on building large scale software applications.

[1] https://www.youtube.com/watch?v=rI8tNMsozo0
[2] https://www.braveclojure.com/