572 comments

[ 3.7 ms ] story [ 159 ms ] thread
Without reading the details, LiveView in Phoenix (Elixir) sends HTML/DOM updates only. Hotwire sounds pretty similar (and it's a good thing IMO)
I won't say this is a step backwards in terms of progress but it is a step back to the way things used to be done in the early days of Ajax - albeit with a slightly more modern approach.

It is appropriate for some applications and not for others. That's just my view.

I'm not really a web dev, though I've built a couple small (mostly static) sites.

Could you expand a bit on what makes it appropriate or not for different applications?

What's old is new again. I recall ASP.NET had some interesting tech around this in the 2000s where it could dynamically update parts of the page.

If I recall correctly, this made use of that new technology of the time called "XMLHttpRequest" (/s) which pretty much jump-started web 2.0.

AjaxContentPanels or something to that effect. Those things were a nightmare. At the time, asp.net pretended to be stateful by bundling up the entire state of the page into "ViewState" and passing it back and forth client to server. Getting that to work with those panels was more work than just ajax-ing the content and injecting it with jquery.

In the Microsoft-verse, this might also draw some comparisons to the more modern server-side blazor.

Oh yeah. I remember that ViewState could reach 100s of KBs on a page if you weren't careful. It was a huge juggling act between keeping state in your input fields vs ViewState.
My thought exactly, though I fully support that. I often rant about how the modern web is billions of layers of duck tape over duck tape and it has become an unmanageable mess of libraries, frameworks, resources, all while javascript remains the most outrageous and absurd language ever created. I'm by no means a fan of rails or ruby for that matter but I think things like these are a considerably better alternative than all the ridiculous libraries and frameworks everyone uses, which result megabytes of javascript and require corporate-grade bandwidth and at least an 8-th gen i7 and at least 8gb of memory to open. And all that to open a website which has 3 images and a contact form. I mean someone should create a package that analyzes websites and creates a minimum requirements manifest. It's good to see that there are people who are trying to bring some sanity.
Preach! Websites don’t seem all that much better to me than they did 10 years ago [^fn], so what are we gaining with all these much more complex and fragile tools?

[fn]: Arguably, the web is worse with chat bots, sticky headers, and modals constantly vying for your attention.

> Arguably, the web is worse with chat bots, sticky headers, and modals constantly vying for your attention.

We can blame this on the MBA types. I've literally never heard a software engineer say "hey, let's make this pop-up after they've already been looking at the page for a minute!" or anything like it.

Engineers typically aren’t tasked with increasing revenue/engagement.
Unfortunately I have to disagree - if there weren't any engineers around to implement the dark patterns they wouldn't be as prevalent. Maybe this calls for an equivalent of the Hippocratic Oath but in the tech world?
Brick layers. Developers develop, designers design was more my point, though of course this line is blurred in many organisations.
There is plenty of duck tape yes,

But there is suprisingly little layers on layers. Part of what has been amazing about the web is that the target remains the same. There is the DOM. Everyone is trying different ways to build & update the DOM.

Agreed that there are better alternatives than a lot of what is out there. We seem to be in a mass consolidation, focusing around a couple very popular systems. I am glad to see folks like Github presenting some of the better alternatives, such as their Catalyst tools[1] which speed up (developer-wise & page-wise (via "Actions") both) & give some patterns for building WebComponents.

The web has been unimaginably stable a platform for building things, has retained it's spirit while allowing hundreds of different architectures for how things get built. Yes, we can make a mess of our architectures. Yes, humanity can over-consume resources. But we can also, often, do it right, and we can learn & evolve, as we have done so, over the past 30 years we've had with the web.

[1] https://github.github.io/catalyst/

If by surprisingly little, you mean 4 pages and 500mb of requirements for a "hello world" project with the "modern" web, then yes. The DOM has always been a mess, much like javascript. And the fact that no one has tried to do something about it contributes to the mountains of duckt tape. It was bad enough when angular showed up, but when all the other mumbo jumbo showed up like react, vue, webpack and whatnot is when it all went south. I refuse to offend compilers and call this "compiling", but the fact that npm takes the same amount of time to "compile" it's gibberish as rustc to compile a large project(with the painfully slow compilation that comes with rust by design), is a clear indication that something is utterly wrong.
Again, you are attributing to the web what a pop-culture is doing with it.

While willfully ignoring all the people doing better.

Maybe we are- as you fear- stuck, forever, in thick JS-to-JS transpilers & massive bundles & heavy frameworks. Maybe. I don't think so.

npm does not compile, it is just a package manager. That said, I understand your frustration.
> If by surprisingly little, you mean 4 pages and 500mb of requirements for a "hello world" project with the "modern" web, then yes.

React is well under 20k.

FWIW when optimizing my SPA, my largest "oops" in regards to size were an unoptimized header image, and improperly specified web fonts.

There are some bloated Javascript libraries out there, yes. But if you dig into them you will often find that they are bloated because someone pulled in a bunch of binary (or SVG...) assets.

Ah react, the biggest crap of them all. A 12 year old with basic programming skills is definitely capable of designing a better "framework". Yes, everything frontend is quoted because it's nothing more than a joke at this point. Back to react, and ignoring all the underlying problems coming from the pile of crap that is js, let's kick things off with jsx. The fact that someone developed their own syntax(I'm not sure if I should call it syntax or markup or something else) makes it idiotic: It's another step added to the gibberish generation. It's full of esoteric patterns and life cycles which don't exist anywhere in the real cs world. React alone provides little to nothing so again you need to add another bucket of 1000 packages to make it work. Compare it to a solid backend framework that isn't js: all the ones I've ever used come with batteries included. The concept of components and the idiotic life cycles turn your codebase into an unmanageable pile of of callbacks and sooner rather than later you have no clue what's coming from where. Going into the size, the simple counter example on the react page is 400kb. Do I need to explain how much stuff can be packed in 400kb? For comparison, I had tetris on my i486 in the early 90's which was less than 100kb, chess was a little over 150kb. Christ, there was a post here on HN about a guy who packed a fully executable snake game into a qr code.
> Ah react, the biggest crap of them all. A 12 year old with basic programming skills is definitely capable of designing a better "framework".

You're literally a stereotypical Hacker News commenter. I also find the modern frontend a bit too complicated but this is just an unreasonable statement.

You'd be right if I had not given arguments for my statement. I did as a matter of fact.
> let's kick things off with jsx.

Of all the problems I have with React, and I do have a few, JSX is not one of them.

If you are going to be using a language to generate HTML, you are either going with a component approach that wraps HTML in some object library that then spits out HTML, or you are stuck with a templating language of some sort. (Or string concatenation, but I refuse to consider that a valid choice for non-trivial use cases.)

JSX is a minimal templating language on top of HTML. Do I think effects are weird and am I very annoyed at how they are declaration order dependent? Yup. But the lifecycle stuff is not that weird, or at least the latest revision of it isn't (earlier editions... eh...). The idea of triggering an action when a page is done loading has been around for a very long time, and that maps rather well to JSX's lifecycle events.

> React alone provides little to nothing

Throw in a routing library, and you are pretty much done.

Now another issue I do have is that people think React optimizes things that it in fact does not, so components end up being re-rendered again and again. Throw Redux in there and it is easy to have 100ms latency per key press. Super easy to do, and avoiding that pitfall involves understanding quite a few topics, which is unfortunate. The default path shouldn't lead to bad performance.

> The concept of components and the idiotic life cycles

Page loads, network request is made. Before React people had listeners on DOM and Window events instead, no different.

Components are nice if kept short and sweet. "This bit of HTML shows an image and its description" is useful.

> Do I need to explain how much stuff can be packed in 400kb?

No, I've worked on embedded systems, I realize how much of a gigantic waste everything web is. But making tight and small React apps is perfectly possible.

And yes, if you pull in a giant UI component library things will balloon in size. It is a common beginner mistake, I made it myself when I first started out. Then I realized it is easier for me to just write whatever small set of components I need myself, and I dropped 60% of my bundle app size.

In comparison, doing shit on the backend involves:

1. Writing logic in one language that will generate HTML and Javascript 2. Debugging the HTML and Javascript generated in #1.

And then someone goes "hey you know what's a great idea? Let's put state on the back end again! And we'll wrap it up behind a bunch of abstractions so engineers can pretend it actually isn't on the back end!"

History repeats itself and all that.

SPAs exist for a reason. They are easier to develop and easier to think about. And like it or not, even trivial client side functionality, such as a date picker, requires Javascript (see: https://caniuse.com/input-datetime).

SPAs, once loaded, can be very fast and scaling the backend for an SPA is a much easier engineering task (not trivial, but easier than per user state).

Is all of web dev a dumpster fire? Of course it is. A 16 year old with VB6 back in 1999 was 10x more productive than the world's most amazing web front end developer now days. Give said 16yr old a copy of Access and they could replace 90% of modern day internally developed CRUD apps at a fraction of the cost. (Except mobile support and all that...)

But React isn't the source of the problem, or even a particularly bad bit of code.

jsx is a retarded idea because it adds an abstraction over something brutally simple(html). Abstractions are good when you are trying to make something complex user-friendly and simple.

> Throw in a routing library, and you are pretty much done.

Ok routing library, now make an http request please without involving more dependencies....

> Throw Redux in

See, exactly what I said: we are getting to the endless pages of dependencies.

> 100ms latency per key press

100ms latency??!?!?!? In my world 100ms are centuries.

> 1. Writing logic in one language that will generate HTML and Javascript 2. Debugging the HTML and Javascript generated in #1.

I don't have a problem with that. At the end of the day you know exactly what you want to achieve and what the output should be, whereas react it's a guessing game each time. We are at a point where web "developers" wouldn't be able to tell you what html is. With server-side rendering, from maintenance perspective you have the luxury to use grep and not rely on post-market add ons, plugins and ide's in order to find and change the class of a span.

The term SPA first came to my attention when I was in university over 10 years ago. My immediate thought was "this is retarded". Over a decade later, my opinion hasn't changed.

> jsx is a retarded idea

> My immediate thought was "this is retarded".

It's generally frowned upon to use retarded in this manner. Not only is it insulting to people, it brings down the overall tone of your argument.

> 100ms latency??!?!?!? In my world 100ms are centuries

Yup that's crappy. The ease of it happening, the Work At A Startup page used to have this issue (may still, haven't looked lately) shows that it isn't hard to make accidentally happen.

As I said, it is a weakness of the system.

> sx is a retarded idea because it adds an abstraction over something brutally simple(html)

Have you seen how minimal of an abstraction jsx is? It is a simple rewrite to a JS function that spits out HTML, but JSX is super nice to write and more grep-able than the majority of other templating systems.

I have a predisposition to not liking templating systems, but JSX is the best part of React.

Notably it doesn't invent it's own control flow language, unlike most competitors in this space.

> My immediate thought was "this is retarded".

Well the most famous SPA is gmail and it's rather popular, you may have heard of it. It is bloated now, but when it first debuted it was really good. Webmail sucked, then suddenly it didn't.

Google maps. Outlook web client. Pandora. Online chat rooms, In browser video chat, (now with cool positional sound!)

SPA just means you are just fetching the minimum needed data from the server to fulfill the user's request, instead of refetching the entire DOM.

They are inherently an optimization.

Non-SPAs can be slow bloated messes as well, e.g. the Expedia site.

appreciated your previous tweet but I am falling asleep here & none of your rebuttals feel like they address the topics raised in a genuine/direct fashion. so many stronger points to make against this
your posting is tribalistic & cruel & demeaning, it attacks and attacks and attacks. this is so hard to grapple with, so so aggressive & merciless & disrespectful. I beg you to reassess yourself. don't make people wade through such mudslinging. please. there's so few better ideas anywhere, & so much heaped up, so much muck you rake us take through. please don't keep doing this horrible negative thing. it's so unjust & so brutally harsh.

> jsx is a retarded idea because it adds an abstraction over something brutally simple(html).

what programming languages do it better?

one of reacts greatest boons, it's greatest innovations, in my mind, is that it gave up the cargo cult special purpose templating languages that we had for almost two decades assumed we needed. it brought the key sensibility of php to javascript: that there was no need, no gain, by treating html as something special. it should be dealt with in the language, in the code.

if you have other places that have done a good job of being ripe for building html directly, without intermediation, as you seem to be a proponent of, let me/us know. jax seems intimately closer to me to what you purport to ask for than almost any other language that has come before! your words are a vexing contradiction.

> Ok routing library, now make an http request please without involving more dependencies....

please stop being TERRIFIED of code. many routing libraries with dependencies aren tiny. stop panicking that there is code. react router v6 for example is 2.9kb. why so afraid bro?

this is actually why the web is good. because there are many many many problems, but they are decoupled and a 2kB library builds a wonderful magical consistent & complete happy environment that proposes a good way of tackling the issues. you have to bring some architecture in but anyone can invent that architecture, the web platform is in opinionated ("principle of least power" x10,000,000), and the solutions tend towards tiny.

redux is 2kB with dependencies as well.

stop deleting flagged posts!! we will never ever improve if you keep deleting antithesis!!!!!! bad arguments are necessary!
The only thing I'm openly disrespecting beyond the unholy mess that is the web of 21-st century, is react and potentially it's designers(I was raised not to be offended but if they are, good riddance). The web is in the worst shape it's ever been. I'm not terrified of code, I've been writing code for over 20 years. I hate antipatterns and spaghetti code, which is what the modern web is, top to bottom, frameworks and libraries included. The main idea behind javascript was to give small and basic interactivity which is entirely self-contained. Is it now? The fact that the modern web relies on tons of known and unknown projects, complex ci/cd pipelines and gigabytes of my hard drive is a clear indication that the js community messed it up. Very similar situation as php, which was intended to be a templating engine (and for that purpose it is brilliant) but just like js, it was turned into Frankenstein's monster(still to a lesser degree). And don't get me started on the endless security issues npm poses. I'm blown away by the fact that those are exploited so little - 15 year old me would have been in heaven if given those opportunities, along with half of my classmates. I seriously wonder what teenagers do these days.
Surely your point could be made better without the hyperbole?

"Most outrageous and absurd language ever," "Megabytes of javascript", "corporate-grade bandwidth", "8th-gen i7 and 8GB of memory" to open "3 images and a contact form."

I'm sure you can find one or two poorly-optimized sites that have 2MB of javascript to download, but it's by no means the necessary outcome of using "ridiculous libraries and frameworks," and not even a particularly common one.

> one or two poorly-optimized sites

Try every old media site and most e-commerce.

> it's by no means the necessary outcome of using "ridiculous libraries and frameworks," and not even a particularly common one

The real world disagrees with you; go check out any major website and observe as your laptop's fans spin up.

However I think the main problem here isn't the symptom (websites are bloated) but the root cause of the problem. I'm not sure if it's resume-driven-development by front-end developers or that they genuinely lost the skill of pure CSS & HTML but everyone seems to be pushing for React or some kind of SPA framework even when the entire website only needs a handful of pages with no dynamic content.

(comment deleted)
Just wanted to point out that it is called duct tape, just to avoid misunderstandings since i had a similiar spelling error as a non-native speaker :)
Interestingly, waterproof fabric-based tape was originally called "duck tape" (for its waterproof quality). The same kind of tape was later also called duct tape, but it's actually pretty terrible for ducts. You want to use the all-aluminum tape for ducts. https://www.mentalfloss.com/article/52151/it-duck-tape-or-du...
Oh wow, so there actually is something called Duck Tape. TIL
(comment deleted)
"Duck tape" originally referred to tape made from duck cloth. They started using it for duct work, and began to call it "duct tape", to the point where "duck" fell out of common use and was able to be trademarked. They've also stopped using it for ducts.

So call it either one and people will know what you're talking about.

Check out Gaff Tape as a replacement for the duct-tape at home use-case.

And for actual ducts you'll want to use foil-tape because temperature changes wreck the adhesion of duct-tape, then the moisture leaks into the walls/ceiling which is $$$$ bad.

> And for actual ducts you'll want to use foil-tape because temperature changes wreck the adhesion of duct-tape, then the moisture leaks into the walls/ceiling which is $$$$ bad.

This strongly depends on the type of duct. Flex ducts that are a plastic skin over a wire coil don't work so well with aluminum tape.

Oh, yes. I'm referring to rigid steel/tin works only.
I'm a native speaker.

I use alot of Duck Tape .

From the little language study I've done, English is one of the most flexible. You can discard entire parts of speak and it still works.

Saying , ,'ey you woke up yet', is ok in many contexts.

it's funny how culture shapes our designations of the same thing. In (specially us) english it's duct tape as the product is primarily known for installation work, and often referred to as "duck tape" for it's well known brand, whereas in (german speaking) europe we also employ an English word for it, but call it "gaffer tape", for it's usage by light operators in the event business (so called gaffers)
I don’t think gaffer’s tape and duct tape are the same thing. Gaffer’s tape needs to be easily removable, which duct tape generally is not.
Gaffers tape is a very different kind of tape similar only in appearance. It’s got a soft cotton content and is used to keep wires taped to things like rugs seamlessly so that people walking around your studio/tv-station/theatre etc don’t accidentally trip on it, potentially damaging the extremely expensive attached equipment in the process. If you’ve ever tried using “duct tape” as gaffers tape, you’d have a bad time, as it wouldn’t be that great at keeping wires down AND it’s likely to leave a residual adhesive on the floor when you take it off.

Duck tape is the stuff developed for the US army to waterproof things closed. Post-war, they made it silver instead of green and marketed it for use with ducts (since being waterproof made it also SEEM like a good candidate for the job in heating systems), but its pretty terrible for this purpose since temperature changes degrade the adhesive rapidly.

The tape you actually want to use for ducts is foil-backed tape.

In short, it was and still is a great marketing gimmick, but Duck Tape was only ever “ok” at keeping things water proof and only looks like gaffers tape or the tape you want to use on ducts.

Javascript as a language is actually pretty decent these days, your criticism probably applies more to certain parts of the ecosystem.
No, I'm talking about js as a whole. Standard library is crap, inconsistent, even the most basic of naming conventions are not followed anywhere. The fact that the standard library jumps between camel case, pascal case, snake case and unicase at random is a perfect example. The list of absurdities is beyond ridiculous[1].

[1] https://github.com/denysdovhan/wtfjs

Who on this thread was saying what's old is new? 100% of what you said has also been lobbed at PHP recently and I've heard similar complaint about PERL and MS-SQL (that I remember well) and I'm sure others (one of those Delphi product too)
What's been strange to me though is I've heard JS advocates lobbing those criticisms at PHP, making the case for, say, why 'Node is awesome, PHP sucks'. Conflating a framework vs a language, then pointing out PHP 'issues' that also exist in JS... there's generally little point in trying to engage/correct at that point (context: primarily conference hallway conversations and meetup groups back when those actually happened).
JS is the new PHP. Part of the problem with massive popularity is it attracts also the lower ability devs and the ecosystem slowly degrades due to this. This cascades.
What standard library?
Oh yeah like the 'new' reddit. It makes even the best machines cry.
Glad I'm not the only one seeing that parallel. I'd be hesitant to use this for that reason, but maybe that's bias on my part? Just seems like you'd get stuck in a similar mess of "special" updatepanels aka hotwire frames that are trying to "save you from having to write javascript". Except it still uses javascript under the covers, so you still have whatever issues that may entail, only now it's more removed from the developer to be able to solve.
(comment deleted)
Interesting bit of history (and yes, I see the /s), XMLHttpRequest was actually invented by Microsoft in Explorer because the Outlook team needed better responsiveness for the web email client.
Is this that web framework from Microsoft that hid the transaction-orientedness of HTTP from you by letting you set server-side click listeners on buttons and generated all the code needed to glue it all together? At the time, I didn't feel good about it because it abstracted away too much, and required Windows on the server. Little did I know about all the ways people would start abusing JS in 10 years.
webforms is dead, long live webforms.
Yep, was using this approach in Java server-side frameworks 12 years ago.
jquery also had a function for doing swaps. Then there's Rails turbolinks, and now Phoenix LiveView in Elixir.

I don't know if it's so much 'everything old is new again' as it is a problem of market penetration.

We need something like XMLHttpRequest right now. Google should integrate Dart into Chrome.
For those unaware, this is the "new magic" that dhh has been on about since HEY was in beta.
I read a little about Turbo, not sure I get it, is this like htmx? https://htmx.org/
They're similar in concept but Turbo uses WebSockets and htmx is more about AJAX.
I've been using HTMX to send "server push" updates over SSE ... I think it wouldn't be too hard to use websockets as well..
Turbo uses Ajax for most of its functionality too. The WebSockets bit is an optional add-on if you want to push updates from the server e.g. for notifications.
I get the feeling it will draw a bit of criticism from this crowd. IMO it’s fine to experiment with tech like this, but I have to wonder where sending HTML fragments over Websockets instead of HTTP falls apart.

Curious to hear about the success/horror stories in a few months/years from any adopters :)

