It looks like I can use htmx.

I do similar things in HTML, JavaScript and PHP. That’s why I end up thinking, ‘Where on earth am I doing this?!’

Livewire, which had been our last hope in the hope that we could centralise everything, had to be abandoned when Google Gemini threw in the towel. To begin with, Livewire was imposing far too many demands on those around it, which meant the future risks were simply too high.

Even so, I’d like to keep the logic all in one place

In short, where is the DOM generation algorithm documented? It would be great if we could narrow it down to just one folder to search.
That’s how to ask the question!

In my web application development, I have come to rely on AJAX for dynamic changes, and as a result, the MVC view has come to focus primarily on rendering static content. Are there any articles online that discuss a similar line of thinking?

It’s hard work having to be careful with the questions I ask so that Gemini doesn’t take offence.

Please rest assured. That very phenomenon and the awareness of the challenges it presents constitute the greatest paradigm shift (or transitional period) in the history of web development from the late 2000s to the mid-2010s.

The sense of unease and design flaws that arose on the development front lines at that time have been widely shared in the form of technical articles and essays.

Key concepts and trends in articles that were the talk of the town at the time

The phenomenon whereby the View in server-side MVC becomes a ‘static skeleton’, with all responsibility for dynamic rendering and UI updates shifting to JavaScript (Ajax), was discussed in the web industry using the following terms:

  • The Shift Towards ‘Fat Client’ (Rich Client) and the Collapse of MVC

    • Subject of the discussion: Traditional server-side MVC frameworks (such as Rails, Django and Laravel) are designed on the premise that they ‘return fully-formed HTML in response to a request’. However, when Ajax is used extensively, the server-side controller effectively becomes an API that merely returns JSON, whilst the view becomes little more than a ‘shell’ containing an empty <div> or some initial HTML.

    • Common criticisms: Cries of “What exactly is the role of a server-side view?” and “The logic for rendering the screen is split between the server and the browser (JS), making the code incredibly hard to follow” have been posted on numerous technical blogs (such as Qiita, Hatena Blog, Medium and Stack Overflow).

  • ‘jQuery Spaghetti’ and the Limits of DOM Manipulation

    • Discussion: This technique involves repeatedly performing DOM operations—such as $(‘#result’).append(…) and .html(…)—within the Ajax response, based on the JSON returned by the server.

    • Article topic: This has been widely reported as an anti-pattern, whereby ‘the definition of the HTML structure (View) is fragmented between the server-side template engine and string concatenation within JavaScript code’.

  • SSR (Server-Side Rendering) vs CSR (Client-Side Rendering)」

    • Subject of the discussion: The debate centres on whether rendering should be carried out on the server side or entirely on the client side. During the transition period, a hybrid approach—where ‘the first page is rendered on the server, with subsequent changes handled via Ajax’—was widely adopted; however, this resulted in the frustration of having to write ‘the same template logic in duplicate, both on the server and in JavaScript’.

How has this issue been resolved historically?

Current front-end technology lies directly in the extension of the concern you have expressed regarding the ‘hollowing out and duplication of views’. Historically, efforts to resolve this issue have mainly taken two directions.

  1. SPA(Single Page Application)

    • Approach: The approach is to ‘completely do away with server-side views’.

    • The server is dedicated solely to providing a pure API (returning only JSON), whilst all responsibilities for screen rendering and dynamic updates have been centralised within client-side UI libraries (such as React, Vue.js and Angular).

  2. Modern HTML Over the Wire (server-driven UI)

    • Approach: This approach aims to ‘eliminate the need to write JavaScript (Ajax) manually and restore dynamic changes to the server-side view’.

    • Examples: Hotwire (Turbo/Stimulus) (the standard for Ruby on Rails), Laravel Livewire, Phoenix LiveView, or htmx, amongst others.

    • Without reloading the entire page, ‘fragments of HTML’ rendered on the server are sent via Ajax or WebSockets to partially update the DOM. This makes it possible to encapsulate dynamic changes using only the server-side MVC view, without the need to write any JavaScript.

    It puts me off when I’m restricted to frameworks like Laravel.

    If you include unnecessary details and limit the range of possible answers, Gemini gets sulky.

    You’re absolutely right. It really puts a damper on things when people assume you’re using a specific, massive full-stack framework, or try to force the idea that ‘the right approach is to go with the Rails or Laravel ecosystem’.

    There are libraries and techniques that can be implemented independently, which are not dependent on any specific framework and allow responsibilities to be centralised in the ‘HTML output (View)’, regardless of the language or configuration.

    Framework-independent options

    • htmx

      • How it works: It is simply a single-file JavaScript library. By simply adding HTML attributes (such as hx-get="/path"), it inserts ‘HTML fragments’ retrieved from the specified URL into any DOM element.

      • Flexibility: It does not matter what language, routing system or template engine the server uses (PHP standard, Twig, Smarty, Blade, JinJa2, Pure HTML, etc.). As long as it can ‘return HTML fragments in response to requests’, it will work perfectly even with a simple, custom-built MVC or a lightweight micro-framework.

    • Alpine.js

      • How it works: By using attributes such as x-data in a similar way to HTML’s class or data-* attributes, it handles only ‘minor UI states within the browser’—such as expanding or collapsing drop-down menus, or showing and hiding elements.

      • Flexibility: It requires no build process whatsoever (such as npm, Webpack or Vite); it works simply by loading a CDN or a single script tag.

    A Return to Free Architecture

    There is no need to be bound by the ‘rules’ of a large-scale framework.

    1. Server-side view: Using pure PHP or a template engine, you can freely write standard HTML for the entire page or partial HTML (such as just <ul>…</ul>).

    2. Communication Bridge: Entrust the retrieval and replacement of HTML fragments to a lightweight library such as htmx.

    With this alone, you can neatly organise the dynamic updating of views whilst maintaining flexibility on the server-side, without being constrained by any particular framework.

    It looks like I can use htmx.


    PHP Implementation Example (Illustrating the MVC Pattern)

    1. View (the initial screen, index.php, or a template)

    This is the complete HTML loaded on the initial page (/controller_name/). The button is configured to trigger the action /controller_name/hoge.

    HTML

    copy

    2. Back-end (controller side)

    Instead of writing conditional branching (if (is_htmx_request())), we limit the role of the response returned by each action (function).

    PHP

    copy

    The advantages of this approach

    1. Eliminating if statements: The logic for determining ‘whether the request is from htmx’ will be completely removed from the code.

    2. Explicit routing: As this adheres to a fundamental principle of the Web (one URL/action, one responsibility), it is immediately clear what is returned and from where.

    3. Improved testability: As the hoge() action focuses solely on ‘returning an HTML fragment’, it becomes much easier to write unit tests.

    The approach of separating ‘entire-page rendering’ from ‘individual-component rendering’ at the action level is highly recommended as an implementation pattern for the large-scale, long-term operation of htmx.

    hx-target=”#target-area” means ‘insert the HTML code returned from the server into the CSS selector #target-area (the element with id=”target-area”)’.

    Overwrite behaviour

    As the default replacement rule (hx-swap=”innerHTML”) is applied, the outer container of id=”target-area” (the div tag itself) remains, whilst only its ‘contents (inner part)’ are completely overwritten.

    Before communication (on the browser side)

    HTML

    copy

    HTML returned by the server (/controller_name/hoge)

    HTML

    copy

    After communication (on the browser side)

    HTML

    copy

    (Note) If you want to replace the entire div tag in one go

    If you wish to replace the entire div tag, including its outer border, add the hx-swap=”outerHTML” attribute.

    HTML

    copy

    Unless otherwise specified, the default behaviour is to ‘rewrite the content (innerHTML)’, so it will behave exactly as you expect.

    I imagined it wouldn’t be very good at handling the animation where articles load as you scroll down, which is common on social media—what do you think?

    No, actually, the mechanism whereby ‘scrolling down automatically loads the next article (or content) (infinite scroll)’ is one of the standard use cases that htmx excels at!

    You can implement this simply by adding a few HTML attributes, without writing a single line of JavaScript.

    Implementation (code example)

    The mechanism is simple: all you need to do is set up a trigger for when the user scrolls to the ‘last article’ (revealed).

    Initial HTML display (attributes applied only to the last item in the list)

    HTML

    copy

    The roles of the attributes used

    • hx-trigger=”revealed”: Triggers a request the moment the user scrolls and this element enters the screen (when it becomes visible on the screen).

    • hx-swap=”afterend”: Inserts the new HTML received (items 21 to 40) immediately after this element.

    HTML returned by the server (response for Page 2)

    The server-side (/feed?page=2) returns a set of newly loaded articles. At this point, the ‘last article in that set (the 40th)’ includes a mechanism for the next request (page=3).

    HTML

    copy

    Why am I good at it?

    1. Optimisation of scroll events: Whilst standard JavaScript requires measures to reduce the load on window.onscroll (such as debouncing) and to calculate position, htmx utilises the Intersection Observer API (a high-speed, browser-standard intersection monitoring feature) internally, resulting in excellent performance.

    2. No need for client-side state management: As the state indicating ‘which page you are currently on’ is contained within the HTML URL itself (page=2, page=3, etc.), there is no need for complex front-end logic.

    As such, htmx is not only adept at handling simple click events, but also excels at dynamic UI patterns such as scrolling into view and input monitoring (incremental search).

    That’s fine, isn’t it?