I'm in the same camp, I've slowly "regressed" backwards from overcomplicated SPA's back to server side rendering. When LiveView hit and I was already using Phoenix it was just perfect. It's a slight embelishment on top of multi-page server rendered pages which gives all the benefits I need and nothing more.
If I _really_ need something to be driven by the frontend like a transition then I'll use Alpine.js.
For CSS I tend to use tailwindcss / tailwindui because I know it well and it doens't need npm. If I didn't know tailwind I'd probably look at something like bootstrap or something I can build on top of with vanilla css.
How do you deal with more complex/dynamic forms? As someone who learnt frontend mostly in React I've always struggled wrapping my head around how you would do that with server-side rendering.
For example:
1) selecting a checkbox alters other fields in the form
2) validation that needs to hit the backend and then present warnings/errors to user
3) field arrays -> sending back a list of fields
LiveView can handle that pretty well, you can setup a click or validation handler for your live view / component. It then hits the handler function on the backend and you can have the component updated in place. Since it only sends the diffs down it's pretty efficient on the round trip, at least not something to worry about compared to the hundreds of api calls most SPA's will make.
So the flow is 1) click the checkbox 2) call sent across the open socket 3) backend does it's logic to figure out what it needs to do 4) backend returns the small diff of changes 5) frontend alters dom.
Its actually recommended with Liveview for pure client side stuff (hiding form elements, etc.) to do that in the client. There are hooks to do such things. Granted I've only built admin-y tools that are pure liveview but did hear/read there are options for client side JS.
Just because it can be done 100% server side doesn't mean it should be, especially if its driven out of a "look, no JS!" type of approach.
If I _really_ need something to be driven by the frontend like a transition then I'll use Alpine.js.
For CSS I tend to use tailwindcss / tailwindui because I know it well and it doens't need npm. If I didn't know tailwind I'd probably look at something like bootstrap or something I can build on top of with vanilla css.