Showing posts with label htmx. Show all posts
Showing posts with label htmx. Show all posts

htmx 4.0.0 has been released!

Mike's Notes

More details from Carson about htmx 4.0.

Resources

References

  • Hypermedia Controls: From Feral to Formal

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

26/09/2026

htmx 4.0.0 has been released!

By: Carson Gross
HTMX: 28/08/2026

Carson Gross: I am a programmer comfortable with both front-end & back-end development. I currently teach at Montana State University.

My primary technical interests are hypermedia and programming languages, but I’m comfortable working in most areas of enterprise systems.

...

Release announcement, 2026-08-28.

htmx 4.0.0 Release

The htmx team is very happy to announce the release of htmx 4.0.0! This is the culmination of 8 months of work (plus a game) and we are very happy with the results.

The idea of htmx 4 started to germinate when I decided to create fixi and, in doing so, got more familiar with the fetch() API and async programming in JavaScript. (htmx had always used XMLHttpRequest due to backwards compatibility issues.)

One chance evening I was contacted by Christian, who had some interesting ideas around streaming HTML that got me thinking that moving the internals to fetch() would simplify things for him and for the library in general.

After a bit of work I managed to get Michael and Alex on board, and we were off to the races.

Development has been very smooth. We started a port of fixi + the htmx test suite. Over time, we rediscovered why htmx did many of the things that it did and moved our new implementation closer and closer to the old one. At this point the behavioral differences between 2.x and 4.x are relatively small and where they do diverge we have made explicit choices that we feel will put htmx-based applications in a good spot for being 100-year web services

Note that we are not marking 4.0 as latest in NPM because we do not want to force-upgrade users who are relying on non-versioned CDN URLs for htmx. Instead, 2.x will remain latest and the 4.0 line will remain next until some point in early 2027. The website, however, will reference 4.0.

Major Changes

As mentioned above, htmx 4, from a user’s viewpoint, is almost identical to htmx 2. There are three major changes:

  • Attribute inheritance is now explicit by default rather than implicit by default (this is the biggest upgrade item)
  • The htmx event names have been standardized & cleaned up. Some advanced users may need to change the events they listen for.
  • History support now does not use localStorage by default (which was a cause of many support headaches). Most people won’t notice this at all.

Internally, we migrated from XMLHttpRequest to fetch() but that should be transparent for most users of htmx.

Attribute Inheritance

In htmx 2 many attributes were “inherited” by default. This allows you to place attributes on parent elements and their behavior will apply to child elements. This behavior, which came from the intercooler.js days, was inspired by CSS and, unsurprisingly, worked out about the same as CSS: powerful but difficult to understand at times.

In htmx 4 attributes are not inherited unless you explicitly say so by adding an :inherited after the attribute name:

<!-- htmx 2 -->
<div hx-confirm="Are you sure?">
    <button hx-delete="/item/1">Delete</button>
</div>
<!-- htmx 4 -->
<div hx-confirm:inherited="Are you sure?">
    <button hx-delete="/item/1">Delete</button>
</div>

This will be the largest upgrade burden in migrating from htmx 2 to htmx 4. To make things easier, we have provided a command line tool to find places you need to mark as inherited.

Note that attributes like hx-disinherit, etc. are no longer required and should be removed.

Events

The events triggered by htmx 2 had grown organically over the life of the library and were not particularly well organized, making it difficult to know exactly which event was fired when.

In htmx 4, all events now follow htmx:phase:action[:sub-action]:

htmx 2 htmx 4
htmx:beforeRequest htmx:before:request
htmx:afterRequest htmx:after:request
htmx:beforeSwap htmx:before:swap
htmx:afterSwap htmx:after:swap
htmx:configRequest htmx:config:request

In addition, the following changes were made:

  • Most error events collapse into htmx:error. HTTP error responses fire htmx:response:error.
  • The htmx:xhr:* events are removed. htmx 4 uses fetch().
  • The htmx:validation:* events are removed in favor of native browser form validation.

The full table is in What’s New in htmx 4.

The command line upgrade checker flags old event names in hx-on attributes and in your JavaScript where it can find them.

History

History support has always been included in htmx, allowing you to implement back-button aware actions with simple attributes. In htmx 2, a cache in localStorage was used to snapshot pages for restoration. Unfortunately a large source of issues was that this snapshot could include DOM mutations by 3rd party JavaScript libraries. When the page was restored, those mutations remained but the underlying JavaScript logic was not.

