Fork me on GitHub
#clojurescript
<
2023-07-21
>
joakimen14:07:56

Hey there! I'm a backend/infra dev with lousy webdev skills who's looking for recommendations on how to develop simple but robust and professional web apps using Clojure(Script). I'm somewhat familiar with Clojure; I know how to consume APIs and work with data, but I don't really know how to visualize things. Background • I've dabbled superficially with stuff like shadow-cljs, ring, compojure, reitit and muuntaja, as well as Luminus (which went way over my head at the time) • I've completed Jacek Schae's free course in Reagent, https://www.jacekschae.com/learn-reagent-free, to get a feel of what Reagent is all about (I have practically zero experience with React) Example use case: live-updating dashboard 1. Query data sources (e.g. database or API) 2. Visualize the data as html, with some styling 3. Keep polling data sources for changes and live-update the data in the browser I'm looking for: simple, maintainable, reactive, modern but reliable I'm not looking for: unreliable, magical, CSS fiddling, bells and whistles In other words, I want to learn how to create something that is reliable and looks fairly pretty. I don't know how the different tools in the landscape relate to each other, so I'm not sure which tools to adopt and spend my time learning. What are your recommendations for approaching web dev in ClojureScript in 2023? I'm open to paying for courses and material. Thanks in advance

joakimen14:07:23

Can also take recommendations in DM if people feel more comfortable recommending specific things there. 🙂

afry14:07:50

Sounds like what you might need is a course in web design? Or maybe some pointers to toolkits? The "data" piece of your question (querying APIs, streaming data, etc.) is definitely clojurescript specific stuff, but most of what you're asking about is more in the realm of HTML and CSS and design, so I might focus there. I've picked up my design chops on the job, so I can't recommend a design course unfortunately, but here are a couple suggestions for CSS frameworks to get into: • If you want a batteries included CSS framework, hard to go wrong with Bootstrap. For interactive components, Bootstrap leans a lot on jquery, which could be ok depending on what level of control you need or want over things like modals and stuff, but could get tricky if you want to mix cljs and jquery: https://getbootstrap.com/ • If you want a library that is more fiddly than Bootstrap but gives you a lot more customization options and lets you do your styling entirely in the HTML/Hiccup part of your app, Tailwind is great. Since you'll probably be coding your markup in Hiccup anyway, all of the great string and list manipulation stuff from clojure could be useful for composing class strings together for components: https://tailwindcss.com/ • For charts, the big beefy fiddly go-to library would be D3, but something like Chart.js would be the easier batteries-included library for something that you don't need to customize very much https://www.chartjs.org/

alpox15:07:02

For getting into HTML/CSS from the ground up I can suggest freeCodeCamp https://www.freecodecamp.org/learn/2022/responsive-web-design/

joakimen15:07:09

> Sounds like what you might need is a course in web design? Or maybe some pointers to toolkits? Yes and yes 😄 I've worked a bit with webdev, but that was the pre-2010 jQuery days, so I feel a bit like a dinosaur. I've used Bootstrap some, and considered getting into Tailwind, but I am more curious how this all comes together in the ClojureScript world, with all the bundling, transpiling and other buzzwords from that landscape. As for your second question, I am more curious about what a mature CLJS-stack would look like today, which is why I'm asking in this Slack - tutorials on CSS and JS are everywhere, but how this comes together in the Clojure-world is harder to find good info on. I'll write down your CSS-tips though!

afry15:07:18

Ah, in that case I'd definitely focus on shadow-cljs. The cljs world has pretty much convened on it as the way to work with NPM packages and JS libraries, integrate them into your cljs code, do interop, etc. It also comes with some nice development and build utilities, so you don't need to worry about adding on any extra transpiling/bundling/building tools. So that will give you a way to integrate exterior JS libraries so you're not writing anything from scratch, will give you a way to develop with a REPL and hot static asset reloading, and a way to build everything so that you can deploy it elsewhere. I'd probably start with the barest-bones shadow-cljs starter kit. I and a lot of other people have a tough time getting comfortable with clojure tooling, so starting small and building up to something more involved works best for me. This one looks nice: https://github.com/lauritzsh/reagent-shadow-cljs-starter

mario-star 2
joakimen15:07:02

Sounds great! I've fiddled a bit with shadow-cljs before, and really liked it. It's just about all this other tooling; there are so many alternatives, and I don't know which to choose and why. E.g. Reagent/Reframe, Ring/Reitit, stuff like that. Playing around them, figuring out the strengths and shortcomings etc, takes time, so I wanted to hear what the community had arrived at, as a reliable stack for green-field projects in 2023 Obviously, there is no "best" tool or stack, but it should be possible to define some sort of "recommended default" stack for webapps, similar to how Spring did with Spring Boot

