Should there be a client-server interaction-adapter API in Elixir?

I was reading through this topic: Nex - A minimalist web framework for indie hackers and startups and I love minimalist web stuff and the “traditional” page-based web of yore, but I also have never liked opinionated frameworks. I always like the pitch, but every time I use one, it makes me sad when I try to write code the way I want and it doesn’t work. I have always stuck with Flask/Quart in Python because it gives all of the difficult-to-implement functionality of a web app, but it doesn’t try to build the legos ahead of time. I’m not limited by however the framework wants the pieces to fit together. It takes care of the hard parts, and I get to just do what I enjoy which is design code that is fun for me personally to work with.

That’s what I love about Phoenix as well. It felt heavy and opinionated at first with the generated code, but after learning it more, I realized I could structure things however I wanted by straying from the defaults.

This message in the linked topic brings up an interesting idea related to all that Nex - A minimalist web framework for indie hackers and startups - #28 by thiagomajesk LiveView as a generic client-server interaction engine.

I’m not sure how feasible it would be to decouple LiveView from Phoenix, but I normally build LiveView-like websockets in my Python apps, and I think it’s feasible to have something that achieves the same things as LiveView as a standalone library.

Carrying on with that idea and my love for frameworks that provide the tools to build the legos myself instead of providing the legos out of the box, I think generalizing the idea of a client-server interaction library might be an interesting thing to explore.

My thinking is that the modern web has been mostly dominated by SPA frameworks, but there’s also been a lot of work going on with the Hypermedia stuff to try to reduce the bloat of the web somewhat. All of these things are basically just different models of client-server interaction. FE-first reactive frameworks use a request-response model for creating a more stateful user experience. Realtime frameworks like LiveView try to accomplish a similar experience with a stateful connection and the ability to push from the server instead of having everything driven by the client.

I think there must be an abstraction hiding here somewhere. Maybe rather than thinking about things in terms of SPA/realtime/hypermedia, we could find a way to abstract pushing/pulling in a bi-directional model. Then we can use that same abstraction on both the client and the server and it doesn’t matter how the actual connection is implemented. This has the advantage that it also works for server-server interactions in a service architecture.

Assuming something like Plug could be implemented for this client-server push/pull interaction abstraction, then the choice of LiveView or HTMX or whatever would be a user decision and not something the framework author needs to decide up front. It would also simplify fallback/failover scenarios when things like websockets or SSE fail in realtime apps. Making it easier to implement both stateful connections with websockets or HTTP2/3 and also stateless connections with the same interface would be super helpful both from a productivity perspective (single mental model for building different kinds of apps) and from a quality perspective (fallback/failover for different networking implementations).

Thoughts?

1 Like

I think you will find there is little in the way of a shared abstraction to be had between React-likes (incl. LiveView) and HTMX-likes.

The purpose of the React-likes is to enable a declarative programming style, i.e. a style in which you rebuild the application’s entire derived state from scratch on each render. You can do this without React, but React’s engine is a tool for making this efficient through incrementalization as it otherwise does not scale very well.

I have not used HTMX but it seems to encourage an imperative style. Ironically a full HTML pageload is as declarative as can be, and it’s only by patching parts of the page that you violate that principle. It is exactly this idea of “patching parts of the page” that led to disaster 20 years ago, and it is exactly those disasters which precipitated the rise of React.

LiveView is a stateful React-like on the server, but it does not provide very good tools for declarative programming. In fairness, neither did React in the beginning; it took them many years to figure out what worked and what didn’t. I do worry that the confusion will lead to a self-fulfilling prophecy, where those using LiveView aren’t really aware of what React-likes are for and are just writing imperative code. Which means that there is no pressure for LiveView to “grow up” in the way that React did and develop into a full UI runtime.

There is an abstraction lurking, but I think that abstraction really is just LiveView or something similar. I don’t think the HTMX-likes factor into the picture at all as their own fundamental abstraction is literally just “HTTP request”. There is probably room for something shaped like “React on the server” to be factored out, and I would point to attempts to use LiveView to render native apps as an example of that.