htmx 4 does not cache pages in localStorage. On back navigation htmx re-fetches the page and swaps it into <body>, or into the [hx-history-elt] element if one is present. This allows 3rd party JavaScript libraries to “just work” in most cases and, with good request caching, is very fast.

If you want local caching instead, we now ship a very complete hx-history-cache extension that restores history from sessionStorage and is designed to integrate well with scripting solutions like Alpine.js, etc.

New Features

There are two big new features in htmx 4, both of which we are really excited about:

Morph Swaps

We now support morphing swaps out of the box with htmx. I created idiomorph and nearly included it in htmx 2.x but decided against it. In htmx 4, Michael has done great work improving on that algorithm and integrating it seamlessly into htmx.

<hx-partial>

Another major new feature is the <hx-partial> tag. This tag is similar to out-of-band swaps, but is much clearer when you want to do something beyond just replacing a single element with a new version of itself:

<hx-partial hx-target="#messages" hx-swap="beforeend">
    <div>New message</div>
</hx-partial>
<hx-partial hx-target="#count">
    <span>5</span>
</hx-partial>

Extensions

Much of the excitement in htmx 4 is in the extensions. Switching to fetch() internally let us rethink how extensions can and should work, and sparked the creation (and recreation) of many new extensions, for example:

  • hx-preload - preload content (e.g. on mouseover) to speed requests up
  • hx-download - native, fetch-based file downloads
  • hx-alpine-compat - smooths over compatibility issues between htmx and Alpine.js
  • hx-history-cache - caches history in sessionStorage, provides Alpine.js compatibility

Additionally, there are three new or updated streaming HTML extensions:

  • hx-sse streams over text/event-stream.
  • hx-ws streams and sends over WebSockets.
  • hx-multipart streams over multipart/mixed

Finally, we decided it was time to try our hand at our own small front-end scripting solution that tightly integrates with htmx. hx-live is inspired by Alpine.js, jQuery and hyperscript, and makes front end scripting pleasant and fun. It even supports what we are calling DOM-based, HATEOAS-friendly reactivity.

There is a new htmax.js bundle in the distribution which packages htmx with the most popular of these in a single file if you don’t want to think about which ones you want to pick.

Upgrading

For a complete upgrade guide see What’s New in htmx 4.

As mentioned earlier, we are providing an upgrade tool to help you:

$ npx htmx.org@4.0.0 upgrade-check -- ./templates

File extensions: .html, .php, .js, .ts, .jinja, .jinja2, .j2, .erb, .hbs
Use --ext to add more (e.g. --ext .vue --ext .svelte)

Scanning 1 file(s)...

Found 8 issue(s) in 1 of 1 file(s).

  • templates/index.html:1: [inheritance] hx-headers needs :inherited suffix (descendant on line 3 has hx-delete) (this looks like a CSRF token; without :inherited the header does not reach child elements and the server rejects the request)
  • templates/index.html:2: [inheritance] hx-target needs :inherited suffix (descendant on line 3 has hx-delete)
  • templates/index.html:2: [inheritance] hx-confirm needs :inherited suffix (descendant on line 3 has hx-delete)
  • templates/index.html:3: [renamed-attr] hx-disable -> rename to hx-ignore (hx-disable now means 'disable during request')
  • templates/index.html:4: [removed-attr] hx-vars is removed -> use hx-vals with js: prefix
  • templates/index.html:4: [removed-attr] hx-prompt is removed -> load the hx-prompt extension to keep the same syntax
  • templates/index.html:9: [old-event] old event name "htmx:afterRequest" -> "htmx:after:request"
  • templates/index.html:9: [old-api] htmx.addClass() is removed -> use element.classList.add()

We are also shipping an agent skill to assist in upgrading

Installing

htmx 4.0 can be installed via a package manager referencing version 4.0.0, or can be linked via a CDN:

<script src="https://unpkg.com/htmx.org@4.0.0/dist/htmx.min.js"></script>

or Downloaded

LLMs

Like it or not, a lot of people are using LLMs and we are providing the following skills files for LLMs:

  • htmx-guidance - core htmx skills for developing with htmx 4
  • htmx-debugging - diagnosing htmx issues during dev
  • htmx-extension-authoring - writing and debugging htmx 4 extensions
  • htmx-upgrade-from-htmx2 - migrating a codebase from htmx 2.x to 4.x

(Let’s leave aside if releasing a new version of a library in the LLM era is a good or bad thing!)

Conclusion

We hope you enjoy htmx 4. htmx 2 will continue to be supported indefinitely so don’t feel any pressure to upgrade.

