Isn't Clojure overkill for small web apps?

Thanks Jacob, I’ve used DO for python web apps and been happy with them.

About a year ago for my Clojure web apps I started using Jelastic (sort of like Heroku for java apps, but much cheaper) and found that it ended up being free for hobby projects with low RAM usage. I wrote a blog post about it a while back and now my ears prick up when ever I hear people talking about Clojure web app hosting.

P.S. Complete aside, but I enjoyed reading your blog post which I stumbled upon a while back about your experience of being home-schooled. My wife and I home-schooled our son for 4 years and it was a wonderful experience.

6 Likes

Seems like mirhosting.com is flagged by my ISP netCaffe as being a malicious website, and Google also flags it as unsafe :man_shrugging:

For Clojure, no job is too small or large.

Large hobby projects are more fun if you’ve already tackled small
hobby projects!

You will eventually settle on a bunch of tools. The parts fit
together pretty well in Clojure. You won’t need a framework to do it
for you.

If you want to stay on a very (very) well-paved path, the first major
decision is Ring or Pedestal for the server. Can’t go wrong with
either. There’s probably more advice floating around the internet
about Ring. Then just hop into a REPL and have at it.

After your first project with Ring, you can do anything. By the way,
do not be put off by scantiness of docs, or anyway, not by that alone.
People who come from, say, Python remember appreciating
the 1800-page Django manual, because Django is easy.
But Clojure is simple. A whole different ballgame.

5 Likes

Thank you Phil! Yes, it’s very useful to hear the opinions here, how to approach thinks in Clojureverse and which libraries are commonly used for which tasks.

I am also experimenting with LFE, which is a full-blown mature lisp on top of BEAM virtual machine. Kinda best of Clojure combined with best of Erlang, which is exactly what you want for web projects.

That’s not exactly confidence inspiring, is it? What’s the Google tool that gave a warning about it? I just checked mirhosting.com on https://transparencyreport.google.com/ and there weren’t any warnings.

Clojure won’t be significantly harder to build a web application on then say, ruby.

However, I know several professional clojure devs that use wordpress. I don’t know the trade off, but the implication is that it might we wiser to start with something much more ridged (less options but more defaults) if you can fit your problem into it.

1 Like

WordPress just hides a lot of problems. I’ve seen pretty complex apps built quickly using plugins, and the performance seems great. But behind the scenes the plugins are doing things like LIKE = “%x%”, and you’ll run into serious scaling issues at 10-100 users. Security seems okay if you’re small and always stay updated, but if you get big enough to be targeted then you need to be shelling out $99/mo for Wordfence. I constantly get breakage due to plugin updates, usually due to minor releases or supposedly “bugfix” releases, but with no automated tests or anything to discover that breakage. It’s basically the polar opposite of the Clojure ecosystem, and it’s been very educational as to why Clojure does things the way it does. E.g., you really appreciate Clojure’s dependency system and always using exact versions when your site dies because you have two plugins using the exact same version of the AWS SDK but with slightly different transitive dependencies on guzzle-http, only differing in the last digit. My solution was to just remove the AWS SDK dependency from my plugin, since it builds on the other and I don’t think one can do any better in WordPress.

Due to all of these issues, I’ve been using WP2Static as much as possible (and am now a committer). It doesn’t work for every site, but where it does it fixes most of the performance and security issues and allows you to get off the update->break hamster wheel. Most of my client sites use this with a Clojure server handling logins and controlling access to the site via ngx_http_auth_request_module. If the site works properly, you can just leave it alone – no updates required. You can achieve the same thing by running the site locally in Docker or such, with no internet exposure.

1 Like

For Google it’s just the bad SSL warning that Chrome gives you: Untrusted connection.

And maybe that’s also why this McCaffee screener from my ISP triggers as well.

Hum, it seems it’s blacklisted by McCaffee and runs an outdated version of PHP. That’s all I could find. Don’t know why.

we’re slightly off-topic here, but I do remember one project that had a MVP on Wordpress and they hosted it on WP Engine – those folks at WP Engine were absolutely killing it!!