I found this little thread on Twitter interesting, complaining Hey (powered by hotwire) is too slow

https://twitter.com/youyuxi/status/1337851036015480843

And here's some additional followup. Minor speculation that maybe his location is what caused slowdown.

https://twitter.com/swyx/status/1292825527116369922

That's one of the reasons SPA aren't going anywhere: trying to handle all the user microinteractions on the server is great when you leave next to it, but it falls apart when your users are spread across the world, especially if it's not western-ish world with fast internet connections.
Huh? How does SPA help here? JSON payloads don't go faster over the wire than html.
JS interacting locally can make a web page be perceived to be faster, even if there's no meaningful content yet. Humans enjoy working with systems that so _something_ as soon as they interact with them and a placeholder/spinner/animation is that exact something. Of course, you don't want any placeholders or animations to go on for too long, but it's good to know that the button you just pressed actually did something and the screen hasn't hung.

Minimal JS pages often have very little direct interaction built in, so they feel blazing fast when the connection is good and the payload is small (HN is a great example) but terribly slow if your internet connection is bad and it's not masking the network delays (again, HN is a great example).

The 2-5s mentioned on Twitter are something else though, perhaps the Hey app is being transferred through a saturated connection in the US or something.

Well, a spinner can be added even into non-SPA applications. So I don’t see how that is an argument for SPA.

