I have a question about how to write isomorphic web apps in Clojure. I want to make sure I start with a fairly well-fitting stack so I don’t end up in the situation I’m in with my big Angular app, 30kloc without a centralized state management solution. What I’d like is a system by which I write the majority of my app in CLJC files, so that if a user is using a browser that supports JavaScript, they’re served an SPA (PWA) with offline capabilities, but if they want, they can turn off JS and still get served a functioning website. I have extensive experience making complex mobile PWAs in Angular/Ionic and know Clojure, but have little experience with a complex web stack, so guidance and explanation would be greatly appreciated. I’ve read and worked through Yogthos’s book on Web Dev in Clojure, but that stack relies on a lot of REST norms and assumes relational databases. Because this is a new project, I’d really like this to be pure Clojure with a Datomic database as a back-end. Or, if it’s simpler, something like it. I like simple and composable things I can learn in parts, abstract complexity, then forget about implementation details. Ideally the data model would be isomorphic on the server and client, and normalized.
The scope of the project is a kind of academic note-taking system that will eventually work offline. It’s kind of like how Datomic works with facts, but for writing academic nonfiction. (Think of a zettelkasten that a 12 year old could use.)
From what I understand, a way to do this would be to use Rum and DataScript to build a front end in an SPA. Rum works server-side so this shouldn’t be a problem. Would I still use DataScript, writing the client as I would assuming it were being served as an SPA, but would just be rendered server side and served as static files? I assume that means some more interactive elements don’t work. Or do I use a kind of reader conditional for my components, writing their structure in Rum but conditionally calling different functions or transactions based on what interpreter is doing the reading (client vs server side)? If that’s the case, then I assume I do something like read from the database in the server conditionals and read from DataScript in the client conditionals?
Is there a good guide to something like this, some repository I could work through? I need authentication and authorization, ideally in a way I don’t have to think a whole lot about (something like Devise & CanCanCan would be most welcome, which seems like Buddy). Any recommendations for resources or repositories I can look through would be most appreciated.
Also, is this whole Rum + cider + DataScript + SSR basically an IKEA version of Fulcro? Should I just be looking at that? I’m working through the Fulcro book right now, and feel at sea when I look at a lot of the code specifically, though I like the architectural decisions. (Plotting the UI as a state machine seems… hard to reason about or rapidly iterate. But again, I’m new at thinking that way.)
In terms of cutting things, I can give up the isomorphism, but I’d be really nice if I didn’t have to. I saw this thread (When is it best NOT to do a [reagent] SPA?) which discussed building out the basic functionality of the site using a traditional multi-page application while still using Rum components, then slowly building it into an SPA with reader conditionals. I like that as a model.
Any guidance is much appreciated, including the advice that I’m way overthinking this and should just start with Rum and cider and DataScript and consider Fulcro when I start feeling pressure, or just dive into Fulcro more. I am unsure of myself in Clojure, so people with experience are my lantern in the dark.