Hi folks, May I ask for your opinion and advice, please?
Is Clojure a reasonable choice for simple web apps? I am talking about hobby projects, mostly CRUD stuff, dozens of users. Things like a simple booking system for a local gym, etc., not expecting millions of concurrent requests
I am also not a professional developer, so I need something that can handle āstupidā hacky junior code. Some advanced Clojure concepts are beyond my (current) skills. The reason Iām drawn to Clojure is that I find lisp style and syntax actually very friendly, natural and elegantā¦
I know frameworks are not very popular in Clojureverse, but would you recommend some that have solid userbase, good documentation, and maybe some similarities with e.g. Phoenix? And have beginner-friendly tooling, including much-hated code generators maybe? Itās a bit difficult to figure out whatās what in Clojure.
The only two āframeworksā Iām aware of for Clojure are Coast and Luminus and even the latter is really just a project template that composes several libraries.
Luminus is more popular, by far, than Coast, but I donāt consider Luminus to be beginner-friendly. I donāt know much about Coast but my understanding is that itās written by a Rubyist who wanted something Rails-like in Clojure.
The reality is that people just donāt use frameworks in Clojure and, for the most part, they donāt build āmostly CRUD stuffā with Clojure ā so thatās a bit of a bare spot that beginners really notice when they come from other languages that either focus on or at least heavily support āmostly CRUD stuffā.
What Rails and Phoenix etc offer has no parallel in Clojure. See this massive ClojureVerse thread about what beginners struggle with and youāll see quite a few posts about the lack of easy web app stuff.
Iāve been using Clojure for a decade in production at this point and I doubt I would use it for hobby web apps that are mostly forms, validation, and database access. Iām not sure what I would use, to be honest. I donāt like Ruby as a language but I might consider Rails, or I might look to PHP or Python for something quick and dirty out of the box ā but it would mostly depend on what tech was easiest for wherever I wanted to host this.
Just for completeness Iāll add Fulcro to the list of frameworks. Not a recommendation however as itās just something on my āto investigateā list.
For some reason I thought Fulcro was front-end only but it does appear to have some server-side components. It looks extremely complex so I would not consider it ābeginner-friendlyā despite the extensive documentation.
Itās hard to compare these ecosystems, they have very different demographics and philosophies. The preference for libraries instead of frameworks has good reasons which Iām not going to rehash here, the net result is that thereās more of an initial learning curve Iām the beginning. Thatās not so much because these libraries together are more complex than an equivalent framework, but it takes effort to figure out which bits you need, and how to wire then up, which is why a template that embodies these opinions regarding the stack and that takes care of the wiring like Luminus exists.
I also feel like thereās more stuff happening around React based apps. Plenty of people are doing server side rendered too, but there are fewer libs coming out in that space, fewer people writing about it. But I do still think itās a great choice for a lot of stuff and there are good libs to choose from.
My personal recommendation would be to lean in to the Clojure way: learn libraries one by one, try them out at the repl, then piece them together. I would start with
Model - honeysql
View - hiccup
Controller - Iād like to say Reitit, but for starting out Compojure is probably better
Thatās it, you can make an app with just these three. The rest youāll figure out as you need it.
Update: as pointed out here vanilla hiccup is susceptible to cross-site scripting attacks, and you should use Hiccup 2, which is nominally in alpha but which has been perfectly fine to use for years. Alternatively use any other Hiccup implementation. For the Lambda Island site we render our Hiccup with Enlive.
hiccup is not safe by default, as it requires you to manually escape every string. Iām not even comfortable using it myself, much less recommending it to a beginner. Iād recommend using rum, since you can use the same syntax but stringify it with rum.core/render-html in place of hiccup.core/html. rum 0.11.5 for now though, as the 0.12.x releases currently require ClojureScript to compile.
You might write a small helper if you do need to set unescaped strings frequently, as rum uses a very verbose React-compatible syntax:
This is a bit of an aside, but the hiccup 2 alpha does escape strings by default. I donāt know how alpha is alpha in this case, however, and there seems to have been little activity in the repo for a while.
Biff is intended to fit this use case, though at the moment itās still an early project and probably needs a lot of work before the onboarding experience for beginners is smooth. If youāre interested in this project, I could really use people to try it out and let me know what pain points they run into. Iām using it myself in production and am quite happy with it, but it can be hard to predict what issues other people will have (especially for the documentation).
The alpha only implements the core as hiccup2.core. Other namespaces like hiccup.page have the old unsafe behavior. It really wouldnāt be that hard to implement, but thereās just no reason to when there are good alternatives that also integrate with ClojureScript.
hey, <script>alert("you got pwned");</script>, have a nice day
then the JS code will run for anyone who views the page. Usually you would want that text to be converted by default to something like hey, <script>alert("you got pwned");</script>, have a nice day.
Oh, also: Firebase + ClojureScript is actually a very nice experience, and I would absolutely look into that. I made Biff after running into limitations with Firebase, but for a lot of apps Firebase will likely be more than sufficient. I have a non-trivial example app here (itās a board game): https://github.com/jacobobryant/mystery-cows
So, I would use Clojure myself, but now you ask as a beginner, and for something that can handle āstupidā hacky junior code. With those constraints, you probably donāt want to use Clojure, unless you are doing it as an exercise to learn about Clojure and web dev.
It might depend how beginner you are. Do you know SQL and can you create database tables, relations, etc.?
Do you know HTML/CSS and basic JavaScript?
You might be able to follow some basic Ring tutorials in this case. That said, even then you might struggle with deployments, and serving requests and anything harder will be pretty confusing, like basic auth, and certs, sessions, etc.
What I meant by hacky junior code is that my solutions are usually not the most efficient, robust and elegant ones. Thereās amazing stuff that can be done in Clojure in 2 lines of code while still being readable, while my solution would probably still be less āclojuricā and take 10-15 linesā¦
Iāve done my fair share in Swift, Ruby, Python, Elixir, etc. so itās not like Iām a total noob. But I would still prefer a sort of framework with āconvention over configurationā ā a starting point with safe bet choices for many tasks. These choices are hard to make if youāre in a completely new ecosystem, so you just need to start somewhere. Iām not looking for a black box, I am looking for a collection of informed conservative decisions tied together in a āboringā postgres-clojure-clojurescript phoenix-like starter pack
Most of my professional apps are āsmallā and āCRUDdyā. I work in a university setting and have to maintain a dozen apps with user-counts usually from the tens to the dozens. I love Clojure for this because, aside from the size, it gives me two things:
Stable Robustness. In the web application world of insane flux, Clojure[script]'s ability to stabilize and provide longevity is truly priceless.
Superior dev experience. The REPL and (on front-end) Figwheel/Shadow.cljs experience is really hard to go without once youāve tasted the wonder. It is more fun, more rewarding, and, as a result, faster dev experience.
These two benefits depend on one requirement. The fact is that Clojureās higher difficulty for beginners is the price to pay for a language that actively pushes you to be a better developer. It will be challenging at the start, but after your first month of Clojure you will be a better developer than that same first month of Javascript, PHP, Python, C, or Java. As a hacker, I think this has to be what you want before other benefits.
In the name of this learning, I second earlier mentions on this thread of Luminus, which is a terrific way to see how the pieces fit together so that down the road you are ready to start customizing/switching them out as needed.
Thank you all! I am starting with Luminus that was mentioned several times and seems to have a decent history. Also seems to have solid documentation and isnāt too quirky (just a little bit)
If you really do want to start with something fairly bare bones for a CRUD app with SSR (server-side rendering of HTML), my user manager example should be fairly easy to follow.
Itās built with Ring, Compojure (routes), Selmer (HTML templates), Component (lifecycle management of resources), next.jdbc (database access).
It uses SQLite for normal operation, but any RDBMS could be used. It has tests and uses H2 in-memory as the test database.
It uses the Clojure CLI / deps.edn which I prefer over Leiningen (at work, we started with lein a decade ago because it was the only option, then switched to boot in 2015, and then to the new, official CLI tooling in 2018). I think itās a lot simpler to work with than Leiningen (although Leiningen is āeasierā to get started with).
Thanks for the link to your user manager demo app, I wasnāt familiar with it. Iāve been using Luminus but itās great to see another (simpler!) example of how to put things together.
Yep, I agree. Ring+Compojure+Hiccup+one of the SQL libraries will get you a long way. And there are lots of examples of how to put together that stack, so I recommend it to beginners as the default starting place. It may not be the most performant stack for heavy-duty applications, but it will handle a lot and can be further tuned if necessary. Add Selmer if you want more advanced templating.
It seems like Luminus recently switched itās routing library from compojure to reitit. The last time I checked (which was last year) it was still compojure.
I was pleasantly surprised because in my opinion this makes frontend and server routing somewhat more streamlined and therefore less decision to make when mix-and-matching libraries. (When we create a reagent-template lein project, it comes with reitit client+server routing by default, so having Luminus - which often is the framework I use as reference - use the same routing library makes it easier for a newcomer like me setup a project from scratch).