World class support, responses in no time, helping with the craziest quirks one can imagine, and squeezing absolute maximum out of Wordpress. I was amazed what’s even possible on Wordpress.

That’s how I got to Clojure actually. We had high concurrency situation, WP was stretched to limits (although WP Engine bought us a lot of time) and we were looking for solutions. Found Elixir and Clojure back then :slight_smile:

Hi!

I’m a bit late to the party, but as far as your intial puzzle regarding size and scope of a Clojure Web App is concerned, I’ve been in pretty much the same predicament about 10 months ago when I was still unsure if should set out to learn Web Development using Clojure or a more “standard” language. Most of all I was unsure if I’d be able to deploy my small time beginner’s apps to a fitting environment. For now I’ve found the Macchiato framework to occupy a sweet spot in that regard.

By now I consider Macchiato to be fairly accessible as long as you know the underlying technology (which I didn’t when starting out). It uses Node.js instead of the JVM for the server side and I now have several instances of it running on a single shared hosting plan – so costs and entry barriers are minimal.

The handling is modeled on Ring and the whole experience seems to be very similar to Luminus (“seems” because my own experience with Luminus is still limited). Sofar I’ve done a couple of small time projects with it, like classic dynamic Homepages (the kind you do when first learning PHP) – and it does the job pretty well. Incidentally I’m currently working on a hotel booking site with parts of the frontend done with Reagent.

In oder to facilitate CRUD I’ve found Directus® to be a really versatile headless CMS with perfect transparency towards the underlying SQL. It offers a very nice API for which I’ve written some wrappers, so I can now query the DB from the frontend and backend using the same Clojurescript code.

There are obvious drawbacks, of course, with Node.js being much less rich as a platform and a good bunch of Clojurescript libraries not assuming it as a runtime (The inability to use hickory to parse HTML into Hiccup has been a pain for quite some time).

The biggest problem for me as a total beginner in (Web) development was the documentation, wich is also rather lightweight. Not many tutorials out there (only now there is one). If you have never heard the terms “routing” and “handling” (I take it you have) you’ll have a much harder time figuring that out than if you were learning, say, Node with Express. Reading Sotnikov’s book on Luminus earlier definitely would have helped me. However, Clojure being Clojure, I was ultimately able to “reverse engineer” Macchiato step by step just following the various function call chains towards a sufficient understanding (I guess Rails would have been more opaque in that regard).

TL;DR, maybe, for small projects, consider Macchiato as a lightweight alternative to the Luminus stack. Maybe combine with a CMS like Directus to facilitate much of the CRUD work.

Cheers!

BTW: Hiccups, the Clojurescript version of Hiccup is safe insofar as it escapes dangerous symbols.

I’ve found Directus® to be a really versatile headless CMS with perfect transparency towards the underlying SQL. It offers a very nice API for which I’ve written some wrappers, so I can now query the DB from the frontend and backend using the same Clojurescript code.

Can you tell us more about what you use it for? How do you manage security if you query the DB from the frontend?

Thanks for asking! This piece has gotten bit long, so I considered opening a new thread for it but I feel it’s actually on topic, so unless any of the moderators feel differently about this, here’s how I use Directus for small Clojurescript websites:

API Security has been a non-issue so far

The Directus API does offer authentication via access tokens. However, being quite new to web development I’ve been pretty paranoid about security; so up until recently I have successfully avoided the need to actually use the auth mechanism: Most of my data is either public for reading or completely off limits via the API. Directus offers fine grained control over the permissions for reading/writing tables and fields – publicly, via authentication (or not at all).

Using only partially public access is completely sufficient as long as I only cater to a closed user base, i.e. I add the content creators manually to Directus and provide them with rights accordingly. So, for now, I ultimately rely on Directus’ account and permission management for security.

Simple Example Project

Directus allows non-technical users to edit a SQL Database in many different ways. As an example you can look at the very first website I’ve made, for a musician. Among other things she needed the ability to manage programs, performers and concerts (connecting them to one another). The underlying SQL looks something like this:

Performers:
| name          | id |
|---------------+----|
| Solo          |  1 |
| Trio Sérénade |  2 |
| Duo Adamé     |  3 |

Programs:
| title          | composer       | id |
|----------------+----------------+----|
| Trio Piazzolla | Piazzolla      |  1 |
| Hallelujah     | Leonhard Cohen |  2 |
| preludes       | Chopin         |  3 |

Concerts:
|       date | program_id | perfomer_id |
|------------+------------+-------------|
| 12.12.2020 |          2 |           3 |
| 14.01.2021 |          1 |           2 |

Directus offers several Frontend Interfaces for the various SQL relations which are created in one go with the tables and fields. The Interface for the O2Ms above looks like this (German, sorry):

To the left are the various collections (≙ SQL tables). When adding a new concert item (≙ SQL row) I get to fill relational fields via dropdowns (or other means). This Interface works very well for non-technical users but is still totally transparent as to the underlying SQL (unlike WordPress @John_Shaffer). Directus offers several interfaces per SQL relation – one of them for multilingual content, which makes internationalization quite easy.

Most of these Interfaces are content-agnostic. In case none of the built-in interfaces make sense of the SQL, one can either write a custom one (in Angular :frowning: ) or make something separate that works on the Database directly (or via API) – Directus won’t mind and just reflect any changes in case it is hooked up to the tables concerned.

Clojurescript integration (without overkill)

There’s not even much to be said here. Directus automatically provides API endpoints for every public collection. So anyone can query the concerts collection with e.g. …/items/concerts?fields=id,date,performer.name,performer.id (I use some wrapper to generate these queries from nested Clojure vectors). In Clojurescript that gives me

[{:id 79
  :date "2021-01-14"
  :performer {:id: 2
               :name: "Trio Sérénade"}}
 {:id 139
  :date "2019-10-26"
  :performer {:id 2
              :name "Duo Adamé"}}]

I have a generic handler that asynchronously fetches multiple collections and then forwards them to a page formatter that processes them first to hiccup and then to HTML. Also I have written a couple of Directus-specific transformers, e.g. for multilingual collections etc. Maybe eventually, when I feel more confident about what I’m doing, I’ll make these into a small library or shadow-cljs-template.

TL;DR Without Directus I’d probably be deep down the WordPress rabbit hole by now. I give it to my clients to manage multilingual dynamic websites that are rather small, but highly customized – with the occasional Reagent app for advanced interactivity.

Disclaimer: If any of the above sounds like I’m promoting Directus it’s only because it really helped me get started with Web Development and allowed me to use a Lisp in the process… also the maintainers around Ben Hanyes have helped me out on several occasions… so they deserve some good rep. I have no stock in them or anything :wink:

Thanks for explaining how it works. Sounds like your client edits their site their own account on the Directus website, and then their website pulls all the data it needs to display from the Directus API. Nice looking website you made fo the musician :smiley:

For other types of apps (i.e. aside from content sites) it seems like you could also use Directus as a sort of replacement for a Django-style admin panel, in that it gives you a GUI view of your database?

How did you come to choose Directus out of all the other options for headless CMSs? I just had quick google and it seems like there are a huge range of options.

So far I’ve only used self-hosted instances of Directus. My clients have their own shared hosting plans where I’m running all three pieces: The Directus instance, the underlying SQL Database and the Clojurescript app (Macchiato). I haven’t used the Directus Cloud so far. It might be faster for frontend-querying, but for server-side rendering I expect self-hosting to have a performance edge. Also that way I can query the DB directly when I feel the need.

This is exactly what I’ve been doing (for the most part) – probably not the first thing you’d choose Clojure(script) for, but a good way to get some first real world experience. My approach still makes for a good amount of clojure code, so it’s only cost-effective for stuff you cannot just throw a Wordpress plugin at.

