
Htmx – high power tools for HTML - oftenwrong
https://htmx.org/
======
recursivedoubts
hello, I'm the creator of htmx (and originally intercooler)

I just released 0.0.4, so htmx is still very young, but it's got a decent test
suite: [https://htmx.org/test/0.0.4/test/](https://htmx.org/test/0.0.4/test/)

there is a nice extension mechanism:

[https://htmx.org/extensions/](https://htmx.org/extensions/)

and some very rough docs on how to pull off pure HTML animations:

[https://htmx.org/examples/animations/](https://htmx.org/examples/animations/)

happy to answer questions

~~~
gavinray
I've heard of Intercooler before and saw htmx on Github trending a few weeks
ago.

A question about this example: [https://htmx.org/examples/inline-
validation/](https://htmx.org/examples/inline-validation/)

This paradigm revolves around sending validation requests to server-side
endpoints, is there any reason to put that load on the server rather than
validate it on the page prior to submit with JS? Or scalability issues?

Not being antagonistic, genuinely curious because I've not seen inline
validation done this way.

~~~
recursivedoubts
I'm not dogmatic about it. Some validation has to be done on the server side
(e.g. unique emails) and any validation has to be redone on the server anyway
since the client side isn't a trusted computing environment, but I can see
doing both.

~~~
gavinray
Ahh got it, yeah in this case that makes a ton of sense. No way to know with
emails about uniqueness constraints until it hits the backend anyways.

I've been playing around with local demo, is it possible through extensions to
make a wrapper that can perhaps compose GraphQL query inputs from forms?

~~~
recursivedoubts
yeah, you could use the json encoding extension as a starting point:

[https://htmx.org/extensions/json-enc/](https://htmx.org/extensions/json-enc/)

~~~
gavinray
I was just trying that, it seemed not to be working for some reason.

I manually copy-pasted the source code into my app, and got:

    
    
        htmx.min.js:1 TypeError: Cannot set property 'Content-Type' of undefined
            at Object.encodeParameters ((index):11)
            at htmx.min.js:1
    

The code for it is:

xhr.requestHeaders['Content-Type'] = 'application/json'

But I believe it should be

xhr.setRequestHeader('Content-Type', 'application/json')

When I do this, it seems to work

[https://developer.mozilla.org/en-
US/docs/Web/API/XMLHttpRequ...](https://developer.mozilla.org/en-
US/docs/Web/API/XMLHttpRequest/setRequestHeader)

~~~
recursivedoubts
looks like there's a bug in the json-enc extension: it's relying on the test
mock which has a requestHeaders property that a real xhr won't.

so the tests passed but it doesn't work irl...

good catch! want to submit a pull request fix?

~~~
gavinray
Sure =D

Done!

Also this extension API is pretty straightforward, the element reference and
parameters are right in the args so it's an easy mapping to GraphQL query
strings from there. Awesome!

I was able to get a minimal version working using just this (with json-enc
extension patch):

    
    
        <input
          type="text"
          name="query"
          hx-ext="json-enc"
          hx-post="http://localhost:8080/v1/graphql"
          hx-trigger="keyup changed delay:500ms"
          hx-target="#search-results"
          placeholder="<GRAPHQL QUERY TEXT HERE>"
        />
        <div id="search-results"></div>
    

Pretty cool

~~~
recursivedoubts
i'd love a graphql extension for the next release, if you are interested

~~~
gavinray
Yeah, definitely game to help out there =)

~~~
bg0
Hell yea

------
wenc
This looks amazing -- seems like you can accomplish a significant amount of
what constitutes front-end work these days with htmx. The examples are
compelling:

[https://htmx.org/examples/](https://htmx.org/examples/)

There is a slight deal-breaker for me. Much of the functionality revolves
around hx-swap'ing i.e. writing the contents of a response as HTML into/around
tags. This requires the server-side to return HTML instead of JSON. From the
docs:

"Note that when you are using htmx, on the server side you respond with HTML,
not JSON. This keeps you firmly within the original web programming model,
using Hypertext As The Engine Of Application State without even needing to
really understand that concept."

I would love to use this with existing REST backends, but most are only able
to return JSON. How does one use this for AJAX without rewriting existing
backends?

~~~
hliyan
On a related note, I recently discovered that when you use semantically styled
HTML, the difference between a JSON payload and an HTML payload is almost
negligible (basically, the close tags). Why not transmit in a format that the
browser already understands natively?

~~~
vosper
Because oftentimes you’re retrieving data that will be stored in one central
store and displayed / used in different ways in various components. Eg I might
fetch user data and sometimes display their name, maybe another time compute
their age from their birthdate, etc...

~~~
nogabebop23
What's the difference between building seperate code paths on the client vs. 2
server endpoints though? Very few scenarios can't afford the behind-the-scenes
extra http round trip...

~~~
vosper
Because I don't want to build and maintain an API endpoint to give me an HTML
blob for the users age, and another one for their full name, and another one
just for their first name, and another one for figuring out what day of the
year is their birthday. I want adding these features to my UI to be a client-
side-only change.

------
fastball
For similar-goal prior-art, see Unpoly[1].

Also the IETF asks[2] that you please stop using "X-" to prepend your custom
HTTP headers[3]

[1] [https://unpoly.com/tutorial](https://unpoly.com/tutorial) [2]
[https://tools.ietf.org/html/rfc6648](https://tools.ietf.org/html/rfc6648) [3]
[https://htmx.org/reference/#headers](https://htmx.org/reference/#headers)

~~~
recursivedoubts
I like unpoly a lot, Henning is a perfect gentleman, but the first check in on
intercooler.js was before the first check in on unpoly:

[https://github.com/bigskysoftware/intercooler-
js/graphs/cont...](https://github.com/bigskysoftware/intercooler-
js/graphs/contributors)

[https://github.com/unpoly/unpoly/graphs/contributors](https://github.com/unpoly/unpoly/graphs/contributors)

I'm happy to change the headers htmx is young enough to get away with it.
Would you like to issue a pull request?

~~~
fastball
Fair point – though some might say if you start over in a new repo then you
have reset the clock ;). In all honestly though, wasn't trying to imply that
this project ripped off Unpoly or anything, just wanted to mention a similar
project. Perhaps poor phrasing on my part.

As to a PR for the headers – I might just take you up on that!

~~~
laingc
I read nothing but good intent in your comment, so this is not me throwing
stones, but one comment I would make is that I think using the term "prior
art" \- coming as it does from patent law - carries an overtone of "I am
implying that you might have ripped off someone else's idea".

It's clear that this is not what you intended, but I think from the response
from the creator, that was the tone that you accidentally conveyed.

Just a thought for the future :-).

------
ksec
I wish some of this ( or All of it ) are implemented inside browser and no
longer need any Javascript to function.

Web App still has its place. But 90% of the web are Web Pages or Interactive
Web Page, not Apps. While Every time I point this out there will be someone
stating Gmail as an example of Web Apps, but we will soon have Hey.com to
prove it doesn't need to be that way.

However browser vendors and standards body ( Which really is just browser
vendors ) has far too much interest in making the Web or Web Browser as
another OS / Platform. Rather than optimising for the 90% of our current use
case.

~~~
eitland
I've been mentioning this together with a very slimmed down html5 for a while
now:

\- make something close to an html5 equivalent to asm.js: remove all ambiguous
variants, everything we know is slow.

\- "ban" all Javascript except some small pre-defined libraries like this.

\- make a catchy name (html-core? web-core?) and a validator for it. Call it a
standard.

It will be fast in all browsers, maybe really fast in browsers that care to
optimize for it.

If it becomes a thing we can create new simpler pure web browsers (as opposed
to todays application platforms that we will then start calling old or legacy
html :-)

------
jedieaston
If you don’t know, this is a rewrite of Intercooler.js without depending on
jQuery. It’s awesome!

------
uallo
Similar projects:

[https://github.com/stimulusjs/stimulus](https://github.com/stimulusjs/stimulus)

[https://github.com/alpinejs/alpine](https://github.com/alpinejs/alpine)

[https://github.com/intercoolerjs/intercooler-
js](https://github.com/intercoolerjs/intercooler-js)

~~~
sica07
You are comparing apple to oranges :) alpine and stimulus are frameworks
(doing all sorts of stuff: css animation, data <-> objects, etc) while htmx is
a library focusing solely on ajax. From your list, the only similar project to
htmx is intercooler-js, but... htmx is actually the new version of
intercooler-js (both projects by the same author).

~~~
uallo
> htmx is a library focusing solely on ajax

htmx supports animations too, and it has extensions to add further
functionality. Of course those projects differ in their functional range, but
they share the way they work; by adding attributes to HTML.

~~~
sica07
Yes, you are right. My response was based on the presentation from the first
page: "htmx allows you to access AJAX, WebSockets and Server Sent Events
directly in HTML, using attributes". In the meantime I read the documentation
and, as you just said, it supports animations and much more.

------
redindian75
From IntercoolerJS website "Work on intercooler 2.0 (renamed to HTMX) has
begun. See htmx.org for more information!"

------
sam_goody
The js via html tags is something I see also in Alpine.js, which has gotten a
lot of press lately.

Is this an alternative, or is each really its own niche (and you might use
both)? Is there a comparison?

Edit: It seems that htmx is almost entirely around AJAX, and Alpine around a)
binding element data to objects and b) css & animations (such as hiding a
popup). It would make a lot of sense to use them together (and the hx- even
complements the x-). Is that correct?

~~~
wysewun
Yeah some kind of bridge between the two would be great. They both seem to
have different areas of specialization

------
tangue
I wish Intercooler and htmx were more popular. But I think that practical
examples, copy and pastable code, youtube tuts are keys for a library to
succeed. Think about php manual, react... There's often no need for some
websites to bring big frameworks but they're well documented. That's the new
nobody ever got fired for buying IBM.

------
abhiminator
Slightly off-topic, but here's another fine example of how appending 'x' makes
almost _any_ name look cool.

------
tannhaeuser
I like it, though I guess the "implementation" for what JavaScript gets
executed on a given custom HTML attribute set is "hardcoded" in the htmx lib.
With SGML, OTOH, you can have your own replacement content (JavaScript, other
HTML, or whatever; it's just syntactical replacement). Would be an interesting
experiment to implement the htmx vocabulary on top of SGML.

------
JadeNB
On the chance that the authors are here: on
[https://htmx.org/docs](https://htmx.org/docs) , there is a link "original web
programming model" where the target is (for some reason) surrounded by
parentheses, so that it points to the wrong location.

~~~
recursivedoubts
fixed, thanks

~~~
persona
On docs fix reporting, there is also a typo on

[https://htmx.org/extensions/client-side-
templates/](https://htmx.org/extensions/client-side-templates/)

any element below it in the DOM can use one of three attributes named
<template-engine>-temlpate ____

------
xrd
How do you test applications written with Htmx? Does it all need to be ui test
harness (running in a browser), or can you unit test components somehow?

I'm happy you noted the test coverage for the library itself is reaching your
standards. That's a great sign.

~~~
recursivedoubts
You can use the same technique I use in my tests: sinon.js has FakeServer that
mocks AJAX calls.

I think I'd look into a headless chrome setup against my real server if I was
doing a large app.

------
XCSme
This is pretty cool.

Does it only send data? If yes, I don't really see a clear use-case for it, as
you normally either want zero JS and just use plain HTML forms posting or you
have a dynamic interface and you use a lot of JS to update data on the page.

~~~
apineda
What else would you send?

~~~
XCSme
Not to send data, but receive data and update the UI accordingly. I looked a
bit through their examples and it seems that they expose a way to update the
UI with the response from the AJAX calls, but probably server has to return
the entire HTML code?

~~~
recursivedoubts
yes, responses are expected to be in HTML

but you can use the client-side-templates plugin if you want to run responses
through a client-side template engine:

[https://htmx.org/extensions/client-side-
templates/](https://htmx.org/extensions/client-side-templates/)

------
maddyboo
Very cool. This seems very useful for lightweight UIs that need a small amount
of interactivity, but not enough that a more heavyweight framework like React
would make sense. Am I on the right track?

~~~
recursivedoubts
you can build a pretty serious app with it

the progress bar demo shows how you can implement a UI that would typically be
done w/ javascript using pure HTML responses:

[https://htmx.org/examples/progress-bar/](https://htmx.org/examples/progress-
bar/)

------
midrus
One of the problems I see is that now anyone that was using intercooler is
using an outdated and quite likely to become unmaintained library and be
forced to migrate/rewrite things.

~~~
edwinyzh
Yes, I wish the author will offer a smooth upgrade path for the existing
intercooler.js users, because my heard wants such a thing to be adopted by
people. I like the concept very much!

------
winrid
Reminds me of AngularJS... :) Much simpler overall though. I like it.

~~~
bufferoverflow
It reminds me more of jQuery. And while I see how it's great for quick
prototyping, it's going to be a nightmare in a large project. I really like
React, where data and HTML are clearly separate. I don't want to send raw HTML
back and forth, I want to send only data.

~~~
winrid
It doesn't look like this requires you to send raw HTML back and forth. Also,
jQuery did not have this kind of data-in-html syntax...

------
coderintherye
How much work / code is required in order to make this IE compatible? I ask,
since the project is young, it would seem like a good time to make the hard
choice to not support IE.

~~~
recursivedoubts
there are a few areas where I need to check for nulls and i can't use some of
the es6 niceties, but it's not too bad

the 'revealed' event logic doesn't use an intersection observer because of IE,
that's probably the most annoying thing I can think of

------
iddan
The haiku is a nice touch

------
k__
How does it compare to intercooler?

What's the Accessibility story?

~~~
madeofpalk
What are your Accessibility concerns with this?

~~~
tylerchilds
A quick skim, the divs with click handlers.

~~~
madeofpalk
Don’t put click handlers on divs? Shame the docs feature that though.

------
yepthatsreality
Very cool. Will use this soon in a project.

------
mikeg8
This looks awesome! Can’t wait to dive in a little deeper and try it out on
some upcoming side projects. Thank you!

------
aabbcc1241
This seems encouraging a fair rebalanced on works between the server and the
client, looks promising

------
woah
The example on the front page already hints at the type of bad programming
this may encourage. When clicked, the button sends a POST (this seems ok), and
then the backend sends new html for the button. The idea of having random
snippets of your frontend markup being returned from api servers seems
questionable.

~~~
latch
I'm not sure I get what you're saying?

I think you're saying that having html returned from the backend "seems
questionable" and is a "type of bad programming".

But that can't be right because that's mostly how the web works? Make a
request to a server, server returns html.

Is your issue that it's partial "random" content? How does that make it worse?
It's a tried and true solution. The hamburger menu in amazon.com does just
that.

~~~
Thorentis
I agree that the objection doesn't hold up given how many websites are made,
but I think they mean that a REST API shouldn't be returning HTML, which is
true. Unfortunately using the replace feature would mean rewriting existing
APIs.

Or, you could use the client side template feature of htmx which supports
rendering JSON into HTML using a templating language:
[https://htmx.org/extensions/client-side-
templates/](https://htmx.org/extensions/client-side-templates/)

~~~
recursivedoubts
> REST API shouldn't be returning HTML, which is true.

No, it isn't. REST implies HATEOAS, and JSON isn't a hypertext.

Calling JSON APIs REST-ful was always a mistake.

[http://intercoolerjs.org/2016/05/08/hatoeas-is-for-
humans.ht...](http://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.html)

------
vz8
Can you use hx-swap-oob to update multiple elements with a single call?

The haiku is a nice touch!

~~~
recursivedoubts
yes, you can send down a bunch of content targeting different elements by id
on the page

~~~
vz8
Very nice. Thanks, looking forward to playing with this over the weekend.

------
apolymath
I'm a proponent of the natural web, where the focus of web development lies
with W3C compliant HTML & CSS sprinkled with very small amounts of JavaScript
(if necessary). Any JS frameworks that requires the user to modify their HTML
to include non-W3C complient HTML attributes is a very poor architectural
decision and should be avoided. Such frameworks include Angular.
Unfortunately, your framework also falls into this category.

~~~
recursivedoubts
you can use data- prefixes if you like

------
dynamite-ready
This sounds a lot like Macromedia Cold Fusion, from back in the day, no?

------
stephenr
I like the theory of this (that is: using XHR to update parts of a page with
the result of requests)

I'm immediately turned off by the demo though, because it's relying on a 'fake
http server' in the client side JS.

If your toy examples can't be run against a real server, I have zero
expectation of it working well for non-trivial examples.

~~~
matsemann
"Can't be run against a real server" sounds like a straw man you just made up?
I'm astonished about how much you believe you can ascertain based on this...
It's a demo, mocking a server is completely fine and also allow them to show
it working without relying on other things.

I mean, this is actually even better. You can expand the mock-server down
below and see what's happening.

~~~
stephenr
Would you buy a car if when you took it for a test drive, it had no engine but
instead the salesman sat next to you and made "vrrm vrrm" noises for 20
minutes?

~~~
chewmieser
Are you purchasing this JS library? Does it not make sense to reduce server
load in order to reduce the cost of demonstrating a free product?

~~~
stephenr
Using the library is an investment of time, and time is worth money, so yes.

Reducing server load makes sense. Use a CDN or proxy, and aggressively cache
responses.

Adding an entirely faked backend response, so that the examples don't actually
show the real traffic it would generate is both adding complexity to the demo,
and potentially giving a misleading picture of how usable the library is: for
all we know, it's too slow to use as the examples show, because a real HTTP
request to a backend is going to be slower than a javascript function
returning a pre-determined string.

~~~
BareNakedCoder
If instead the salesman took you and a car that included an engine out on a
test track, would you not buy the car because the test track was fake? You are
not buying the test track so you shouldnt care. You are not buying htmx's demo
backend either so you shouldnt care.

~~~
stephenr
In your analogy the 'test track' is still close enough to a real road - just
as a functional backend providing fake data is real enough to test the
functionality.