I’d like to thank the following people for all their help with this release:

  • Michael West - Incredible teammate & grug-brained developer
  • Christian Tanul - Inspired htmx 4 & led the streaming & live extensions
  • Alex Petros - For keeping the ship on an even keel
  • Stephen Mitchell - The genius behind the game
  • Stu Kennedy - Our WebSockets expert
  • AndrĂ© Ahlert Jr. - Providing IDE & Editor Support
  • Dien Hoa Truong - For kicking the tires on early htmx 4 and helping fix many bugs

Upgrade Music

Wouldn’t be an htmx update without upgrade music:

htmx 4.0: a Fetch-Based Rewrite, Built-In Morphing Swaps, and Explicit Attribute Inheritance

Mike's Notes

Excellent news.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library > Subscriptions > InfoQ
  • Home > Handbook > 

Last Updated

25/09/2026

htmx 4.0: a Fetch-Based Rewrite, Built-In Morphing Swaps, and Explicit Attribute Inheritance

By: Daniel Curtis
InfoQ: 18/09/2026

Daniel Curtis: Daniel Curtis is a UI Development Manager at Griffiths Waite, a software consultancy based in Birmingham, UK. He leads front-end engineering efforts with a strong focus on delivering innovative enterprise solutions using TypeScript across the stack. Daniel is passionate about modern web architecture, developer experience, and the use of AI to both support software delivery and solve real customer problems within products.

...

The htmx team has released htmx 4.0.0, the first major version of the hypermedia library since 2.0 arrived in 2024, landing after eight months of work and skipping version 3 entirely. Creator Carson Gross, who had promised there would never be an htmx 3, summed up the leap to InfoWorld in a one word quote: "Oops."

htmx has swapped its long serving XMLHttpRequest transport for the modern fetch() API, a rewrite that unlocks native streaming while keeping the script around 14KB. For most developers the familiar hx-get and hx-post attributes behave exactly as before, but the move enables the two features the team is most excited about, which is built in morphing swaps powered by idiomorph, which preserve DOM state such as input focus during updates, and a new hx-partial tag that lets one response cleanly update several targets, a tidier take on out of band swaps.

Attribute inheritance is now explicit, so parent attributes reach children only when marked with an :inherited suffix:

<div hx-confirm:inherited="Are you sure?">
 <button hx-delete="/item/1">Delete</button>
</div>

A detailed DEV Community write up warns this is the trap to watch, because an hx-headers attribute passing a CSRF token to child elements silently stops working without :inherited and the server begins rejecting requests with a 403 while nothing looks broken.

Event names have also been standardised to a htmx:phase:action pattern, so htmx:afterRequest becomes htmx:after:request, and history no longer snapshots the DOM into localStorage, instead refetching pages so third party scripts just work.

A Hacker News thread passed 700 points, with developers praising the Go, SQLite and htmx stack and how well AI assistants handle it, one noting that Claude "understands it and does it well", and the r/htmx release post drew over 300 upvotes.

Elsewhere a .NET and Angular developer argued htmx forces you to mix presentation with business logic and another agreed and said their team is moving back to React.

htmx 4.0 ships under npm's next tag rather than latest, so nobody on an unversioned CDN link is force upgraded, and 2.x stays supported indefinitely. The team provides a command line checker that flags inheritance issues, renamed attributes and old events:

npx htmx.org@4.0.0 upgrade-check -- ./templates

Beyond inheritance changes, there is also a new 60 second request timeout and a number of attribute renames, such as hx-disable becoming hx-ignore. These changes need applying with care. A full What's New in htmx 4 guide is available, and dedicated skills files for LLM assisted upgrades.

htmx is an open source library that adds AJAX, CSS transitions, WebSockets and server sent events directly to HTML through attributes, letting developers build modern interfaces with minimal JavaScript. It remains a flagship of the hypermedia movement, popular with Django, Go and Rails backends where server rendered HTML meets low client side complexity.

Ben Nadel on HTMX

Mike's Notes

The Pipi 9 CMS Engine (CMS) uses HTMX in the rendered User Interface (UI). HTMX interacts directly with the DOM.

Recently, Ben Nadel has been running a fascinating series of blog posts about his coding experiments with HTMX.

He shares a lot of CFML code on his blog, which is freely reusable. I learn a lot from Ben.

I will update this page with additional references to Ben's HTMX posts.

This experiment has a repository on GitHub.

Resources

References

  • Hypermedia Systems by Carson Gross