“Database GUI” pretty much sums it up, so I assume you can use it for anything where an easy way to edit SQL comes in handy.
I’ve never used Django, so can’t really compare the two. Looking at what I could dig up just now it seems that Django offers more fine-grained control over the details of the admin panel – at the expense of setup-easiness (maybe not simplicity :wink: ). Setting up Directus, once installed, is mostly a point-and-click adventure: The SQL relations are created together with the Interfaces. One should know how relational databases work and have an idea of how one wants to query the API, but that’s pretty much it. I have yet to write a single line of PHP or Angular for any Directus-Project.

I’ll try to make this short since ultimately the choice was more or less arbitrary. My main constraints at the time were

  1. Self-hosted
  2. PHP-based (I was unsure if I’d find a shared hosting space offering anything else in Germany)
  3. SQL-based
  4. WYSIWYG HTML editor for my clients.
  5. Integrated Thumbnailer

A nice guy on on StackExchange pointed me at http://cmsmatrix.org/, where I pretty much just stumbled across Directus. After a quick chat with Ben Haynes I was optimistic about getting it to work with a Reagent App, which it did just fine (only later did I find out about Macchiato and switched to server-side rendering).

Maybe some other CMS might have served my purposes just as well; in my case Directus happened to make the use of clojurescript viable for the small content sites I had to start with in order to get a feel for the matter.

Yeah, makes sense to self-host, then db access is quicker. Thanks for explaining the context of how you find Directus

BTW, I forgot to mention, the link
https://www.violina-petrychenko.de/en/termine

doesn’t work but this one does:
https://www.violina-petrychenko.de/de/termine

SEO tip: might be worth including meta description tags the pages, if search engine visibility is important for your client.

Hi, thanks! The English link does work on my side, actually all three languages do… weird. Does it give you 404?

Also thanks for mentioning the meta tags… I have learned about them since, but haven’t gotten around to backport some of what I’ve learned from later sites to this first one.

(for specifics of that site, feel free to PM me, I want to avoid monopolizing this thread)

FYI, babashka with httpkit server was released as 0.2.1.

1 Like

I use Wordpress for all my non-Clojure stuff; or I should say, I’m in charge of Wordpress. Lots of it. The biggest plusses I find in WP is good interfaces for non-programmers to do CRUD stuff, and a truly massive ecosystem with a tried-and-true robustness (despite being on PHP).

Very late to the party here, but as a long time “CRUD-like” application builder (and as a proficient, Clojure developer who uses currently Clojure professionally), I still can’t come close to the efficiency of Rails or Laravel when building CRUD applications in Clojure. This is not a language deficiency, but, in my opinion, a limitation of framework adoption in the Clojure world. I’m talking mainly of server rendered applications, which are the norm for these type of applications. Front-end single page application frameworks are great, but in my experience, overkill for the application. Coast is close (and some very nice work by a dedicated person, but still doesn’t benefit from community adoption. I’m afraid that to see a Clojure CRUD framework begin to stand out, it will take a lot more adoption by the broader community. In the meantime, I’m happily productive in Ruby/Rails with my CRUD apps.

It’s somewhat timely that you’ve responded to my post from last August at this point in time: at work I’ve been “migrating” a legacy CRUD app to Clojure and after manually writing a bunch of handler functions that process fairly simple forms, I’ve abstracted some of the work out into an internal library called, imaginatively, crud-form. It is mostly centered on two functions: one to handle nearly all of the basic form processing and database insert/update – leaning heavily on Spec for validation and exoscale/coax for data coercion, and a second one to turn Spec errors into readable error messages for users leaning heavily on the phrase library.

Although it’s doing a lot of heavy lifting for me, the invocation – taking a data source, the form parameters, a database table name, a Spec, and various processing options, several of which are functions – is often almost as long as the rote code it would replace: the joys of generic processing when there are always edge-cases and overrides and custom logic. It’s about 200 lines of code right now. I figure that once I’ve migrated more of the legacy apps – and also refactored some of the earlier “verbatim” migrated code to use crud-form – it might be in a state worth releasing as a library, in case it helps other people.

3 Likes