I presume you can lie to user by pretending that their change was instantly submitted, while syncing in background. In that case, yes, SPA all the way.

That's not really lying, it's good UX. Optimistic updates feel a lot better than waiting for something to happen.
This varies on how important the action is.

Optimistic updates are great for inconsequential stuff like an HN upvote. The user likely doesn't even want to see an error message if their upvote timed out.

But it definitely is "lying to the user", or better phrased "breaking user expectations". It's just that the user isn't likely to care except for important actions.

For example, imagine applying optimistic update to sending an email. The user would expect to be able to close their laptop after sending an email and seeing the UI transition. It would be catastrophic if the email was never actually sent.

Optimistic updates are best relegated to micro-polish imo. Frankly, I think it's overused especially in combination with autosave UI.

Gmail does this all the time, and it makes me mad. I just sort out some mails to have my empty inbox, and then close the browser tab. And it says that the changes haven't been saved, so I need to deal with the popup, and then close the browser tab again...
Skeleton screens and spinners don't feel faster.
Because the DOM can be updated client-side before the server responds
An app with longer usage leans towards SPA. Quick or sporadical stuff, shouldn't be a SPA. The problem is always doing, SPA all the things or Do everything in the backend like if it's 2005
Surely a JSON payload is almost always going to be considerably smaller than the contents of that payload laid out in an entire HTML document?
It’s not the entire HTML document, it’s piecemeal. As for sizing equivalent data in HTML vs js, I remember reading an investigation that XML and JSON are generally closer than you would expect and that for some data structures, XML is terser.
It's not XML though, it's HTML. HTML with additional nodes for layout, class names, etc.