Repository

  • Home > Ajabbi Research > Library > Subject > CFML
  • Home > Ajabbi Research > Library > Authors > Ben Nadel
  • Home > Handbook > 

Last Updated

17/10/2026

Ben Nadel on HTMX

By: Ben Nadel
bennadel.com: 2025

A Passionate Web Developer With 26 Years Experience.

"I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self! - Ben Nadel"

HTMX 4 Adds findAll Support In CSS Selector Attributes

By Ben Nadel on October 12, 2026

After moving my blog over to HTMX 4, I was excited to learn that HTMX now supports the findAll operation in its CSS selector attributes (such as hx-disable). In earlier versions of HTMX, the find operation scoped the subsequent CSS selector to the host element of the given attribute. Which was helpful; but it could only match a single element. The findAll operation works the same way — scoping the subsequent CSS selector to the host element — but it allows you to match on multiple elements. Which is exactly what I need when submitting forms with HTMX..

read more

Using The HTMX HX-Redirect Header For Loop-Backs In ColdFusion

By Ben Nadel on October 12, 2026

Now that I've migrated my blog off of Hotwire (with Turbo and Stimulus) and onto HTMX 4 and Alpine.js, I'm working out a few long-tail issues. One that I ran into this morning is that HTMX has trouble looping-back to the same page after form-processing if the URL resource of the target page matches the URL resource of the current page...

read more

Preventing HTMX And Alpine.js From Binding To User Generated Content

By Ben Nadel on October 02, 2026

On this blog, I try to keep things securely locked down. On the ColdFusion side, I run all user generated content (UGC) through a JSoup sanitizer (though I previously used the OWASP AntiSamy project); and now that I've switched my client side libraries from Hotwire (Turbo and Stimulus) over to HTMX 4 and Alpine.js, I want to make double sure that nothing in the UGC output accidentally triggers HTMX or Alpine.js behaviors...

read more

You Can CMD+Click To Submit A Form To A New Browser Tab

By Ben Nadel on May 29, 2025

In the past couple of months, I've been digging into the HTMX JavaScript framework as a way to layer dynamic client-side functionality on top of my ColdFusion applications. I'm enamored with HTMX; but, unlike as with other frameworks such as Angular or Svelte, HTMX doesn't want to be an end-to-end holistic solution. Which means, I—as the developer—have to make a lot of decisions about where logic should live; and, whether or not something is a good idea. This is turning out to be a lot harder than I first imagined...

read more

Creating An hx-event Extension For Triggering Events In HTMX

By Ben Nadel on May 21, 2025

I'm still very deep in the "learning phase" of using HTMX, trying to understand how things are wired together and where the jagged edges might be. As a code kata, I wanted to see if I could create an HTMX extension that would trigger an event instead of an AJAX call. This way, I might be able to click on a button and bubble a synthetic event up the DOM (Document Object Model) tree to another element that is using an hx-on:{event} binding...

read more

Considering The Functional Requirements Of A Modal Window In An HTMX Web App

By Ben Nadel on May 17, 2025

To start with, I'm not a huge fan of modal windows in a web application. InVision used a ton of modal windows; and it felt like we painted ourselves into a corner that we couldn't get out of. My ambiguity on the matter has only been hardened by articles such as "we use too many damn modals", "modalz modalz modalz", and "who's afraid of a hard page load". That said, modals—and modal-adjacent experiences—do have their place. And, as I start to think about this experience in the context of an HTMX-powered web app, I wanted to come up with a set of functional requirements that I could aim for...

read more

Using A No-Content URL To Help Manage DOM Caching In HTMX And ColdFusion

By Ben Nadel on May 14, 2025

When you hx-boost / AJAX'ify your ColdFusion application with HTMX, HTMX will cache the state of the DOM (Document Object Model) as you navigate from page to page. This way, when you hit the browser's back button, HTMX can restore the previous DOM state, pulling it out of the LocalStorage API. The caveat being, HTMX only does this in response to an AJAX request. Which means, if we want to cache the current state of the DOM, we must issue an AJAX request and we must change the URL...

read more

HTMX Extensions Have Access To An Extended API

By Ben Nadel on May 12, 2025

The HTMX JavaScript framework exposes a public API that is a mixture of convenience methods, such as htmx.on() for event-binding; and framework-specific methods, such as htmx.process() for initializing externally-loaded HTML fragments. When creating an extension in HTMX, the extension's init() method is passed an api argument. At first, I thought this was just an abstracted reference to the aforementioned public API. But, upon further inspection, this reference contains an extended API to help specifically with HTMX extension authoring...

