Fork me on GitHub

Hi! I am trying to figure out how to use Calva with a fresh duct +cljs project. Is there somewhere I can read about how to set things up to use Cider with duct +cljs? That would help me figure the Calva options out, I think.


It’s been a while, but should just work with Cider, unless Cider has changed things around. The +cljs option should add a piggyback dependency.


Oh, actually, I think I remember this now. Cider did change some things around. Let me see if I can find the workaround.


I think you can add to your .dir-locals.el something like:

  (cider-custom-cljs-repl-init-form . "(do (dev) (cljs-repl))"
  (cider-default-cljs-repl . custom))


Thanks! Let me try that.


It’s actually something that needs to be added back to the .dir-locals.el template. I seem to remember I had to remove the auto-integration of cljs when Cider changed.


Now I get this:

Execution error (AssertionError) at duct.server.figwheel/start-piggieback-repl (figwheel.clj:124).
Assert failed: (some? build)


(Not using CIder here, trying it at the REPL directly.)


Oh! The server has to be started. I forgot that.


(do (dev) (go) (cljs-repl))


Getting closer! 😃 Getting a 404 in the browser...


I might not have set up routes and stuff. Just created this with lein new


Oh yeah, you need some routes. If you use the +example as well as +site +cljs it should work.


I did: lein new duct duct-cljs +site +example +cljs


And now accessed /example and am up and running with my cljs repl and all. 😃

🎉 4

Let me know if the Cider options work


But that’s good news 🙂


I'm using Calva. Want to write a guide how to get it going with Duct, much like this one, for Luminus:

💯 4

To get it that streamlined, I would need to provide some Calva settings with the Duct template. Would you consider accepting such a PR?


Yes - though add them to the “lein-ring” plugin, as that’s the one that adds locals outside source control.


OK. will do.


So these are the settings I'd like to provide together with a fresh lein new duct +cljs project.

    "calva.replConnectSequences": [
            "name": "Server only",
            "projectType": "Leiningen",
            "afterCLJReplJackInCode": "(do (dev) (go))",
            "cljsType": "none"
            "name": "Server + Client",
            "projectType": "Leiningen",
            "cljsType": {
                "dependsOn": "lein-figwheel",
                "connectCode": "(do (dev) (go) (println \"Server started\") (cljs-repl))",
                "isReadyToStartRegExp": "Server started",
                "printThisLineRegExp": ":duct.server.http.jetty/starting-server"


Doesn't seem to fit in lein-ring, but I am completely new to this so I might misunderstand something.


What the settings achieve is to make Calva jack-in prompt the user for starting the server only or the sever + client. If server + client is selected, it will make calva spawn the cljs-repl.


Oh, sorry, not lein-ring. I meant lein-duct.


The lein-duct plugin is for local templates out of source control.


It’s in the Duct repository.


Right now all my attempts end complaints about :cljs-build lacking in project.clj.


I personally would just use Duct for server side, and a separate CLJS frontend with shadow-cljs. Not sure how to have it inside of Duct. I know someone had recently created a shadow-cljs module though


One advantage to using cljs with Duct rather than a separate project is that your frontend is always in sync with your backend.


That's true. I'm not saying it's a bad thing. It's just not my preferred method. I personally like being able to iterate over my frontend without having to deploy the backend as well, since most of my work ends up there anyway


You can have the best of both worlds here. It’s trivial to support multiple workflows in the same repo; including ones that run the front end components independently from your backend etc. Also it makes building isomorphic apps with server side rendering totally possible. We have our shadow-cljs front end in the same source tree as our backend duct which makes integration testing a million times easier; and ensures that features that touch both the backend and frontend can be reviewed together.


You mean a mono repo?


no I mean a single application repo. If the backend and frontend are the same application, and a front end feature requires a backend change etc put them together.


otherwise you’ll spend forever version bumping / commit locking etc.


I’ve done the later too; and it’s not fun.


e.g. if you’re not careful every time anyone changes branches or merges master they’ll be forgetting to also fetch the new backend; and running into issues that are hard to recreate.


and each PR for new features will be two or more PRs that need to be linked together


so you’ll be using lein checkouts a lot; or tools.deps classpath overrides — which are easy to make mistakes with.


Sorry I think I'm misunderstanding something. Why would you have to use lein checkouts if frontend and backend are separate?


well it depends entirely on what you’re doing and your architecture — if your front end is purely an spa or whether it includes some server side html; and whether you think that’s backend or frontend. Either way the important problem is that you need to tie the front end and backend versions together somehow, and verify them as working together; and try and avoid issues with version mismatches etc. There are literally a million ways to do that; what I was assuming you were doing was having your backend (clj http server) include your front end project as a dependency, and serve it off the resource path for example. Or you could do it the other way round…


Ahhh ok. No the backend is just purely and API, and the frontend is completely separate, and communicates with it through the API


They don't actually have context of eachother


so how do you tie the versions together?


The backend just has a v1 endpoint, which should always be backwards compatible


They have separate project.clj versions


> should always In my experience this is rarely the case; least of all for intermediate WIP, feature branch releases etc


but you will end up in situations where the front end feature requires a backend bug fix that hasn’t been merged yet etc.


If it isn't then you introduced a bug, and it shouldn't have gone past the staging environment


Currently at my work we use a mono repo, which is a single git repo containing both the frontend and backend as separate project. So you keep them in sync that way (you have to deploy both)


But I'm not a very huge fan of that method


ok sorry I misread separate project as being separate repo too — not separate project in the same repo. There’s a spectrum of options here.


I’m not a big fan of mono-repos either. I’m a fan of carving your repos / projects across the right seams to minimise problems with coordinating changes/releases, and balancing other concerns too — e.g. licensing.


Splitting by layer though is usually a mistake in my book. I prefer to split applications by feature.




I should clarify; it’s a mistake if you don’t have a good reason. Scaling is usually the one people one cite; which I think is fair, if and only if you can’t make splitting vertically scale.