
Fulcro Developers Guide: Single-page full-stack web applications in clj/cljs - ghosthamlet
http://book.fulcrologic.com/
======
manishsharan
Should I be using a Modern do-it-all frameworks for Clojure and Clojurescript?
My opinion is of course colored by my years spent in JAVA/J2EE's world of web
frameworks ( Wicket, Tapestry, JSF + Hibernate EJBs etc.). In this world, I
found most of my time was spent in learning the deep intricacies of the
framework and fitting it to my use case. I began to hate every minute I spent
on these frameworks.

And then I discovered Clojure and Ring and later Liberator. What I like about
my current setup is that I have full control over my framework and my team
knows its ins and outs and the corresponding Clojure code is succinct enough
to allow developers to come upto speed quickly. Our set up is not sexy but it
works and we know how exactly it works.

I am not sure what I would miss if I did not use a framework like this. Is
Liberator no longer good enough ?

~~~
jwr
My take is that frameworks are great when you are building new projects, but
become somewhat limiting over time. Also, with a complex application you often
find that not everything can be nicely abstracted and there are features which
cut across the stack, requiring changes everywhere.

In my fairly large Clojure+ClojureScript app I do not use a framework, mostly
because nothing existed when I started. I pick libraries and make them work
together. This has advantages, but also brings endless frustration when I have
to deal with stuff like web authentication, file uploads, or Oauth2. I really
wish there were good solutions for these kinds of generic problems.

Also, not all choices made by the framework are necessarily a good fit for
every application size. I used to like Reagent, and I still think it's great
for learning. But then it became limiting, I switched to Rum and never looked
back.

But in general, why not take the Clojure approach and use the right tool for
the right thing? You don't have to chain yourself for life to a framework, you
can use a framework for one app and use a bunch of separate libraries in
another. I think in the Java world there is so much incidental complexity,
that you have to choose a single framework and stick with it, as it's likely
the only thing you will be able to learn. Not so in the Clojure world.

~~~
blunte
The huge reason I'm not using Clojure for webdev is because there is rarely an
accurate, current guide that demonstrates how to plug things together to get a
typical CRUD+user auth website going.

I know that everything I need already exists, but I have yet to find a
complete tutorial (Rails Depot, for example) that actually works. There's
always some gap that isn't explained or some step that fails because the guide
is 2+ years old.

So while I do agree that choosing your own libraries (and essentially building
your own custom framework, because that's what they all end up as) is
preferable long term, it is incredibly frustrating trying to build that first
webapp.

------
mark_l_watson
Really good work. I spent 15 minutes reading through this book over my first
cup of coffee this morning.

I stopped using Clojure about 5 years ago, after two long consulting jobs
using Clojure. I decided Clojure was not a perfect fit for me (and, really,
neither is Common Lisp, Racket, and Haskell - more favorite languages) but I
am very happy to see the Clojure ecosystem still creating such great tools
around the language and functional composition.

~~~
jdhorwitz
What have you found is the perfect fit for you?

~~~
mark_l_watson
Nothing. I use Python for deep learning but don’t care for the language. I
prefer Lisp languages, most comfortable with Common Lisp but love the
ecosystem around Racket. Love Haskell but I am in a many year learning curve.

~~~
rlander
No love for Pharo? ;)

~~~
mark_l_watson
I play with Pharo about once a month. Love but no real amount of time spent
with it anymore. Good language and platform, very energetic community but it
is a small community.

~~~
rlander
Same here. It's been on my "someday I´ll use it on a real project" list for
10-ish years. From time to time I boot an image, play around, cry a little,
get back to Python.

------
azeirah
> All of the full stack examples use a mock server embedded in the browser to
> simulate the interaction, but the source that you’ll read for the
> application is identical to what you’d write for a real server.

God, I'm loving this already. The only other framework I know that could do
this for a book is Meteor.

~~~
chrisweekly
Yeah, the Meteor book was incredibly well-done. Also agreed, this looks
similarly excellent.

------
chrstphrhrt
Would anyone recommend Clojure if you run an engineering org and get to make
decisions about languages?

I've been running node shops for the last several years, and love Clojure
since having hosted a couple meetups a while back.

That and being most influenced by lispy/ai culture from SICP, CTM, PAIP, AIMA
books. Node is getting tiresome due to not being able to trust the ecosystem
quality (which takes away some of the common justification of huge ecosystem).

Not worried about hiring since not open to fresh grads from universities or
bootcamps without lots of training anyway (which can include a new lang). Are
there crappy/charlatan Clojure devs out there or is it more of an
elite/experienced culture?

With stuff like Fulcro, could we replace our basic REST APIs and business
logic without having to re-invent too much?