read more

What Happens When You Mutate The DOM Outside Of HTMX

By Ben Nadel on May 10, 2025

In a previous post, I looked at using Alpine.js inside an HTMX application. Since Alpine.js uses the MutationObserver API to observe changes within the Document Object Model (DOM) structure, it doesn't much matter where mutations are initiated. HTMX, however, isn't quite so dynamic. As such, I wanted to sanity check what happens when DOM mutations are initiated outside of the HTMX life-cycle...

read more

Returning JavaScript Tags In HTMX And ColdFusion

By Ben Nadel on May 8, 2025

The primary mechanic of HTMX is swapping out branches of the DOM (Document Object Model) in response to user interactions. Yesterday, however, I had to update a bunch of form inputs based on a <select> change. I wasn't sure how to do this in the cleanest "HTMX Way". Eventually, I settled upon a happy medium in which I use HTMX to execute one-off JavaScript task via an Out of Band (OOB) swap of a <script> tag...

read more

Using Stale-While-Revalidate Cache-Control Headers In HTMX And ColdFusion

By Ben Nadel on May 6, 2025

In my ColdFusion applications, unless I'm generating dynamic images that need to be cached, I almost never use the Cache-Control HTTP headers. Historically, all of my "caching needs" for perceived performance have been handled in my client-side Angular controllers. But, the HTMX JavaScript framework is all about leaning on the web platform to drive application mechanics. As such, I wanted to see how I might use the stale-while-revalidate response directive to boost performance in an HTMX and ColdFusion application...

read more

Keyboard Command Extension In HTMX And ColdFusion

By Ben Nadel on May 3, 2025

Earlier this week, I took a look at using extensions in an HTMX and ColdFusion application. Extensions allow us to tap into the event life-cycle of nodes withing the document object model (DOM); which, in turn, allows us to augment the document behavior as HTMX swaps content into and out of the rendered page. For this follow-up post, I take inspiration from the Docket app by Mark Story. Mark's HTMX and PHP app allows keyboards events to trigger DOM interaction. I wanted to try building something similar for a ColdFusion demo...

read more

Exploring Extensions In HTMX

By Ben Nadel on May 1, 2025

The HTMX JavaScript framework operates by traversing your Document Object Model (DOM) looking for elements that match a set of criteria, such as the existence of an hx-get or an hx-post attribute; and then, processes the matching elements by applying new behaviors. As it orchestrates these modifications, it emits a series of events on the DOM. Informally, these events can be a way for any JavaScript library to hook into the HTMX life-cycle by consuming the DOM as an event-bus; but, HTMX also provides an official way of doing this by using extensions...

read more

Using :scope To Identify The Host Element In .querySelectorAll()

By Ben Nadel on April 29, 2025

Here's a helpful tip that I learned the other day. When using a Document Object Model (DOM) method to query for HTML elements using a CSS selector (ex, .querySelectorAll()), the :scope pseudo-class can be used to identify the host element on which the method is being called. This allows us to use the direct descendant selector (>) to target children of the host element...

read more

Using hx-preserve To Persist Elements Across Swaps In HTMX

By Ben Nadel on April 27, 2025

With HTMX, you can use the hx-boost attribute to AJAX'ify navigation in your ColdFusion applications. Boosting pages increases the complexity of the application and can lead to some strange JavaScript behaviors. But, this trade-off in complexity ushers in the ability to maintain some state across pages. And one way to maintain state in HTMX is with the hx-preserve attribute...

read more

Previous / Next <CSS Selector> Both Use A Depth-First Algorithm In HTMX

By Ben Nadel on April 26, 2025

In the HTMX JavaScript framework, the hx-target attribute can reference other elements in the DOM (Document Object Model) by using CSS selectors, convenience keywords (such as this and next), and a combination thereof. Most of these are relatively straightforward; but, I ran into surprising results when using previous {CSS selector} and next {CSS selector}. I had read the documentation and interpreted it as meaning that the targeted elements were direct descendants of the same parent element. But, this is incorrect. Internally, HTMX is using a depth-first traversal algorithm—from the document root—to find the target nodes; and then, selects the one closest to the trigger element based on a depth-first node traversal order...

read more

Fetch API Will Propagate Non-POST Methods Upon Redirect

By Ben Nadel on April 26, 2025