joakimen15:07:27

As well as how to actually solve real-world problems such as live-updates of views, which is where courses come in 🙂

afry15:07:19

Ha, yep, this is a common pain point in the Clojure world. It's a society of people who like to fiddle around and pick their own stack, which is awesome in a lot of respects, but also puts all of the burden on you to make the "basic" decisions that other languages and frameworks make for you. MY stack looks like this: http-kit and ring on the backend, reagent and shadow-cljs on the frontend. Maybe reframe if the app gets big enough to need it, but not before. Reitit if I need a frontend router, but not before. One thing I like to look out for in a library is whether or not you can write the code as "one big chain of functions". http-kit definitely fits the bill, Pedestal not so much (I dropped it once I got to the point of needing interceptors, which I didn't want to spend the time trying to grok: http://pedestal.io/guides/what-is-an-interceptor) I also look for an older, long-established library. You'll find more examples, documentation, slack posts, etc. That makes it a ton easier to figure out how to get up to speed.

joakimen15:07:22

Definitely agreed on the last bit, and just your recommendation right there (http-kit, ring, reagent, shadow-cljs) is very useful! I think having some recommended starter-guide that helps you assemble a toolkit for a given task might help in language adoption, but that's a topic for #C0CB40N8K. Thanks for taking the time for all these replies; I'll take your recommendation, and look into some Tailwind later on. 😄 Much appreciated, and have a great weekend!

afry15:07:40

No prob man! Good luck.

kennytilton07:07:31

In 2023? I am finding Flutter to be a saner target than HTML/CSS. CLJS itself rocks, but #C03A6GE8D32 (repo https://github.com/Tensegritics/ClojureDart#readme) rocks, too, and then we get desktop and mobile as well as Web. CLJD hides almost all the Dart OO unpleasantness. I would recommend my own https://github.com/kennytilton/flutter-mx, but you said "no magic". :rolling_on_the_floor_laughing: If that was not a hard constraint, I also did a pure HTML/CSS https://github.com/kennytilton/web-mx#readme. No React, which methinks too ornate/clumsy. Just HTML, CSS, and MX state management (the magic). Have fun!

joakimen10:07:34

I've seen Flutter and Dart/ClojureDart thrown around, but never considered them. Will give it a look, thanks for the recommendation!

kennytilton17:07:05

I was triggered by your qualifier, "...in 2023" because I have been thinking for a while Flutter answers the question, "What tool would we build today, knowing that we want to deploy rich applications to the Web, not just documents." HTML is great, but it is a great Lego set. We also want more than just the Web -- mobile, IoT, and even the ye olde desktop -- so in 2023 we would strive for sth target-agnostic. The one thing we would not do in 2023 is build this tool atop a statically-typed OO language sigh, but...ClojureDart! Btw, I also get a kick out of them throwing away all their low-level Skia rendering code and creating https://docs.flutter.dev/perf/impeller. That told me a lot about the team/intent behind Flutter. Let me know if you, or anyone, would like a couple hours of onboarding. f/mx has been used by one intrepid developer to deploy a production app, more would be fun.

Chase18:07:58

Here is a recent talk going over current CLJS trends and whatnot: https://www.youtube.com/watch?v=fT28NeZtaAg IMO, you have already stumbled on a "can't go wrong approach" with Reagent, Re-Frame, and Reitit. Jacek Shae has courses on all of that and I think Eric Normand still sells some stuff. There is a Web Development with Clojure book written by the same folks who did Luminus and Kit.

joakimen11:07:57

Finally got around to watching this video 😁 This thread and that video has really helped narrow down the alternatives for helping me choose a toolkit, so again, thank you all so much. Gonna get my feet wet now, might poke back again with questions at some point! 🙇

DeepReef1118:07:36

I have the following object in typescript:

{
        key: `agenda-${slot}`,
        slot,
        reset: true,
        template: `<div id="${id}"></div>`,
        // style: {},
      }
Slot is just a string. How can I translate that in clojurescript? I don't understand why there's a string within an object. Feels like I'm missing something. Here's what I got:
(clj->js {
                                                                            :key (str "agenda-" slot)
                                                                            ;; missing slot
                                                                            :reset true
                                                                            :template (element :other (str "id=\"" id "\""))
                                                                            })

thheller18:07:13

slot, in JS is just short for writing slot: slot,, so :slot slot in CLJS

DeepReef1118:07:19

So if I had var mystring and did { mystring } I would get { mystring: "content of mystring" } ?

thheller18:07:44

correct

2
DeepReef1118:07:04

Great, thanks a lot!