scy,
@scy@chaos.social avatar

I've spent a few days playing around with #HTMX, and I'd like some insights from people who are using it in production. Doesn't need to be a paid project, but more than just "my pet experiment".

What are you using it for?

Like, to me it feels as if either the backend needs to be really tailored to HTMX, with HTML fragments and custom headers and stuff, or you need to start writing non-trivial amounts of JS in the frontend for anything but the most basic tasks.

#WebDev

kly,
@kly@fosstodon.org avatar

@scy I'm using it in production at work because I just wrote the backend, which is a straightforward REST api.

I don't like it.

Sure, some things are easier, but we've had to make a ton of adaptations on a backend that SHOULD have been just a jinja template engine. Instead of just a handful of simple js stuff.

I think the appeal is mostly "everything else is too big and spending thirty minutes writing vanilla JavaScript is just too much work".

kly,
@kly@fosstodon.org avatar

@scy And people forget that web development around year 2000 sucked. Also, htmx is just an other JavaScript framework, just don't tell anyone.

scy,
@scy@chaos.social avatar

@kly See, that is the impression I get, too.

I wonder whether a JS library that combined

• HTMX's ease of AJAXifying stuff
• a simple JS-objects-to-HTML templating engine
• some good utility functions that simplify everyday tasks
• and, most importantly, no complicated magic that slows things down (looking at you, reactivity)

would make for a significantly better solution.

kly,
@kly@fosstodon.org avatar

@scy Keep in mind that htmx means form data, instead of pure JSON as well, and I really don't want my backend - which is also used by shell scripts and what not - to have to deal with that stuff. And you end up with just as much complexity by trying to divide everything up into snippets of this and that...

The fundamental problem is that people think you can't just use vanilla JavaScript and write a tiny little helper library suited for your specific project, but you totally can.

scy,
@scy@chaos.social avatar

@kly FYI though, HTMX has a "json-enc" extension that transparently converts form data into JSON before sending it. Super easy to use, just enable it and be done.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy It doesn’t. If in doubt serve the entire page, HTMX is gonna swap out the page and it still feels snappier. From that on, you might leverage your template engines ability to render and serve partials, but that’s an optional albeit pretty common approach.

scy,
@scy@chaos.social avatar

@odrotbohm This assumes that I actually want to have any templating in my backend in the first place.

Also, "replace the entire page" doesn't really work that well when I'm implementing a chat.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy You asked a generic question, you get a generic answer. 🙃 doesn’t have to be a template. What matter is whether you can render snippets of HTML. A chat sounds like an easy enough todo thing as it’s basically appending divs. HTMX has native support for SSE, so depending how your server stack can deal with those, you should be able to get away without any custom JavaScript.

scy,
@scy@chaos.social avatar

@odrotbohm Actually, if you're coming an me this way, I didn't ask a generic question at all. I've asked "people who are using it in production, what are you using it for?" :P

The OOB swapping you mentioned elsewhere in the thread could help a little, but the whole thing still seems like a kludge.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy I was replying to the „does it need to be tailored to HTMX“ part. You didn’t mention anything about a chat in the first post either, which is a very specific use case. OOB swaps are a first-class concept. Returning exactly the elements I want to have updated feels pretty natural to me.

smartsammler,
@smartsammler@chaos.social avatar

@scy @mborus maybe you can help?

mborus,
@mborus@mastodon.social avatar

@smartsammler @scy I’m using it in production for ticket sale machines and internal web pages. In development for a mobile phone app, too, but that’s a prototype at the moment.

As a Python dev my JavaScript skills are really basic, there’s almost no JavaScript other than timeout handling (so that the machines go down if the connection to the server breaks)

scy,
@scy@chaos.social avatar

@mborus @smartsammler Thanks! That sounds like a good use case for HTMX to me.

So, every tap on + or - on that screen is an actual HTTP request that updates state on the server, right? Do you swap out the whole form on each interaction, or only the row that has been tapped?

callionica,
@callionica@mastodon.social avatar

@scy I’m very interested in the responses to this question. I’ve done similar research to you. It looked to me like the common case would be write a standard multi page website then, where you want partial replacement (“interactivity”), you would have server responses tailored to those tasks. It didn’t feel to me that those responses would be tailored to HTMX so much as tailored to the task.

What model of web development are you implicitly comparing to?

scy,
@scy@chaos.social avatar

@callionica I've been building API-driven web apps for the last years, where the backend sends and receives JSON and the API is pretty much independent of the frontend, which allows you to even completely replace the frontend with something else, which doesn't even have to be in a browser at all.

The frontends I've built were usually Vue with some kind of component library.

scy,
@scy@chaos.social avatar

For example, I've tried writing an SSE-based chat application with HTMX and a FastAPI-based backend.

Initial SSE setup was super easy with the SSE extension, but then what do I actually send over the connection? I went for HTML fragments, one <p> for every chat message, appending to a container via hx-swap="beforeend".

But sending additional state like "your username/session ID is X" and having HTMX send that back with each request proved difficult.

scy,
@scy@chaos.social avatar

I could send that username as JSON, but then I'd need to manually handle the message, replacing HTML content on screen and maybe update a <input type="hidden">'s value with the name, so that HTMX would include it in its POST request.

I'd need to do that anyway because you can't hx-swap into an attribute, and how else than with an input would I make HTMX include the username when it sends a chat message?