In the book Hypermedia Systems by Carson Gross, the authors mention that the browser will propagate the HTTP Method upon redirect. In all my years of programming, I had never seen this; so, I sanity checked it and put the issue to rest in my head. Then, yesterday, I was listening to the Remote Ruby podcast with Chris Oliver and Andrew Mason, and they too mentioned this HTTP method propagation specifically for the JavaScript fetch() API. I feel like I was taking crazy-pills; so, I went to sanity check it again; and, discovered that the fetch() API will propagate the HTTP method; but, only for non-GET/POST methods...

read more

Using Alpine.js In HTMX

By Ben Nadel on April 25, 2025

The HTMX JavaScript framework allows us to move a lot of state management out of the browser and back into the ColdFusion server where the "source of truth" resides. But, not all interactions—and not all state—need to be sourced from the server. In such cases, we can use Alpine.js to provide light-weight state management and event binding in the browser. That said, both HTMX and Alpine.js want to "manage the DOM" and the event-bindings. As such, it's not obvious that they'll play well together. To get a sense of where the points-of-friction might lie, I wanted to put together a small demo that uses both HTMX and Alpine.js as well as the hx-boost attribute to "AJAX'ify" the page navigation

read more

Filtering HX-Trigger Server Events In HTMX And ColdFusion

By Ben Nadel on April 22, 2025

When building Single-Page Applications (SPA) with Angular and ColdFusion, one common pattern that I used was to return an event in every mutation-based API response. This event was then triggered on a client-side event-bus; and, various Angular components could respond to it as needed. In an HTMX multi-page application (MPA), we can use the HTTP response header, HX-Trigger, to achieve similar outcomes. And, we can use the filtering capabilities of the client-side hx-trigger attribute to limit the scope of this client-side response...

read more

Conditionally Preventing HX-Boost In HTMX Using An Extension

By Ben Nadel on April 19, 2025

In an HTMX application, the built-in hx-boost attribute tells HTMX to intercept all form and anchor interactions and "AJAX'ify" them. That is, prevent the default browser behavior and re-implement it using AJAX and the History API in order to side-step a full page-load. This is a neat feature; but, it doesn't have any hooks (that I can find) to conditionally prevent hx-boost from acting on a given link. Such a hook would be necessary when integrating content that comes out of a content management system (CMS). To try and add such a hook, I've created my first HTMX extension, prevent-boost, that can conditionally prevent boosting based on RegEx patterns and / or filter callbacks...

read more

Comparing Undefined Values With Optional Chaining In JavaScript

By Ben Nadel on April 17, 2025

Yesterday, while working on some HTMX experiments, I stumbled upon a feature of JavaScript that I didn't known: the undefined value, when compared to Booleans and numbers, always returns false. I've always thought of undefined as a falsy value (which it is); so, I was very surprising to see that undefined did not soft equal false. But, this turns out to be hugely beneficial when it comes to the optional chaining operator (aka, the safe navigation operation) in JavaScript...

read more

HTTP GET And HTTP POST Are Sufficient (For Me) In ColdFusion

By Ben Nadel on April 14, 2025

As of this writing, HTML supports two different HTTP methods: GET and POST. And for the last 25-years, I've been building web-based applications very successfully on top of these two operation. Many people, however, are not satisfied with these limitations; and, would like to see PUT, PATCH, and DELETE added to the list of natively supported methods in HTML. Personally, I'm quite satisfied with GET and POST and haven't really experience any pain-points. So, I thought it might be interesting to try and articulate my perspective....

read more

ColdFusion And HTMX Contact App

By Ben Nadel on April 13, 2025

A couple of weeks ago, I read Hypermedia Systems by Carson Gross. The book is an introduction to HTMX - a JavaScript library that extends the HTML specification and brings dynamic single-page application (SPA) type features to a traditional multi-page application (MPA) architecture. Some of the aspects of HTMX are fairly simple; but, some require a sizable mindset shift. As such, I thought it would be helpful (for me) to take the "contacts app" that Carson builds in the book and translate it into a ColdFusion application context.... 

read more

Hypermedia Systems By Carson Gross

By Ben Nadel on February 18, 2025

Last week, Peter Amiri - maintainer of the CFWheels framework for ColdFusion - sent me a hardcover copy of Hypermedia Systems by Carson Gross, Adam Stepinski, and Deniz AkÅŸimÅŸek. This book argues for the benefits of "Hypermedia Driven Applications" (HDA); and how leaning into the foundational nature of the web as a unified interface and hypermedia platform makes applications easier to build and more accessible while still achieving a high-bar of interactivity. This book is clear, concise, and quite compelling. Coming in at around 300 pages, I finished reading it in two day—I just couldn't put it down.....