If you're not invalidating the cached code multiple times per day (which, in fairness, a lot of the stuff from Google, Facebook, etc probably are), an SPA should use less data over time than a comparable server rendered app. The initial outlay is bigger, but once it's cached you only need the raw data as you navigate around.

You're right, but the data can be cached and the views shown optimistically. After the first fetch it should be faster.
In this non-westernish world the internet is slow but how much processing power do the computers have to render the SPAs?
Hey approach needs server on at least 2 regions to cover 90% of worldwide usage. I guess they only have server in the U.S. and some users may experience some lacking. I'd say having SFO3,FRA and NRT are pretty much enough for global customer.
I got into the Hey beta, wound up purchasing it and I haven't had any performance issues to speak of. I'm curious to know what their setup is.
I've used Hey daily since it launched on desktop and mobile and I can't see it being slow in any way. I guess you could count that it shows a loading symbol for a file to appear (on the first load only).. but that would be excessive nitpicking.
It never performed slowly for me. It ended up having none of the features I wanted, but that’s a different concern altogether. Definitely rode the hype train and feel dumb about it now haha
The inventor of one of the most successful js frameworks might be a tad biased when it comes to the whole „as little JavaScript as possible“ thing.
he is complaining on Hey's lack of speed and interactivity, not complaining about the lack of js.

which is a fair complaint, I would say.

It is. But he also wrote this in a subsequent tweet:

> For a typically long running app like an email client, the obsession with shipping as little JavaScript as possible is actually detrimental to the end UX.

I'd argue that's almost objectively true. For a long running app, initial load time isn't as important as something like a ecommerce store.
Hey probably is the worst example for this approach, even though it works and it's impressive what they were able to achieve. It should be much better for most website out there that aren't trying to be a low latency app you run 24 hours a day.
Nope. And I will tell you why. To read my email I need the app to load. Gmail did not load for me in several countries and takes forever on a train wifi for example.

I never leave an email tab open, but even if I did, I first need it to load...