scy,
@scy@chaos.social avatar

Plus, when the backend sends me a message that I've successfully changed my username, I'd basically need to send that twice: Once in a more structured, machine-readable way so I can update the state in the frontend, and a second time as an HTML fragment for a "You've changed your name to X" message to actually show in the chat log.

I could generate that HTML fragment in the frontend via HTMX from the first message, but then I'd need templating in the frontend. Doesn't that defeat the purpose?

pa,
@pa@chaos.social avatar

@scy funny, I am at a similar experimental state with htmx, jinja2 and fastapi.

Have you seen this? https://htmx.org/examples/update-other-content/

scy,
@scy@chaos.social avatar

@pa But none of these are really helping, are they? Imagine I have this <input type="hidden" name="username" value="scy"> in my form. I can't have the backend simply send an SSE message like

event: UsernameChanged
data: scy2

and easily inject that value into the attribute, I'd need to update it manually from JavaScript.

pa,
@pa@chaos.social avatar

@scy maybe if you add hx-target and use https://htmx.org/extensions/json-enc/ ? Not sure if that can be combined in an elegant way.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy @pa You’d send a form with the data to be changed, the server renders all elements that need to be replaced with new data. You return those to the client and HTMX replaces all elements you send. No custom JavaScript required.

scy,
@scy@chaos.social avatar

@odrotbohm @pa I think my main issue with this approach was that I was originally serving the page as static HTML. The server doesn't render it, it's streamed directly from disk.

Therefore, my idea was to replace only certain parts of information, on the client side. Because the server doesn't even know how the page looks like.

But that's not really how it works with HTMX, I guess? The server itself needs to render the page, allowing it to consciously replace certain parts as required.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy @pa I see. That “change username“ functionality existed before? How did you handle that on the server?

scy,
@scy@chaos.social avatar

@odrotbohm @pa No, it didn't, the whole application was just to experiment with HTMX and FastAPI (which is really designed to deal with JSON by default, but can accommodate other input & output) combined.

So, I was like "okay, how do I get the new username into the form in my static page", but when I think about it in terms of having the server replace the whole form and fill in the data that it expects to receive back from the client, things start to make a lot more sense.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy @pa HTMX really plays to its strengths when you can both handle form submissions and produce HTML. It’s the antidote to the client messing with JSON and turning this into HTML eventually. I guess with a constrained server-side, HTMX is not of much help.

pa,
@pa@chaos.social avatar

@odrotbohm @scy

This is how I handle form data with fastapi.

async def function_1(request: Request):
try:
form_data = await request.form()
foo = form_data.get("foo")

scy,
@scy@chaos.social avatar

@pa @odrotbohm I didn't say that FastAPI can't handle it. In fact, I said that it's flexible, even though its defaults are JSON.

The issue here is/was not technology, but mindset. I haven't been server-side rendering HTML for ages, only static pages and SPAs.

pa,
@pa@chaos.social avatar

@scy @odrotbohm sorry, didn’t mean to splain you :)
I was at a similar moment, fuzzing a lot around how to build requests and how to treat the requests from htmx, hoping to find a way that feels elegant.
If you continue to try out things and find a way, I’d be happy to see your approach whatever you find.

scy,
@scy@chaos.social avatar

@pa Accessing form data in a FastAPI endpoint is easier (and comes with validation) if you use Form() by the way:

https://fastapi.tiangolo.com/tutorial/request-forms/

scy,
@scy@chaos.social avatar

So far, people have responded that

• HTMX feels snappier (than current bloated frontend technology? not surprised)
• it has an SSE extension (I know, I wrote about it in the thread) and
• I'm probably too junior of a web dev to wrap my head around it (one of my first websites is from 1999, and it's still online)

but nobody has actually replied to the question, which was "what are you using it for, in production, with real people other than yourself interacting with it?"

odrotbohm,
@odrotbohm@chaos.social avatar

@scy I think part of the challenge is that you conveyed two questions at once. A broad one (“What do you use it for?”) and a very specific one (“how don’t solve this one special thing for my chat app?”). That’s hard to respond to on social media.

On the former: I’ve built pretty complex dashboards for a commercial product in the SBOM space, some health care related CRM-like UI and some advanced examples primarily focusing on integrating micro-frontends.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy It feels like you’re overthinking it a little. The server sends HTML, you send the server forms, state is in the URI, nowhere else. If you think in these constraints (the constraints of the web essentially) things usually fall in place easily.

odrotbohm,
@odrotbohm@chaos.social avatar

@scy Out of band swaps is what you’re looking for. Those allow you to send multiple partials that HTMX would put into the right place. You could return a single chat message besides some other div with an event (just make them sibling elements with the proper hx:swap each) and HTMX takes care of the rest. IIRC replace by ID is the default.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • webdev
  • thenastyranch
  • DreamBathrooms
  • tacticalgear
  • magazineikmin
  • khanakhh
  • everett
  • Youngstown
  • mdbf
  • slotface
  • rosin
  • ethstaker
  • InstantRegret
  • kavyap
  • ngwrru68w68
  • megavids
  • cisconetworking
  • cubers
  • osvaldo12
  • modclub
  • GTA5RPClips
  • tester
  • Durango
  • provamag3
  • anitta
  • Leos
  • normalnudes
  • JUstTest
  • lostlight
  • All magazines