read more

HTMX history and the back button

Mike's Notes

I have been building a ribbon UI component and experimenting with different ways to do this. You can go and try them out.

  • Version 1 (Uses CSS, tabs not stable)
  • Version 2 (Uses HTMX)
  • Version 3 (Uses CSS and HTMX; tabs not stable)
  • Version 4 (Uses CSS and HTMX, tabs are stable, and the back button works)

Version 4 is OK.

To get the browser back button to work, I added the meta HTML code below

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

18/05/2025

HTMX history and the back button

By: Mike Peters
On a Sandy Beach: 18/09/2024

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Code

<meta name="htmx-config" content='{"refreshOnHistoryMiss":"true"}' />

Dynamic Web Apps without JavaScript - HTMX Showcase at DjangoCon and Devoxx

Mike's Notes

Discovering this presentation at QCon solved many problems and simplified the building of the Pipi UI.

Resources

References

  • Architectural Styles and the Design of Network-based Software Architectures by Roy Fielding

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

17/05/2025

Dynamic Web Apps without JavaScript - HTMX Showcase at DjangoCon and Devoxx

By: Bruno Couriol
InfQ.com: 21/10/2022

DjangoCon and Devoxx Belgium recently reported examples of interactive web applications developed without JavaScript developers. The showcased htmx HTML-first framework seems to target those applications that mainly propose a friendly interface to CRUD operations over remote resources. In one case, the team was able to remove the JavaScript developer.

At DjangoCon 2022, David Guillot reported reimplementing his company’s SaaS product with HTML-first framework htmx in two months with the following results:

Guillot gladly mentioned that 15,000 lines of JavaScript code disappeared from the codebase; performance improved (as measured by time to interactive and memory usage); the only JavaScript developer in the team left and back-end developers turned to full stack developers.

The htmx team however warns that such spectacular results were achieved because this particular SaaS application was a good fit for htmx’s HTML-first approach:

These are eye-popping numbers, and they reflect the fact that the Contexte application is extremely amenable to hypermedia: it is a content-focused application that shows lots of text and images. We would not expect every web application to see these sorts of numbers.

However, we would expect many applications to see dramatic improvements by adopting the hypermedia/htmx approach, at least for part of their system.

At Devoxx Belgium 2022, Wim Deblauwe showcased the kind of interactivity that htmx can implement without any JavaScript: search-as-you-type input field, update of the user interface as some remote resource is affected by CRUD operations, regularly refresh the user interface with server-sent data, and more.

The htmx team considers an application a good fit for the framework if the UI is mostly text and images; the UI mostly interfaces CRUD operations; and HTML updates mostly take place within well-defined blocks. Conversely, applications with many, dynamic interdependencies, that require offline functionality, or update state extremely frequently would not be a good first for htmx’s hypermedia approach.

In an htmx application, the server returns pages or fragments of pages.

<button hx-post="/clicked"

    hx-trigger="click"

    hx-target="#parent-div"

    hx-swap="outerHTML">

    Click Me!

</button>

The previous HTML excerpt encodes that when a user clicks on the button, htmx issues an HTTP POST request to the /clicked endpoint. Htmx uses the content from the posterior response to replace the element with the id parent-div in the DOM. With htmx, any element (i.e., not just anchors and forms), any event can trigger an HTTP request. The HTML response from the server only updates the relevant part of the UI. For the full overview of htmx capabilities, developers may refer to the documentation.

Interestingly, htmx is often showcased by back-end developers who belong to non-JavaScript ecosystems (e.g., Python/Django/Flask, PHP/Laravel, Ruby/Ruby on Rails). As Guillot mentioned, with htmx, back-end developers extend their scope to the entire stack without having to learn JavaScript, npm, Webpack, React, CSS-in-JS, and many more. Matt Layman, in his You don’t need JavaScript talk summarizes:

"It’s just this constant churn in the [JavaScript] ecosystem and adding a lot of complexity onto a flow when you’re trying to deliver a web application. You want to just get an experience out there that actually works for people. But then you end up fighting with [the toolchain].

…

At a certain amount of scale, JavaScript can be a fantastic thing to build into your applications. But for an average person or a small team, it’s a ton of extra complexity so my recommendation is: just don’t. We have other options."

htmx is an open-source project under the BSD-2-clause license.