~~~
sansnomme
The main issue with using Clojure is that you are expected to build everything
out yourself. A lot of dependencies tend to stop being maintained after a
while. Auth systems etc. are half-baked with 10 different implementations on
GitHub. The newer shinier ones lack in features while the more featureful ones
are from 3 years ago and have not seen a single update since. Now lisp people
like to say "but...but.. backwards compatibility!" Sure that works for a lot
of things but it goes out of the window when you need to prototype something
quickly and your intern using Django/Rails has already built a MVP while you
are still trying to sort out your dependencies story. Now you can always pull
in Java libs, but then you will spend the rest of the week writing a wrapper
for a very tiny subset of features that only you would use and the next person
that comes along will have to do the same thing for the subset of features
that they use.

Using Clojure (other Lisps have it way worse than Clojure so they are not even
worth mentioning in an enterprise context) is a bit like using an extremely
new cutting edge language like Rust or Nim where there's no high quality
libraries for anything except the lowest common denominator but without the
massive community and support. Yes Node has its issues. But at the end of the
day, you still need to get things shipped. Elegant code that would look at
home in SICP is useless when money is on the line and you can't ship. Clojure
et al. is very much NOT a "Move Fast and Ship" type of language. If it's for a
game jam where no one's using Unity and everyone's doing OpenGL or one of
those dinky little Lua game dev suites, sure go for it. If it's your company,
use Go and get things into production first.

Don't get me wrong, I love Clojure. There are a lot of smart people doing
interesting things with it. It's probably the most advanced of all Lisps in
terms of beginner-friendly tooling alone (shoutout to the Nightcode and
Parinfer authors!) and it's Java interop is tremendously powerful in the right
domain. Just that the ecosystem feels at times like Android 1.5 with its
terrible fragmentation problems. The main corporate sponsor behind the
language gives off apathetic vibes to community needs and the lack of
featureful, maintained libraries is covered up under the guise of "Big
frameworks bad! Elite programmers build their own!"

~~~
didibus
Don't write a wrapper when using a Java lib. Just use it directly. Now the
next person coming in just has to use it, no need to understand the wrapper
and extend it. Interop is a first class feature specifically for that reason.

For the rest, I can only say that I don't understand the sentiment. It's true
what you say about lots of Clojure libs, they were one off projects from
someone and work has stopped on them. But I am able to move fast and ship with
Clojure. For me, I can actually move faster with it. That's one of my main
reasons for liking it so much.

There's a Java lib for everything complex. And there's a quality Clojure lib
for everything common. I've never not found what I needed. And in general, I
don't need as many things because the core libs are so full featured.

I'm not trying to deny your experience. It just makes me curious how my
experience can be so different and almost opposite. That's why I've concluded
that it's just not for everyone. It seems you are either a FPer or you aren't.
And you are either a Lisper or you aren't. And with Clojure, you have to be
both a Lisper and a FPer.

~~~
sansnomme
It has less to do with FP or Lisp and more to do a lack of emphasis for rapid
development and a significant impedance mismatch with the rest of the
ecosystem. JVM interoperability works when the API is clean. It doesn't when
obscure OOP features are used three layers deep and have to be mapped into
Clojure which is more functional in nature.

------
mrcristisanjoe
If anyone is interested in working on a Fulcro application full-time we are
building tools for the insurance industry and are a remote-first team.

