The server names what changes
3 November 2023
The frontend runs on an agreement of eight words. The server answers with JSON naming inner, outer, before, after, remove, main, uri and title; the browser carries them out in the order they arrive, inside a view transition.
reply(uri: "/chat/$id", inner: ['#saved-sessions' => $this->savedSessions, '#chat-messages' => %message->list], trans: 'sessions,messages')
The division is what keeps the client small. There is no store to synchronise, no component tree to reconcile, no second model of your data living in the browser. The route that did the work already knows what changed, so it says so, and the markup that comes back is rendered by the same views that rendered it the first time.
It also means the client never needs to understand your domain. It knows about elements and operations on them, and nothing about invoices, chat sessions or orders. That is the whole reason it can be one small JavaScript file rather than a framework.
The protocol is deliberately open at the edges: adding a command means the server can name one more kind of change, and the interpreter grows by a line. Classes, stylesheets, scroll position and page transitions are the obvious next candidates.
What it asks of you in return is that the server stays the place where decisions are made. Anything the client works out for itself is a second opinion waiting to disagree.