htmx claims to provide AJAX, CSS Transitions, WebSockets, and Server-Sent Events directly in HTML, using attributes, so developers can build user interfaces with the simplicity and power of hypertext.

HTMX

Let’s look at the first feature of htmx: the ability of any web page element to issue HTTP requests. This is the core functionality provided by htmx, and it consists of five attributes that can be used to issue the five different developer-facing types of HTTP requests:

hx-get

Issues an HTTP GET request.

hx-post

Issues an HTTP POST request.

hx-put

Issues an HTTP PUT request.

hx-patch

Issues an HTTP PATCH request.

hx-delete

Issues an HTTP DELETE request.

hx-target

Relative Positional Expressions in Htmx.
  • next - Scan forward in the DOM for the next matching element, e.g., next .error
  • previous - Scan backwards in the DOM for the closest previous matching element, e.g., previous .alert
  • closest - Scan the parents of this element for the matching element, e.g., the closest table.
  • find - Scan the children of this element for matching element, e.g., find the span.
  • this - the current element is the target (default)

hx-swap

The hx-swap attribute supports the following values:

  • innerHTML - The default, replace the inner html of the target element.
  • outerHTML - Replace the entire target element with the response.
  • beforebegin - Insert the response before the target element.
  • afterbegin - Insert the response before the first child of the target element.
  • beforeend - Insert the response after the last child of the target element.
  • afterend - Insert the response after the target element.
  • delete - Deletes the target element regardless of the response.
  • none - No swap will be performed.
  • settle -Like swap, this allows you to apply a specific delay between when the content has been swapped into the DOM and when its attributes are “settled”, that is, updated from their old values (if any) to their new values. This can give you fine-grained control over CSS transitions.
  • show - Allows you to specify an element that should be shown — that is, scrolled into the viewport of the browser if necessary — when a request is completed.
  • scroll - Allows you to specify a scrollable element (that is, an element with scrollbars), that should be scrolled to the top or bottom when a request is completed.
  • focus-scroll - Allows you to specify that htmx should scroll to the focused element when a request completes. The default for this modifier is “false.”

hx-include


hx-vals


hx-push-url

“Pushes” the request URL (or some other value) into the navigation bar.

hx-location

Causes a client-side redirection to a new location

hx-preserve

Preserves a bit of the DOM between requests; the original content will be kept, regardless of what is returned.

hx-sync

Synchronized requests between two or more elements.

hx-disable

Disables htmx behavior on this element and any children. We will come back to this when we discuss the topic of security.

hx-boost


hx-confirm


hx-indicator

Let the user know that a search is in progress.

HTTP Request

When placed on an element, each attribute tells the htmx library: “When a user clicks (or whatever) this element, issue an HTTP request of the specified type.”

HX-Boosted

This will be the string “true” if the request is made via an element using hx-boost.

HX-Current-URL

This will be the browser's current URL.

HX-History-Restore-Request

This will be the string “true” if the request is for history restoration after a miss in the local history cache.

HX-Prompt

This will contain the user response to an hx-prompt.

HX-Request

This value is always “true” for htmx-based requests.

HX-Target

This value will be the id of the target element if it exists.

HX-Trigger-Name

If it exists, this value will be the name of the triggered element.

HX-Trigger

If it exists, this value will be the ID of the triggered element.
once. The given event will only trigger a request once.
  • delay - Allows you to specify a delay to wait before a request is issued. If the event occurs again, the first event is discarded and the timer resets. This allows you to “debounce” requests.
  • changed - Allows you to specify that a request should only be issued when the value property of the given element has changed.
  • throttle - Allows you to throttle events, only issuing them once every certain interval. This is different than delay in that the first event will trigger immediately, but any following events will not trigger until the throttle time period has elapsed.
  • from - A CSS selector that allows you to pick another element to listen for events on. We will see an example of this used later in the chapter.
  • target - A CSS selector that allows you to filter events to only those that occur directly on a given element. In the DOM, events “bubble” to their parent elements, so a click event on a button will also trigger a click event on a parent div, all the way up to the body element. Sometimes you want to specify an event directly on a given element, and this attribute allows you to do that.
  • consume - If this option is set to true, the triggering event will be cancelled and not propagate to parent elements.
  • queue - This option allows you to specify how events are queued in htmx. By default, when htmx receives a triggering event, it will issue a request and start an event queue. If the request is still in flight when another event is received, it will queue the event and, when the request finishes, trigger a new request. By default, it only keeps the last event it receives, but you can modify that behavior using this option: for example, you can set it to none and ignore all triggering events that occur during a request.