Hello, I'm a refugee from Rust looking for faster and easier iteration of development of a web app (mainly CRUD); my experiences in frontend are limited to the old Frontpage 😅 and Leptos. Was looking at clojure examples but it seems we have three different approaches: simple html responses; some React wrapper (re-frame, reagent) / framework (fulcro); newer SPA cljs frameworks like Replicant. If I don't want to use React but have some interactivity (say, autosave), it seems I need to serve a SPA from the server? I haven't found "SSR with client side hydration" library, I could implement something with enough time and help, but it seems a common use scenario? Or nowadays it's best to just bite the bullet and do everything in the client side, be it React or something else?
hey folks, I was following the thread and sorry for jumping in after a few days, but it's been a year I've "dancing" with the idea of having something Reagent-like but very simple for ClojureScript and I decided to finally make it and I just published this idea to my Github and to clojars: https://github.com/mtmr0x/bud
I need to test out a couple of things, but if you download the repo and run with shadow npx shadow-cljs watch app, it runs the example file. I strongly believe we should have alternatives to React that focus on simplicity and high performance when updating the DOM. I will continue development and try to transform this first version into something robust (yet keeping the minialistic aspect of it)
I know this is probably most appropriate in the announcements channel, and I will do it later this week, but since this thread inspired me to finally get to work, I posted here. So I'm sorry for the noise, and hopefully this is something that can add positively to the discussion
If you need a client-side app (which strongly depends on how much interactivity you want), I've had fun with https://github.com/cjohansen/replicant. There's a recent video from the author introducing the library: https://www.youtube.com/watch?v=AGTDfXKGvNI
IMHO SSR is as viable as ever, but it's not going to be reflected in web dev discussions, because the requirements haven't changed much. I used to work on caribou, which is no longer maintained so I can't recommend it. hiccup is a good server side templating library. there are various routing libraries but I'm not sure which is best right now, if you start with compojure, anything else should be an easy transition if you grow out of it in general, the clojure ecosystem encourages composition of small single purpose tools, so your best bet is likely to refine your requirements and find the clojure libraries that are the closest fit
the lingua-franca on the server side tends to be that the HTTP request server is a function, the request handlers for each page are functions, and the router takes a set of paths and functions to return a function dispatching for each request. typically each "feature" (eg. database access, remote APIs) is written as a function that takes a request handler and returns a new request handler which gets the functionality added as special args alongside the request.
so (defn login-handler [{:keys [db request]}] ... (some code that returns html))
then (defn wrap-db [handler auth] (fn new-handler [request] (ensure-auth auth request (handler request))))
then (def routing-function (mk-router {"/login" (wrap-db login-handler)) ... ...})
then (def server (mk-server {:router routing-function ... ...}))
(with details that didn't fit cleanly, like passing a function to query the db as a new key on the request object in wrap-db...)
another thing you will see commonly is a state management lib (handles things like wiring up each service with the creds apropriate to that env, initializing or cleanly shutting down stateful objects...). component is a popular library for this but there are multiple options
if you want a slimmer frontend, I know there are front-end projects with that orientation, but I think it's best to ask CSS or JS communities about them, I don't think clojure would play much role on that side
For relatively simple interactivity on the frontend, I'd probably start with https://code.thheller.com/blog/shadow-cljs/2023/07/13/the-lost-arts-of-cljs-frontend.html. The next two articles in the blog expand on the idea.
There's always HTMX for "some" interactivity on the client. Biff is a full stack of libraries and tools that provides a "batteries included" web setup, using HTMX, for solo devs https://biffweb.com/ and #biff (but it may be overkill for what you want).
I looked at Biff tutorial but I don't know if its unfamiliarity, but i felt a lot of complexity thrown at once, like a new DB, e-mail and authentication, but I've not looked at a minimal example if I can ignore those parts.
Yeah, overkill for beginners I think. But I was mostly pointing at it as something that uses HTMX by default.
I keep meaning to update https://github.com/seancorfield/usermanager-example to have an HTMX variant.
For simple interactivity something like HTMX or Datastar will do. I've heard some people use Hotwire Turbo as well (which I think is similar in spirit and what Rails uses).
To answer the mail about "faster and easier iteration of development of a web app (mainly CRUD)"... you will have REPLs for on-the-fly changes and hot reloading of the client JavaScript if you want it, no matter which client-side libraries you use or how dominant they are in your application architecture. Of course, the server and client are distinct programs (although they can conveniently share a src directory and even *.cljc portable source code files). Iteration can be slower when you have to change both programs. Therefore, especially if you're just getting started and have no better plan, you might as well maximize whichever side, client or server, you expect to iterate more often. (Which will be the client side, right? Because how many ways can a server CRUD a data record?)
@p-himik thanks, that was an enlightening post series, felt like I really understood what is happening behind all the abstractions, even if not purely functional felt simpler