It falls apart in environments where WebSockets doesn't work, unless there's a fallback mechanism using XHR.
yeah... fallback is not a problem, you can always long-poll as socket.io has done for years
It's great when people do use an automatic fallback, and we've had reliable methods for that since the 1990s. I've seen WebSockets webapps where they don't bother with a fallback, though.
It's proved technology

.NET's Blazor (server based) uses this.

Um... Blazor hasn’t been used in any significant scale, and where it has been deployed, the websocket has been a bottleneck to performance.
proved in the sense of - the concepts makes sense, is actually implemented, used by some, viable in some cases.
It's hilarious that web servers rendering HTML and sending it to the browser over a TCP connection is now "cool new tech".
It's actually not as simple as that. The simplification is too brutal and doesn't appreciate the details.

It's the answer for people that sick of the weight of modern webapp, where everything need to be rendered client side.

Honestly, my experience is that most webapps aren’t that heavy for what they actually do.

Web sites are heavyweight, serving megabytes of useless nonsense just to display an article. With a bunch of ads obviously.

(comment deleted)
I'll just take a break for 3 years until SPAs become cool again. But they won't be called SPAs anymore... they'll be called "microapps". Elixir and Rust will be "just not fast enough" and there will be a new language VM that will "promise Hyperspeed™ on Google Crystalline™ chips". JSON will be considered harmful, and XML will be in favor again because it is flexible and there's plenty of bandwidth for all the extra bytes.
This isn’t new at all. This is version 7 of Turbolinks that has been renamed to Turbo and has some added versions. It has been what the Ruby on Rails and it’s creator have promoted for years and years.

The new thing about it are the name and associating it with Stimulus and some features, not the general concept.

Oh wow that is not clear at all. The old website of StimulusJS doesn’t redirect to its new home, and the old GitHub repo for turbolinks (not turbolinks-classic) still exists.
I had to look for it too. It isn’t clear and should’ve been. I’d like to know it is an enhanced renamed version of something I know rather than dismissing it because I can’t find time to learn something new.
This sounds a lot like server-hosted Blazor, streaming HTML snippets though websockets. Am I understanding it correctly?
Is this just PHP templating with extra steps?
It could be. Hotwire isn't tied to Rails at all.

You could just include it in your existing PHP app if you wanted to.

It sounds a lot like Laravel Livewire[1]

Also a lot like React Server Components that we saw on HN yesterday[2]

It seems like this is the next wave of web apps. Hopefully once the hype settles, we'll be able to decide which approach is best for which project.

[1] https://laravel-livewire.com/

[2] https://news.ycombinator.com/item?id=25497065

I wonder how recruiting companies will continue selling frontend react rockstars and backend nodejs warriors who can write endpoints. And yes, that's how they differentiate between frontend and backend, because knowing how to format your json urls (which is not real REST) is backend work and react is frontend.
> not real REST

Rarely admitted, but absolutely truth.

Livewire, of course, having been heavily inspired by Phoenix LiveView https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html
Tho, LiveWire is AJAX, while LiveView and Stimulus Reflex are Sockets. LW is a pleasure to work with for small pieces of interactivity.
I believe (but could be wrong) that liveview degrades to http long poll.
(comment deleted)
It does indeed!
still not sure if the degrading code is there, but you can definitely configure it to USE long-poll.
How does Hotwire compare to Phoenix LiveView?
For one, LiveView doesn't send HTML over the WebSocket channel. It sends a highly optimized diff structure that is applied to HTML.
> How does Hotwire compare to Phoenix LiveView? It seems the same to me.

It's much different based on a preliminary reading of Hotwire's docs.

Live View uses websockets for everything. If you want to update a tiny text label in some HTML, it uses websockets to push the diff of the content that changed. However you could use LV in a way that replaces Hotwire Turbo Drive, which is aimed at page transitions, such as going from a blog index page to contact form. This way you get the benefits of not having to re-parse the <head> along with all of your CSS / JS. However LV will send those massive diffs over websockets.

Hotwire Turbo Drive replaces Tubolinks 5, and it uses HTTP to transfer the content. It also has new functionality (Hotwire Turbo Frames) to do partial page updates too instead of swapping the whole body like Turbolinks 5 used to do. Websockets is only used when you want to broadcast the changes to everyone connected and that's where Hotwire Turbo Streams comes in.

IMO that is a much better approach than Live View, because now only websockets get used for broadcast-like actions instead of using it to render your entire page of content if you're using LV to handle page transitions. IMO the trade off of throwing away everything we know and can leverage from HTTP to "websocket all the things" isn't one worth making. Websockets should be used when they need to, which is exactly what Hotwire does.

I could be wrong of course but after reading the docs I'm about 95% sure that is an accurate assessment. If I'm wrong please correct me!

Fwiw, you can use long polling for LiveView if you wanted. That could completely remove websockets as everything happens over http.

Hotwire will benefit from caching better than LiveView, because frames are distinct URLs. But I haven't personally need that.

> Fwiw, you can use long polling for LiveView if you wanted.

How does that work for page transitions? The docs don't mention anything about this or how to configure it.

With Turbolinks or Hotwire Turbo Drive, the user clicks the link to initiate a page transition and then the body of the page is swapped with the new content being served over HTTP. With Turbo Frames the same thing happens except it's only a designated area of the page. In both cases there's no need to poll because the user controls the manual trigger of that event.

How would LV do the same thing over HTTP? Everything about LV in the docs mentions it's pretty much all-in with websockets.

Then there's progressive enhancement too as another difference. Turbo is set up out of the box to use controllers which means you really only need to add a tiny amount of code (2-3 lines) to handle the enhanced experience alongside your non-enhanced experience. For example you could have a destroy action remove an item from the dom when enhanced using Turbo Stream or just redirect back to the index page (or whatever) for the non-enhanced version.

There's an example in the Turbo docs for that at https://turbo.hotwire.dev/handbook/streams if you search for "def destroy".

But with LV wouldn't you need to create both a LV and a regular controller? That's a huge amount of code duplication.

Although to be fair I would imagine most apps would require JavaScript to function so that one is kind of a non-issue for most apps, but it's still more true to the web to support progressive enhancement and the easier you can do this the better.

It uses long polling over http. To be clear it's not restful http, but it's not websockets. I believe that Chris doesn't believe it's important for most people so there are no directions right now. Could be wrong there, I'm not Chris.

Page changes are still initiated by the client in LiveView (although can be server initiated)

LiveView is just channels under the hood. Once you consider that, long polling may seem more obvious