[http://bindhq.com/company/](http://bindhq.com/company/)

------
myguidingstar
Fulcro can be too sizable to consume in one bite, most importantly the three
core concepts (ident, query, state). Personally I find it useful to start with
just EQL which is an Clojure native alternate to Graphql. In fact, Fulcro's
predecessor, the famous Om.next was inspired by Graphql. Introduction by
Wilker Lucio
[https://www.youtube.com/watch?v=yyVKf2U8YVg](https://www.youtube.com/watch?v=yyVKf2U8YVg)

------
serpi
Somehow I got the feeling of there being a lot of boilerplate necessary to
create just about anything. Still this is years ahead of the competition
(excluding re-frame).

~~~
myguidingstar
Yeah, long require forms, long namespace keywords, protocol methods... but
they are all necessary so Fulcro can figure out a lot of things itself. It
pays off really well because things that are often hard in other frameworks
such as forms and server-client communication suddenly become easy as a
result.

------
adamfeldman
In addition to the book, Fulcro has excellent docs and resources available:

* Full-stack example [0], implementing the RealWorld spec using the Walkable SQL library and the Duct server-side framework

* Fulcro's implementation [1] of UI state machines (recent HN discussion on the topic [2])

* Fulcro training video series, from the creator Tony Kay [3]

* An answer to why Fulcro [4]

* How Fulcro differs from Om [5]

* Fulcro's integration with the Semantic UI React toolkit [6]

* Where Fulcro is headed next, in v3 [7]

To me Fulcro is Clojure's missing framework. With Fulcro (and thanks to
Clojure/Script), applications are composed and painted onto the screen -- this
is thanks to the REPL and hot-reloading that preserves state. For a
demonstration, see the Fulcro training playlist on YouTube [3].

Some personal favorite Fulcro features: (A) the built-in support viewer [8],
which can take state history serialized on the client and play it back on a
developer's machine (like a basic, self-hosted
[https://logrocket.com](https://logrocket.com)). (B) Workspaces [9], which is
similar to [https://storybook.js.org](https://storybook.js.org).

#fulcro is very active on the Clojurians Slack
[http://clojurians.net](http://clojurians.net) (or Zulip!
[https://clojureverse.org/t/introducing-clojurians-
zulip/3173](https://clojureverse.org/t/introducing-clojurians-zulip/3173))

[0]: [https://github.com/walkable-server/realworld-
fulcro](https://github.com/walkable-server/realworld-fulcro)

[1]: [https://github.com/fulcrologic/fulcro-
incubator/blob/develop...](https://github.com/fulcrologic/fulcro-
incubator/blob/develop/state-machine-docs.adoc)

[2]:
[https://news.ycombinator.com/item?id=19268734](https://news.ycombinator.com/item?id=19268734)

[3]:
[https://www.youtube.com/playlist?list=PLVi9lDx-4C_Rwb8LUwW4A...](https://www.youtube.com/playlist?list=PLVi9lDx-4C_Rwb8LUwW4AdjAu-39PHgEE)

[4]:
[http://fulcro.fulcrologic.com/benefits.html](http://fulcro.fulcrologic.com/benefits.html)

[5]: [http://fulcro.fulcrologic.com/vsom-
next.html](http://fulcro.fulcrologic.com/vsom-next.html)

[6]: [https://github.com/fulcrologic/semantic-ui-
wrapper](https://github.com/fulcrologic/semantic-ui-wrapper)

[7]:
[https://www.patreon.com/posts/fulcro-3-25683469](https://www.patreon.com/posts/fulcro-3-25683469),
[https://www.patreon.com/posts/incubator-23082756](https://www.patreon.com/posts/incubator-23082756)

[8]:
[http://book.fulcrologic.com/#_support_viewer](http://book.fulcrologic.com/#_support_viewer)

[9]:
[http://book.fulcrologic.com/#_workspaces](http://book.fulcrologic.com/#_workspaces)

------
lauritzsh
Does anyone have experience using Fulcro just for frontend (no backend)? I
have been considering it versus Reagent and Rum for building a heavy client-
side app that doesn't need a server (nothing to store in a database, local
storage is fine). At some point I might add users for data sync between client
and server but I don't plan to do SSR for SEO purposes at least.

What I am curious about is if I use Fulcro, will I write a lot more code to do
the same as in Reagent/Rum because it's supposed to play well with a backend
that's (for now) non-existent? Does it provide better tools for client-side
state management compared to Rum/Reagent (+ re-frame)?

Right now I am using just Rum with its built-in cursors and derived atoms and
the experience is okay. I did try DataScript but ended up just with a simple
atom for now.

~~~
adamfeldman
I think Fulcro would shine for your client-side state management use-case:
[http://book.fulcrologic.com/#_the_secret_sauce_normalizing_t...](http://book.fulcrologic.com/#_the_secret_sauce_normalizing_the_database)

Please also see the links from my reply elsewhere in this thread:
[https://news.ycombinator.com/item?id=19522998](https://news.ycombinator.com/item?id=19522998)

I am exploring using Fulcro remotes to persist data locally using
[https://github.com/replikativ/datahike](https://github.com/replikativ/datahike)
(and sync via
[https://github.com/replikativ/replikativ](https://github.com/replikativ/replikativ))

------
askosh
As an alternative, modern web framework for Clojure, I recommend Coast
[https://coastonclojure.com/](https://coastonclojure.com/) (I have no other
affiliation to this project other than using it myself).

~~~
myguidingstar
Coast is a framework that focus on traditional server app and rapid
development similar to Rails or Django. I don't find it "modern" tbh.

------
victor106
Can someone here elaborate what are some advantages of using fulcro vs using
another stack?

~~~
slifin
Time travelling immutable universal databases are their own reward, lol

[http://www.hyperfiddle.net/](http://www.hyperfiddle.net/) is probably the
closest proof of concept I know of right now, some interesting properties are
solved N query problem with smart and pinpoint caching, infinite TTL caches,
SQL injection impossible, client exposable query language

Aggregate shapes defined at query time, not at insert time, it's mostly about
moving immutable Datoms around not trees that are hard to reconfigure & reuse
like nested JSON

I'd suggest looking into the feature set of Datomic, and then ask yourself
what would happen if you ran with those concepts in the front end? - Fulcro

------
G4BB3R
Clojure is awesome. But refactoring a big project without a type system is
very hard and error-prone, and clojure error messages are very difficult to
understand.

~~~
harperlee
In my experience the new spec system (a sort of gradual typing) greatly helps
in both refactoring and both surfacing and explaining errors, if you havent
worked with clojure 1.10 I’d recommend to give it another go.

Also spec is still in alpha so it will keep getting better.

~~~
dkersten
Honest question (as I've been out of the Clojure world for a little bit):
which refactoring tools integrate with or use spec?

~~~
harperlee
Look at [https://github.com/clojure-emacs/clj-
refactor.el](https://github.com/clojure-emacs/clj-refactor.el)

~~~
dkersten
Thank you!

