Ctmx - super lightweight web dev

Hi fellow Clojurians! I have been writing Clojure professionally for about 8 years now, and recently came across the https://htmx.org library. It provides an elegant way to build dynamic web apps, so I decided to connect it to a clojure backend and the two go together really nicely.

ctmx provides a ‘component’ macro which expands to both an ordinary function and a REST endpoint (via reitit). It feels quite similar to writing clojurescript, except you are fully on the backend with JVM clojure and no compiled js to load on the frontend. The GitHub repo has a demo project which you can start by cloning and typing lein run.

Feedback and suggestions would be much appreciated.

18 Likes

This looks great, my only feedback would be that the types seem to make no sense for Clojure.

Clojure uses long and double by default, not int and float, so what type does the cast convert the value too?

When you say array I’m assuming you mean vector, but again, I can’t tell what a cast to an array will convert the string too.

Otherwise it’s a cool idea and I’m looking forward to trying it out!

Good suggestion @didibus, I will put that in.

oh this is nice I’ll check it out! I’ve been using clojure+htmx for a while now and it’s such a nice combo. No need to mess around with Cljs to make some SPA-like

Feel free to make feature requests, I’d like to make ctmx more useful for the community.

:man_technologist:I’ll play with it soon and maybe I’ll have some feedback :slight_smile:
The idea of combining the element with its own endpoint in one go sounds good already, which was my biggest nuisance.

When you code you feel like you’re on the frontend, but then you think: “oh great I am on full JVM clojure with sync, threads, access to db etc”. It all just fits together, hard to describe you have to experience it yourself.

Oh yeah I get it! I don’t know Javascript so staying in Clojureland was a massive advantage. I was trying Turbo lately, but I think I’ll revert back to Htmx. Turbo is too rooted in RoR and it does not allow the level of flexibility Htmx has.

@Matthew_Molloy on this SPA-like I’m building right now, I have to update multiple divs with a single request. I was using hx-swap-oob before (I’m testing Turbo these days, but I think I prefer Htmx) but I don’t think I had the correct pattern. Do you have an example of that?

@jcpsantiago sure. So for hx-swap the system needs to know a matching ID. The response will look like

<div id="swap-item1" hx-swap-oob="true">...</div>
<div id="swap-item2" hx-swap-oob="true">...</div>

htmx checks the top level items. If hx-swap-oob="true" it knows it has to swap in somewhere, so it searches the web page for the matching ID. If none is found it will throw an error.

In CTMX you would write as follows

(when top-level?
  (list
    [:div#swap-item1 {:hx-swap-oob true} ...]
    [:div#swap-item2 {:hx-swap-oob true} ...]))

You have to check top-level? because you only want to include these items on an element update, not on the initial render.

If you share your code with me I can give you a more specific solution. My GitHub account is whamtet.

I was missing the top-level?, interesting bit. I’ll try something.

GitHub - jcpsantiago/htmx-clj-dashboard: Explorative playground on building a dashboard with server-side tech I had started this repo to play around with creating something like ctmx but didn’t get far :smiley: The stuff I’m working on right now for my company is waay more complete hehe, I’m trying to convert it to ctmx and seeing where I find problems.

I was talking to some of the scicloj people (hey @daslu :wave: ) that would be cool to have a similar frameework to R’s Shiny for quickly creating simple apps and dashboards to showcase data science projects to non-technical people (a common use case I have).

1 Like

Shout out if you want any help converting! You might find it easiest to start with the demo project /demo in the ctmx repo. cd in and then just type lein run. You can then copy the /demo directory into a fresh git repo and start making commits.

Hi,
Before today, I don’t know about ctmx, still less about htmx and it’s awesome!
Nice work you done!

I find very useful and interesting these alternative propositions for Clojure ecosystem.

For my part, I had the same feeling when I wrote this Inertia adapter which allow to write back-end the same way but resulting to SPA.
The state, the routing and the logic continues to live on back-end and the front-end libs (Reagent, React, Vue, etc) are used like any templating language.
And icing on the cake, it supports now SSR.

Here the links, if you interested in:

2 Likes

is there any template file for leiningen?

@md1frejo for now just cd into /demo in the GitHub repo. Can create one if there’s demand.

Wow, I will check this out!

1 Like

yes that would be nice and probably encourage more to try this project

This looks good! Thanks for bringing htmx to attention, I hadn’t come across it before. I was convinced that I wanted to use stimulus.js for my next web project, but htmx looks even better.

I think if I end up finding the time to experiment with this, I will start by building with pure htmx to see the patterns in full, and then convert to ctmx for comparison.

When you decided to build ctmx, was that a result of having used reitit and hiccup to build an htmx app before?

1 Like

I created ctmx in parallel with my first htmx app. I wanted something that feels like frontend, especially react or clojurescript reagent, but is actually on the backend. I would like suggestions if you have alternative ideas for a clojure/htmx architecture.

1 Like

Cool! I will let you know what I find when I get around to actually build something with htmx and ctmx.

Having ctmx as a library would be great :grimacing:
doesn’t seem too difficult? Clojure - Deps and CLI Guide