Since LiveView is built on phoenix channels, it's the same story. Simply pass the `transport: LongPoll` option to the LiveSocket constructor and you're now using long polling with LV :)
> LiveView is just channels under the hood. Once you consider that, long polling may seem more obvious

It's not obvious to me for user invoked page transitions because when I think of long polling, I think of an automated time based mechanism that's responsible for making the request, not the user. But a page transition is invoked by the user at an undetermined amount of time / interval (it might happen 2 seconds after they load the page or 10 minutes).

Your idea of "long polling" sounds more like periodic polling (repeated requests within a frequency), though that's not what long polling is or how it works.
> Your idea of "long polling" sounds more like periodic polling (repeated requests within a frequency), though that's not what long polling is or how it works.

Right isn't long polling keeping the connection open for every client on the server and then the server is doing interval based loops in the background until it gets a request from the client or times out?

It wouldn't be doing a separate HTTP request every N seconds with setInverval like the "other" type of polling but it's still doing quite a bit of work on the server.

In either case, LV's long polling is much different than keeping no connection open, no state on the server and only intercepting link clicks as they happen for Turbo Drive and Turbo Frames.

I don't think that's necessarily a big deal with Elixir (I wouldn't not pick it due to this alone, etc.), but this thread is more about the differences between Hotwire and LV, and no state being saved on the server for each connection is a pretty big difference for the Drive and Frames aspects of Turbo.

Yes there is a lot of stuff different here. I don't want to take that away. Just pointing out that websocket only is not accurate.
> But with LV wouldn't you need to create both a LV and a regular controller? That's a huge amount of code duplication.

You just do LiveView instead of a regular controller. No duplication.

When you request a page, it is render on the server and all of the HTML is returned over HTTP as usual.

After the client has received the HTML updates, live updates can go over a websocket. For instance you start typing in a search field, this is sent to the server over websockets. Then the server might have a template for that page that adds search suggestions in a list under that search field. The server basically automatically figures out how the page should be rendered on the server side with the suggestions showing. By "re-rendering" the template with changed data used with the server side template. Then it sends back a diff to the client over websockets. The diff adds/changes the search suggestions to the page. The diff is very small and it's all very fast.

> You just do LiveView instead of a regular controller. No duplication.

Yes but this is only in the happy case when the client is fully enhanced no?

What happens if you hook up a phx click event to increment a like counter.

After the page is loaded, if you click the + to increment it while having JavaScript disabled it's not going to do anything right?

But with Hotwire Turbo, if you have a degraded client with no JS, clicking the + would result in a full page reload and the increment would still happen. That's progressive enhancement. It works because it's a regular link and if no JS intercepts it, it continues through as a normal HTTP request.

I've found that the vast majority of clicky stuff I do leads to a URL change anyways, and these are just proper links to the new URL that LV then intercepts.

In your Counter example, it's true that for the 'degraded' version to work, the link would have to be a proper link and not a phx-click. But in the (IMO very unlikely) case where this fallback is necessary, solving it with a proper link/route does not require duplication, just a different approach.

What you would do is create a LiveView that handles both the initial page and the 'increment' route. If LV is 'on', it intercepts the click and patches the page. if LV is 'off', your browser would request the 'increment' route, and the same LV would handle all this server-side and still display the new, incremented counter.

The LV is both the server-side controller /and/ the client-side logic. That's part of what makes it so appealing, but, admittedly, also something that can take a while to wrap your head around.

I've more than once reflexively gone for phx-click solutions where the LV would receive the event and 'do' something, only to later realize that it would be much better to use a proper url/routing solution (where LV is still the 'controller'). In hindsight it's often a case of treating LiveView too much like just 'React on the server', basically.

Yes, the `phx-click` doesn't automatically get translated to a link or form submission. You can still design the page to work without javascript. For instance by having a "+" button be a normal form or link and then have phx-click intercept it when javascript is enabled. This can be done with one LiveView module without having to also have a separate regular controller.

One way to do it would be to in the `mount` function handle normal non-javascript params being sent and a `handle_event` function handle `phx-click`.

I don't know if there is already a way to have `phx-click` with fallback to HTTP in a less "manual" way. It should be possible to make.

I've just been getting into it, and am completely loving it, especially the elixir part. It feels like the whole OTP/erlang part of it (basically single codebase microservices and patterns that come with it) has proper engineering and principles behind it, and it's something I've been missing for a long time in our profession
Caleb Porzio (creator of Livewire) made videos about "Server-Side Applications": https://laracasts.com/series/javascript-techniques-for-serve...

His work inspired me to build my app (TravelMap) with SSR views: https://clem.travelmap.net

Off topic from the main thread, but Travel map looks really good. Reminds me of all the travel blogs I used to read when I was in high school / college dreaming about getting out and exploring the world. Great work!
Sounds like Phoenix LiveView. I love phoenix <3
These folks literally invented Ruby on Rails and were building web applications for over 20 years now. This tech seems "old" but it's solid.
This kind-of tangential reply is in bad taste, but DHH is currently being an asshole about this very topic on Twitter, so:

This seems cool, but the progress that HEY has made since launch isn't very impressive if that's the flagship example.

HEY's search UX, which uses these capabilities, has been abysmal since the day it launched. It's a much better experience if you disable JavaScript/Hotwire and fall back to the server-side-rendering instead of the hybrid mess they push down. I'm very disappointed that this hasn't been improved. (I sent feedback about this while they were still in their invite-only phase.)

We were also promised custom domain support by the end of the year, and we don't have a timeline or even pricing yet. (That's obviously backend and unrelated to this announcement.) I don't want to go back to Google, but the lack of improvement isn't giving me a lot of confidence as a HEY customer, so I'm considering alternatives.

I‘d be curious to hear about your general experience w/ hey - from the outside it looks like it has some cool new(er) approaches, but I‘ve seen someone‘s actual full email account in a screencast once and it looked like it‘d get messy with actual heavy usage really quickly and the UX might deteriorate. Any takes?
Not OP, but I have a Hey account and I really enjoy it. The screener feature is worth the price alone IMO. The biggest challenge for me was having to re-conceptualize email after switching over since Hey doesn't use traditional email terminology (i.e. "paper trail" vs "archive").

The amount of inbound email I get has dropped immensely due to the screener and my inbox ("imbox") is so much easier to manage with Hey, IMO.

I find HEY's general workflow very good for my medium-volume personal email. It encouraged me to filter a lot more stuff out of my inbox than I did with Gmail, while spending less time configuring filters. The ability to leave internal comments on external email threads (business accounts only) is very useful as a first-class feature, instead of relying on fiddly BCC. The apps are quite nice to use. Overall, there's less clutter and it is a more pleasant experience than other email clients I've used... until I try to search in the Hotwire-powered web view.
>We were also promised custom domain support by the end of the year,

Basecamp / DHH generally speaking hate deadlines / roadmap etc. They are ready when they are ready.

Although I do agree a little update would be nice.

(comment deleted)
This is the Ruby on Rails version of what Elixir Phoenix Live View and .NET Blazor do.

For those not familiar, rather than using a standard web framework where a lot of processing is done client side, these frameworks allow html buttons etc to call native Ruby, C#, or Elixir functions on the server rather than using some sort of post/get request to do that. Every UI interaction goes over the wire, which is where performance can be hurt.

Having used Blazor in production for nearly a year, it speeds up development, but your server is doing a lot more processing and will not be able to handle an equivalent amount of users that a normal web app would because it’s keeping a copy of the clients DOM in memory. It’s updates the dom on the server then streams that update through websockets to the clients dom, creating your magic Single Page App experience.

I think it’s cool tech, but not necessarily scalable due to the increased server load. I’d be interested to hear from people using it to serve large orders of magnitude of clients at once.

Any idea how many people use Hey.com? That might be an early indication as to how scalable this is (at least for hotwire's concerns)
GitHub scales just fine on their own variant of Turbolinks.
Agreed. My comment about scaling is simply that a lot of other companies use rails at scale, and alike that of hey.com (which I presume is heavily used) it is probably built to... scale
Well Rails was never not scalable in literal sense. It was just the cost of scaling being expensive; comparatively speaking when people say Rails not able to scale. And for most if not all SaaS that should never be much of a problem. Because you are getting revenue per user, and generally speaking the cost percentage of user / app / server resources is so small, that is a rounding error in grand scheme of things.

What doesn't work quite as well is when the app is operating a freemium / ad based model. Where a large volume of traffic are required before you start generating revenue.

I always find the Rails/scalable thing to be a funny argument - especially on the startup-minded HN.

You don't need scale at a startup. You need velocity. If you're hitting scale at a startup, you've done one of two things:

* Written absolutely terrible software

* Succeeded

Unless you've hit the second one, it will almost always be cheaper to simply spin up another server.

Could be because a lot of startups are just trying to squeeze just as much traffic as they can with very little capital involved.

It's basically here's my app that does billions of things and wants billions of users and runs on potato thing.

It depends right? If your app is a dashboard this could be less work when using smart cashing. You could cache entire html fragments on the server for specific user defined filter values. If you are serving hundreds of users you’d have dashboard faster than most BI tools out there including PowerBI.
I get the rush to provide technical comparisons to something that was just revealed five minutes ago, but none of what you just said is actually how Hotwire or Turbo works. There's no client DOM in memory on the server, there's no html buttons that call native code.

There are forms being submitted, there are normal requests happening, there are templates being rendered on a per-request basis (just like a full page load).

This is like a normal web application that renders HTML, from the perspective of how the server works. Just as scalable as every other Rails application that renders HTML. Be that GitHub or Shopify or Zendesk or Basecamp or HEY or any of the many, many other apps that have long ago definitively proven that Rails Scales.

Although I do find the commentary that the current #1 comment on the HN thread is literally a "bUt DoES iT SCaLE??" take, based on a misunderstanding of how this works. All is indeed as it's always been

Hi @dhh!

Loving the tech and the website (and Rails, and Basecamp, etc). However it looks very similar to StimulusReflex (https://stimulusreflex.com), which has already attracted a few users.

Can you highlight the biggest differences between the two?

Thanks!

Literally LOL'd at the first part of this. A+++.
(comment deleted)
(comment deleted)
It's not keeping a copy of the DOM server-side..

That's not how it works, at all.

I can’t speak for Blazor but LiveView does not keep a DOM on the server nor it requires all UI interaction to go to the server.
My first thought was that some dude is ripping off LiveWire and Turbolinks because of the strange centered text (no professional web designer would do that), until I saw that those were renamed evolutions of those technologies from Basecamp, cool!.
Gotta give @dhh credit - he is one of the world's great marketers/promoters. He's been building hype for this as the "next Rails" for months and the man knows how to pique an audience's interest.
I've never seen one of these "logic in html-attributes" systems take error checking seriously. In stimulus they start to mention it in "Designing For Resilience" (though only for feature-checking), but in "Working With External Resources" where it uses calls network/IO bound calls they never mention how to handle errors or if the framework just leaves it up to you. Stimulus is also where you need to write your own js code, so I guess you could handle it yourself but in turbo when I skimmed the handbook I find no mentions of what/how to handle errors (or even what happens when turbo gets one), and when loading stuff over the network that is pretty much crucial.

From the turbo handbook: "An application visit always issues a network request. When the response arrives, Turbo Drive renders its HTML and completes the visit." Using the phrase "When the response arrives" begs the question of what happens if it doesn't arrive, or if it takes a minute for it to arrive, or if it arrives but with a faulty status code.

A very good point! Presumably the appeal of a system like this is the potential for graceful degradation where if sockets aren’t working or some requests are failing then the default html behavior should still work: links will just take you to the original destination, but there’s no indication that this is actually what happens.
This is an isomorphic fetch. The original href already is the visited URL, so I'm not sure that trying that again is wise, or appropriate, unless the user chooses to reload.

The entire design philosophy here is to mimic apparent browser behaviour, or to delegate to it. Hence, to GP's question; you should expect the appearance of browser-like behaviour in any circumstance, modulo anything Turbo is specifically trying to do different. Deviation from baseline browser semantics was certainly a basis for filing bugs in its predecessor (Turbolinks).

As for what Turbo actually does, I checked the source. Good news, even for a first beta, they're not the cowboy nitwits alleged; it gracefully handles & distinguishes between broken visits and error-coded but otherwise normal content responses, and the state machine has a full set of hooks, incl. back to other JS/workers, busy-state element selectors, and the handy CSS progress bar carries over from Turbolinks.

I’ve used intercooler with browser-side routing and, the strategy for error recovery that makes sense in that context is “if something goes wrong, reload the page”: the server is designed to be able render the whole page or arbitrary subsets and, so, reloading should usually be safe.
(comment deleted)
Yes!

1. What if something goes wrong?

2. How do I test for handling success/error?

They never address this stuff.

...also what is when response/request "items" are not handled chronologically due to load. I once wrote a real-time application with that pattern (HTML over AJAX). It worked but it was not enjoyable at all. Also literally every larger feature change would break the code because you had all these weird corner-cases.
They do already address error handling. GP is shooting the breeze here, evidently has no specific knowledge of Turbolinks family API or behaviour.
Counterpoint: is there any error handling in the majority of SPAs today? From my experience, SPAs can crap out in all kinds of interesting ways when the underlying network connection is flaky and I often end up stuck on some kind of spinner that will never complete (nor give me a way to abort & retry the operation when I already know it won't complete and don't want to wait for the ~30-second timeout, if there is a timeout even).

Not saying this is better from an error handling perspective, but at least the whole idea of Hotwire and its peers (Turbolinks, etc) is that there is no state and it should thus be safer and quicker to reload the page should things go wrong.

I refresh SPA apps more than other apps because of these problems.
Me too. However, this also doesn't work properly on a lot of SPAs xD
Also the app looking fine immediately after refresh (when it's been server-side rendered), then crashes a second later when the JS framework hydrates the HTML and hits a client-side bug.
I agree that most SPA apps do it badly too, but hiding the opportunity to do it well certainly does not help.

> there is no state and it should thus be safer and quicker to reload the page should things go wrong.

That's not exactly true since there are non-idempotent HTTP methods and while the browser will prompt you if you want to resend a non-idempotent HTTP request when refreshing a normal form POST I don't think that turbo/turbolinks/similar will allow you to prompt or resend.

On refresh should turbo retry a POST? The "right way" is to keep the state of the last POST and prompt the user for confirmation, but it seems like it is undocumented as to what it does. I'm guessing it either does not retry or it retries and hopes effect will be idempotent.

No one (SPAs, traditional webpages and "spiced" webpages like this included) is doing everything right, but my objection to this framework is that it seems to try to say things are simple or easy when they clearly aren't.

I believe the only place you'd use a POST with Turbolinks is in response to an explicit user action like pressing a button. In this case, if it fails, you'd refresh the root page (which embeds the button) at which point the state of that page would reflect whatever the server has, so it would display the new data or may not even have the button anymore if the initial POST actually did make it to the server.
You're correct in that the only standards-based way to retain a POST in the session history is to not disturb an existing entry. However:

> it seems to try to say things are simple or easy

That's an unfair mis-characterisation. The developers are not pitching a universal panacea that solves all your problems and handles every edge case. They are offering an architecture that simplifies many common scenarios, and one that is thoroughly developer-friendly when it comes to supplying observability and integration hooks for edge cases.

For this latter purpose it merely remains to bother with reading the (clean & elegant) source code to enlighten oneself.

> it seems like it is undocumented

On the contrary, the behavior w.r.t full-page replacement on non-idempotent verbs is extensively discussed in the Turbolinks repo.

The "Turbo Drive" component appears to me as essentially unchanged behaviour in Turbo 7.0.0beta1 from Turbolinks versions 5.x. Turbolinks was introduced in 2013, has many years of pedigree and online discussion, and is well understood by a large developer community. Turbolinks was always maintained, even being ported to TypeScript (from the now venerable CoffeeScript) ca. two years ago with no change in behaviour. Turbo Drive is, practically, just a slightly refactored rebrand of the TypeScript port.

The stuff everyone is so excited about are Turbo Frames and Turbo Streams. These are new, and may be used without adopting Turbo Drive: as with practically everything from Basecamp, the toolkit is omakase with substitutions. They are, nevertheless, complementary, so you get all three steak knives in one box.

Which I find frustrating because literally the only reason I find compelling for making an SPA in the first place is to deal with flaky networking situations.

If I know the network is always there, why bother.

Facebook does this constantly for me. It's a crapshoot whether I'll be able to open notifications or messages without a couple of refreshes, or if I'll just get the fake empty circle loading UI indefinitely until I hit F5.
This is my experience in Reddit generally these days on mobile Safari
This combined with them intentionally breaking the mobile web experience has almost entirely stopped me from using Reddit.
I was trying to quit Reddit for years and their intentional breaking of mobile web (as well as making email address required even for already existing accounts) is what finally enabled me to.

Of course now I just go on Hacker News and Twitter instead.

in htmx we trigger an htmx:responseerror:

https://htmx.org/events/#htmx:responseError

in general, the right approach in HTML-oriented, declarative libraries appears to be triggering error events and allowing the client to handle them, since it is too hard to generalize what they would want

Hype hype hype hype...
Gentlemen, we have come full circle.
web development has jumped the shark, I thought this was a parody at first.
I thought this had to be satire when I opened the page. Now I'm still not sure.
I thought it was a joke. and completely ignored it when i first saw the headline. only later someone else referred to DHH's hotwire. it clicked me that it is the New Magic thing.

I am still wondering if there is any benchmark presenting some objective facts

I'm also still not sure. Also thought this is satire.
Wait, we still need to add a cgi-bin to this
cgi-bin has been rebranded serverless: running external processes to the web server.
That's good, because I've been deliberately ignoring pop webdev technology in hopes this would happen.
Is this the "new magic" that DHH teased on Twitter, or are we still waiting to see what that is? Also, should we expect this to be included in a future version of Rails?

My first impression is that the API seems a little convoluted, but that might just be me. In an ideal world, I'd love to just build components (similar to React components) on the server side, and let the framework intelligently handle synchronizing state over the network (Phoenix LiveView seems closer to that), but this feels like it involves a lot more framework-specific logic (and markup) with special cases - stuff that's likely to change as the framework evolves, so I'm not sure how I feel about it.

I guess it makes sense in terms of making this easier to add to an existing rails app incrementally (since it's more-or-less "opt-in" for each model, view, and controller), but if I'm building a new project with this and want it on everything, it feels like it will necessitate a lot of code duplication. Either that, or I use it judiciously only when absolutely needed (and use traditional rails behavior for everything else), but that feels like a mess of two very different approaches bundled together in one codebase.

Yes, this is the "new magic".
You should check out React Server Components.
Yes this is the new magic stuff.

But I doubt they'll integrate this into Rails. They'll just create better and better tooling to make using this with rails a cinch.

I think this will just remain backend agnostic, like turbolinks and stimulus were before "hotwire".

(comment deleted)
I'd like to try a version of this outside of Ruby/Rails.
I use Turbolinks for some Django projects, so took a look at how much work it would be to port these over to Hotwire/Turbo. Very little in the way of docs to go on right now and what little there is in the way of examples is buried in Rails gems. Should be mostly straightforward, with a thin Django middleware to check headers and the like. I guess The Turbo Stream stuff could be adapted to Django channels quite easily. I'll wait and see how and when they improve the documentation, especially on the Rails-agnostic front.