We use HTMX at Savio (https://www.savio.io), which started as a pure Django app.
Our operating theory was that using a JS FE framework was overkill for a CRUD app. So we went with stock Django and server-rendered HTML.
It became clear that parts of our UX would benefit greatly from client-side interactivity, which is what we eventually expected to happen. We sprinkled in HTMX (on top of our Jquery) on certain pages and it's been a breath of fresh air. We even built a nice Kanban board w/ HTMX and a Jquery plugin. Key benefits include:
1. When you're looking at a template the HTMX syntax makes it obvious what happens
2. HTML is rendered server-side in templates (imho where it should be) and is sent down the wire
3. We get a lot of stuff for free from Django (routing, back button handling, etc) that we don't need to build with a FE framework
Even though we're devs we believe the best code is no code (in the literal sense, not the de rigeur "No Code" sense). Maintenance costs are important to us. Getting stuff for free is important to us. Building for a specific use case is incredibly important to us.
With that in mind, the Django + sprinkled HTMX experiment has been pretty successful thus far.
I've only prototyped adding HTMX to my Django app (currently using React & DRF), but there seems to be a great alignment between Django and HTMX. HTMX wants you to send back a partial HTML tree for the node being updated, and Django's template inheritance machinery lets you very cleanly separate the "parent page" from "partial sub-tree" (since you can just say `{%
include "foo_table_fragment.html" %}` in the parent page template, and then render the "foo_table_fragment.html" template directly on the GET/POST with HTMX headers).
It's all very easy to wire in to a normal Django page to gradually add interactivity (say, partial updates to filter/sort a table to instead of full-page reload).
This is what I do (not Django but same idea). Works lovely. Between that and a 900+ package npm install for a simple demo code I’ve given up on “modern JS frameworks”.
If you use django-htmx, it's pretty simple to get the "this HTTP request came from HTMX" flag and branch accordingly in your view. The docs give a simple example of the logic here:
Though that's very slightly different than how I described it above, but it's basically the same idea; in this case you commonize the `main` block between the two contexts.
Hah. My co-founder uses your phrase “locality of behaviour” all the time. I was trying to remember it when I wrote that first item in the list but couldn’t. I very much appreciate you using it in htmx - makes understanding code so much easier. Thank you!
That's an interesting perspective, although I definitely have a negative gut reaction to that "where it should be" comment. It's so nice having a separation of concerns where that the backend doesn't deal with any view/presentation/styling concerns and only exposes an API, and then the clients consume that API (doesn't matter if those clients are FE web apps or iOS or Android apps or 3rd party developers accessing your API).
Another advantage is there are some cool no-code solutions where you can build internal admin tooling on top of your API, which kind of gets you some similar benefits to the django admin interface system. I haven't really used this approach in production but it makes a lot of sense.
But in some cases this can definitely come with more overhead than a quick Rails or Django app, and if you have a very read-heavy traditional website and no other clients then that overhead might not make sense. Sounds like you've found a platform that works well for your use case.
>> It's so nice having a separation of concerns where that the backend doesn't deal with any view/presentation/styling concerns and only exposes an API
You’re just casually glossing over the fact that now you’ve created a distributed system - state still exists server side but now there’s a distributed eventually consistent subset of state living in the user’s browser (i don’t mean trivial UI state like is the dark theme enabled, i mean application state).
And you’ve opened this can of worms only for the trade off that you get to move view templating from the server side to the client side.
There’s one case where there’s obvious clear benefits of choosing the client side rendering trade off and it’s if you’re building a client side app. Something that should be an intensive desktop app but you choose to deploy via browser instead. Maybe a music mixing or live DJ’ing app or a photo or video editor. Delivering these apps via web has some neat benefits in app distribution and cross platform accommodations. It wouldn’t be possible to build them without client side rendering so it’s a clear win.
Most web apps are not that though. Most are like you describe, a UI to some APIs. The state really lives server side - my bank account UI, my blog posts, my … etc etc For these cases, you can reduce complexity by ditching the client side rendering.
You're just casually glossing over the fact that the server-rendered + jquery approach was already a distributed system, just with less explicit boundaries and more ad-hoc patterns for managing and updating that state.
It all just depends on the product though, if the client-side interactions are minimal enough than I agree the server-rendered approach can be better. I was just saying I don't see this as the inherently better way, there are pros and cons to each approach.
We use django + react. I've long been curious about HTMX but one thing has been holding me back that I'm trying to get others' opinion on: the npm ecosystem is incredibly rich. I'm thinking of drop in components like maps, UI libs, etc.
Don't I need to spend a lot more effort using their original JS incantations and integrating that w/HTMX?
By pulling in React you're now on the hook for another tooling+build pipeline for JavaScript. HTMX is a single JavaScript import meaning you can forgo the whole js tooling, which in my book is a _massive_ win.
I've been wanting to do this switch too and have the same concern. One option worth investigating is Shoelace - https://shoelace.style/, a library of nice looking web components that you can just add to your page without setting up a whole build pipeline.
Not certain, but should be easy to make a new folder, fire up the django tutorial, and drop in htmx and shoelace from their cdn links into the main template to start experimenting. Looks feasible.
It obvs depends on what you're trying to do. In general we aim to use well documented, well maintained, and popular dependencies if we take them on at all. We haven't run into any issues where it felt like we were doing more work than necessary to get HTMX up and running.
I agree npm is wonderful and if you need npm just stick to React but you mentioned UI libraries. I use Django + HTMX stack in side projects. I've been using Material UI with React before, but I don't see a need for something similar in Django + HTMX stack. Just add some css like bulma and you're done.
Not really. Django already has routing and (obviously) back button functionality. By introducing react you first break it, then you add another library to fix it again. The point is HTMX doesn't break it in the first place.
Not that I'm saying HTMX is better (or worse) than react, but that's what is being discussed here.
So explain it then. A React-based framework is too complex so we went with Django because we get routing and back button functionality for free, even though you get routing and back button functionality for free with React-based frameworks.
Something I've wanted to comment on this as well. It's best to use render_template() when rendering the views so it doesn't tangle w/ a lot of python controller logic.
I built https://PlotPanel.com with Django, htmx, Alpine.js, and Tailwind CSS. I was new to all 4 of those technologies and learnt whilst on the project, it was a great experience. It was my first time using the Stripe API too, which has the nicest documentation I've ever seen!
I left my job in August last year and set a target to complete a project every month of 2022! PlotPanel.com was my February project, I launched it around the 25th (so around 24 days). It's deployed using containers and a VPS!
Thank you! There isn't yet, but I'm going to find some time to write perhaps a post per-project on https://polyra.com. I'm not sure it will get any reach!
It's indeed all Tailwind CSS! This was my first Django project and I started with Django 4. It has form templates that I've overridden to use Tailwind elements. This was quite tricky and meant learning more about Django than I'd expected!
I recently switched back to Rails after 7 or so years seeking (part-time) a better option, and wow....Rails and Ruby are still beautiful and my productivity has spiked tremendously. I'm finding https://hotwired.dev/ to be awesome, and was able to develop an interactive data grid in less than an hour.
If you haven't tried Rails lately because it's no longer cool, I encourage you to look again. I've tried many different frameworks, including Flask, but nothing touches Rails (IMHO) in terms of productivity.
This is exactly my experience. During the last years I mostly wrote ts, python and some golang. About a year ago a friend asked if I'd like to join his startup. I was skeptical at first because his personal philosophy includes avoiding js as much as possible and (almost) exclusivity relying on the rails way of doing things. The rails community seems like a cult to me at times. One year later and I'm not exactly in love with ruby the language but I seriously love the productivity that comes with using rails. It is the most complete framework I have used and from my observation it seems to raise in popularity again.
As a complete beginner to the Rails world (but not web dev in general), the official Getting Started guide at https://edgeguides.rubyonrails.org/getting_started.html was a short and sweet way for me to get an introduction to how it works.
After that I went through a number of Chris Oliver's GoRails tutorials (https://gorails.com) which I found really helpful too.
I've only used HTMX for a tiny project along with FastAPI, it was basically just a single form page that would send the response in JSON to the server.
Things I liked were that it felt really lightweight, easy to setup, and basically just worked how the docs described.
However one thing I'm still trying to wrap my head around is how to better handle "intermediate" pieces of HTML i.e. partials. In SPAs you create a component that renders the template on the fly and is reused, but in HTMX you would need to hit an endpoint to get something like a partial.
This sort of had me pause because I'm so used to keeping my backend routes very "RESTy" (in the loose sense). But when using HTMX I was wondering if I need to make some routes like `/contact-form/modal` just to retrieve something like a success modal.
The article kinda displays what I mean with how all of the book routes return the buttons for the form. Also the `/get-book-row/<int:id>` and `/update/<int:id>` routes both return the same type of buttons. Those buttons seem prime candidates to be extracted into a common template of sorts.
Does that make sense? If so does anyone have a good example of a larger HTMX app which handles these scenarios?
Recently saw Michael Kennedy's presentation at Python Web Conference where he talks about this. He also has a course on using Flask + HTMX. Even if you don't take the course, you do have access to the github repo for that course.
He wrote a small library extending Jinja that does what you're referencing here, I believe. It's a little different than Jinja macros and include (you can reference the github issues for a discussion on that).
I use HTMX + Alpine.js for a project I'm working on. It's been pretty nice and I think my only complaint is that the requests are form encoded instead of JSON. There is a HTMX extension that can JSON encode the requests, but all values get encoded as strings so its not great if you want lists, numbers, etc.
I also use Tailwind CSS and I found a way to make that work nicely with HTMX for CSS transitions which I wrote about [0].
This seems like a good simple stack. Can it get more simple? I've been trying to envision the best stack for small weekend projects that will see 3-4 users a month.
Ideally: Monolithic, 1 Language, No need to write your own APIs. Just direct access from the View.
Replace Flask with Bottle.py. It's a single-file dependency (don't even need pip) and includes routing, and a templating engine. Super simple to prototype and iterate a backend API.
This is what I started doing. Bottle has user auth plugin called cork that is handy too. All very simple to understand.
I did start using jinja instead of the built in template engine though.
Elixir + Phoenix/Phoenix LiveView is very good at this. LiveView lets you change state on the server, and have it reflected on the client. Or, when the client does an action, do something on the server (that can then trigger another state change on the client, etc). All of this is purely using Elixir - no need to write JS 99% of the time.
One of the benefits of PHP is the single page idea, where the file system directly matches the URL structure.
For quick and dirty projects I’ve always wondered what a Python version would look like.
Maybe Jinja2 pages, a place to define extra code to be run or a custom ninja tag for longer sections of Python, and a binary to launch the whole thing as a server?
Rails is awesome, I'm a huge fan. I just think there's a huge ramp up out of the box. I wish I knew how to go from rails init -> dashboard w/ login faster.
Not sure if bottle is really "better" — it has different pros and cons compared to Flask, so whether it is better depends entirely on the usecase.
If you e.g. have a use case where your dependency-situation is one where you won't benefit from bottle being single-file (because you e.g. have a ton of other non-single file dependecies), then choosing it over the widely used Flask might not be show you any benefits at all.
I was responding to the request in the top comment for something simpler that can be used for weekend projects. In this case, Bottle.py is "better" in that it is more simple than Flask; not that Bottle.py as a web framework is objectively better than Flask.
For the record, I've used both, and Bottle is much faster to get started with. The docs are also much leaner.
Flask will take you pretty far. I'm not sure I would build a build a business around it, but it's the easiest thing I've found for just getting some code up on the web.
You mentioned "weekend projects", which indicates that you value development productivity. You want to be able to do more with your allotted time. The way we tend to envision a "simple stack" is to mean a combination of lighter and possibly specialized tools. But does that necessarily translate into quick development? Your choice of tools still relies on your experience with them individually.
I often see people advocating for microframeworks when this question comes up. As a long time user, I would say sure, but with the caveat that they come with very few batteries, and sometimes fewer opinions. To me this is also the promise of many future decisions to be made, by you. How much time does a single decision typically cost you?
Also, the size of your project's audience, doesn't imply that the app needs considerably less dependencies, than something more ambitious popularity wise. The difference usually lies in the infrastructure that will eventually specifically address scalability.
I think a good simple stack for week-end projects should aim to get you from install to development fairly quickly. Don't waste time making too many technical decisions beyond the choice of tools. Spend half an hour setting up a container, design your database, and get to work. If some other people have already spent time working out what's best in 90% of cases, use that experience first. Find out later that your case falls within the 10% that doesn't apply.
---
Now, for some more practical recommendations. I think Django's opinionated batteries make it a more compelling solution for "week-end" type projects. Does it matter that it installs megabytes on disk, of which you end-up barely using a few KBytes? For most cases I don't think it does.
My stack suggestions for week-end type projects on the back-end will be heavily Python-centric (except for Ruby-On-Rails):
- Django|RoR, Postgres: Opinionated batteries. Just hop on the train and simply let it drive you.
- Flask, Psycopg2, Postgres: when you're already comfortable replacing most things Django offers for free, with your own assortment of best-of-breed tools and practices (testing, templating, etc). Working with Psycopg2 implies that you're reasonably comfortable working directly with SQL, and willing to spend some additional time working out the various kinks that inevitably need addressing, when managing your own connections to the database.
- Flask|Django, Postgres, SQLAlchemy: Only if you already know SQLAlchemy. If you don't, just trust that you won't learn it in a week-end.
I'm not a fan of Javascript but my simple projects often need some interactivity that just HTML and CSS alone can't provide. Things like, "when the user clicks thing thing, update this other thing."
I thought HTMX was going to be that silver bullet that let me get away with never writing JavaScript again, but after using it in a few places, I'm a bit more selective in which projects I adopt it for:
If you're doing anything fancy before or after a request, you either have to use Javascript anyway, or pull in hyperscript as another dependency and then you also have to learn hyperscript. (Some of the demos on the HTMX site require hyperscript.)
Browser-native prompt dialogs send the contents of the prompt as a custom request header instead of POST data, which means you have to modify your backend routes, making HTMX much less plug-and-play. If there's a good reason for this design decision, it's not mentioned in the docs or examples.
If you already know how to use querySelector(), fetch(), and innerHTML in Javascript, HTMX isn't going to offer you much except cleaner-looking code at the cost of adding a dependency to the project.
I suspect HTMX is the salve for backend developers (particularly Python webdev) doing anything possible to avoid dealing with modern frontend and the toolchains that come with it.
I’m not talking about frameworks, I’m talking about vanilla es6+ and occasionally leveraging npm the way they do Python package dependencies.
I don’t blame folks for this but solid devops exists now.
A lot of the pains around including modern js in a template driven web project have been worked out. The benefits including the cross browser compatibility, tree shaking and module importing and are there for the taking.
Form manipulation, Ajax behaviors—-using JS to liven up your app can be learned and implemented.
Full stack dev here. I know plenty of frontend JS. I've written a chat application for my job that's currently in use by ~thousands of people among other things. This preface just to note that I'm not bad at JS or scared by it.
I hate having to set up a "modern" js toolchain when starting a new project. No matter what tools you choose it's always a huge hassle, and it never manages to integrate seamlessly with the backend.
What I like about HTMx and alpine.js is that first of all the set up is trivial. I just stick the js files in my static folder and stick a script tag in the header. Secondly they leverage exactly what the backend is good at: producing HTML. Getting the backend and frontend talking is trivial instead of a huge REST-y kludge.
With modern JS I need to write database models, REST views, REST serializers, components, routing logic, etc.
with HTMx and alpine I still need to write database models, views and templates but I get to fully skip the whole translation to and from REST (or whichever other API model you prefer). And in the end it's no less performant.
So yeah for hobby projects I definitely avoid modern JS, but it's not for no reason. The developer experience is just awful IMO.
I'm not super familiar with HTMX but lots of people in the Elixir/Phoenix/Liveview world are using Alpine JS for these types of problems.
Liveview(HTMX analog) for anything with data and state that needs to go to and from the server; Alpine JS for client side interactions with ephemeral state like opening a modal.
there is no silver bullet: htmx and hypermedia are a tool, and give you a pretty low-complexity solution to many problems, but eventually you will run into something that needs a more elaborate front end solution and using Alpine, vue or whatever makes sense.
Hopefully by staying close to HTML's semantics and design philosophy, using htmx doesn't introduce a lot of conceptual load on top of what is already there, and saves you complexity where the more elaborate client-side stuff isn't needed.
yes, and jquery is still useful in cases like this, despite the disdain most modern front-end devs have for it. the added weight is also not a big concern for any site not meant to serve millions of requests a day. it just has all of the core convenience methods you'd want, and a sane dev UX (unlike plain js).
i'd add that stimulus is another great alternative for sprinkles of front-end interactivity without going all-in on js tooling and a js framework. it pairs nicely with rails 7's new turbo feature to provide a full server-side rendering experience, similar to htmx.
I am trying to understand better your pain points here. What other fancy cases are you referring to when you say before or after a request? Are you talking about dom events?
Do you see any other scenarios where this stack setup struggles? If you were to design this how would you do it? Since I do think it is helpful in some cases like creating forms and basic navigation.
The first time I read about HTMX here on HN I didn't get it, thought it was pointless. Then it clicked, and I think it's awesome. Fits nicely with Django, super easy to understand and the docs are great.
I think Flask here is just a placeholder for "a simple backend framework". I agree that Django probably ends up the simpler choice once you need the stuff you'll almost certainly need. But that would have spoiled the flavour of this tutorial.
I think that is exactly the problem with Flask. Look how simple it is! Except, as you say, you almost always need at least some of that stuff, and wiring it together yourself is/becomes an unholy mess (IME). And getting set up with Django is just as simple, so I don’t buy that argument anyway.
I had the same pain points with Flask, so I built Flask Unchained to integrate many of the best extensions (IMO) to all work together out of the box in a reusable way:
The problem with Django is that it's so opinionated. If you don't really use the admin interface and you want to do things your own way you will spend way more time wrestling with Django than you saved using a few plugins. Also, the ORM is hot garbage that you have to carry with you to some degree if you do actually use the admin at all.
I rarely use the Django Admin except maybe for poking around in the early stages. I’ve never tried to build a full blown app/site with it.
I think the right comparison here is to Flask-Admin, though, not Flask itself, and I’ll just say that the app I have to deal with that’s built on Flask-Admin is a nightmare, certainly no better than an equivalent app using Django Admin would be.
Re the Django ORM, SQLAlchemy is certainly better in many ways, but the Django ORM is pretty good these days (and has been for a while IMO).
If I know I’ll have complex database requirements that Django can’t easily handle, I’d much rather use Pyramid + SQLAlchemy than Flask.
I guess it's a nice way to visualize the models, at least in the beginning. I prefer shell_plus along with dbshell. Then I can also write code that I can later easily adapt into my views etc.
It's invaluable in many ways for me and my clients and it's saved me countless hours of developing things from scratch.
I think the animosity towards "over use" by some of the core community is misguided. The continued work that goes towards improving extensibility and features is surely a sign that someone finds it worth contributing towards. And the number of projects on Github or Django Packages that hook into the admin have to be written by somebody.
What problems do you run into with Flask (presumably + SQLAlchemy)?
IME, this stack has been pretty simple both at-scale and at-home. At scale, my experience is mostly using it in REST APIs serving a react frontend.
At-home, I've used it to setup numerous graphql services (with the graphene plugin).
Admittedly, there's probably 100 different ways to configure anything wrong, especially for any framework written in Python. But once you witness a "golden path", and stick to it, it's pretty straightforward. (The Flask docs have improved a lot in this regard, in the last few years)
May have changed, but when I tried it, the first day with Flask was incredible. The second day, when you're ready to implement log-in and password pages, maybe email reset... you are on your own. There's six and a half third-party extension options with different overlapping scopes to research, the author of the best one has taken off for the Bahamas for two years…
Ah yeah, fair enough. The places I worked at-scale had their own o-auth setups (built mostly with FOSS) wired up to flask with some relatively small libraries [1].
I personally wouldn't want my web framework to implement login/password/email-reset for me, although I understand Django offers it to varying degrees. It's a space where "best practice" has evolved dramatically in the past decade.
As practice evolves, Django gives you a migration guide. That's great because the alternative could take a potentially unbounded amount of time. And you still could go it alone if sufficiently motivated. Although it could get annoying, as mentioned.
The main point though is that I'm not interested in being on the forefront of login, it is not a differentiator (unless project is a laggard). In fact being five years behind bleeding-edge sounds a bit perfect.
I’m working on multiple Flask apps currently and I have a lot to say about it, but regarding docs, the main Flask docs might be fine, but the docs for some of the extensions we use are quite bad.
Also, there’s nothing about these apps that requires the alleged flexibility of Flask, so there’s a lot of issues with dependencies and integrating extensions. That’s a lot of extra work and probably weakens security for no benefit at all.
I think part of the reason the Flask extension ecosystem is so weak, is that most problems solved by an extension have solutions that are relatively small / cheap to build in-house.
These things are difficult both to depend upon externally and to maintain, due to the dependency/upgrade issue you mentioned.
For an example in a similar ecosystem: at a previous company, at one time we used SQLalchemy-continuum for audit tables. We found some bugs and were not able to upstream them. When we wanted to upgrade SLQLAlchemy to X.Y, we were stuck with this dependency that required SQLAlchemy X.Y-1.
After a few years, we realized it was cheaper to cook up a SQLAlchemy-Continuum subset that met our needs, so it'd be easier to keep in line with SQLAlchemy.
It's a very different mindset from Django; I think there's an appropriate context for each.
This is not a better way of making apps. Or a worse way. In solutions there is no such thing as good or bad—only more and less fit for the problem.
If your problem and requirements are such that you will always be outside the part of the solution space that SPAs are meant for, HTMX and progressive enhancement are great. If not, you may discover the transition like a boat discovers the transition between water and ice.
If you don't immediately know the shortest path from your requirements to that transition, but you're sure that SPAs are Bad and this is Good, please take a moment to consider why you think that.
>If your problem and requirements are such that you will always be outside the part of the solution space that SPAs are meant for
That seems like a very very strong claim. "You should do an SPA in case you ever need to make an SPA". Like what do you think actually needs to be an SPA?
Here's my list of popular sites that don't need to be an SPA but are anyway
* Reddit, nothing about it lends itself to being an SPA at all.
* Facebook, I think they went the SPA route in order to make it more difficult for ad blockers
* instagram
* Netflix (don't know how related this choice is to DRM constraints honestly)
* pinterest
* paypal
* gmail
Here's my list of sites that do need to be an SPA, or are at least easier if you make them as an SPA.
* Google maps
* Google docs
* Photopea
* Discord (This is almost all achievable with something like HTMX, save the webrtc stuff, but I think it would be more of a pain and would rely on a lot of complicated session management stuff happening on the server)
* AirBnb, which I'll give a pass since it makes such heavy use of maps.
My take away is that if you're reaching for the standard SPA toolkit you might be better off using something like QT or Godot engine, writing native code, and compiling it for the web. Anything that uses maps or rich text editing probably should be done as an SPA, although if you can make it so that just the one component is "rich" you should probably do that.
Using more complicated components can be a reasonable idea, like using a graphing widget or a maps widget, but you can do those things without making your entire app an SPA.
I just don't buy the "you might need to make your app an SPA some day to you might as well take on the technical burden from that decision now" idea. Very very few projects need to be an SPA, and when you have one it's probably pretty obvious.
> I just don't buy the "you might need to make your app an SPA some day to you might as well take on the technical burden from that decision now" idea.*
I'm not selling that idea. "Boil the ocean now in case you want a cup of tea tomorrow" is a fantastically effective way to fail.
>> If your problem and requirements are such that you will always be outside the part of the solution space that SPAs are meant for
> That seems like a very very strong claim.
By that wordy garbage I was trying to contrast the very extreme, where HTMX is an obvious fit, with points further down the spectrum where it's not so clear. You could go full SPA on an HTMX-shaped problem, if you wanted to, or full progressive enhancement on an SPA-shaped problem; I can't think of any technical thing that would stop you. There would just be consequences and it's up to you if they're worth it.
> Like what do you think actually needs to be an SPA?
I think a move to SPA gets more attractive when you have 1) ad-hoc client-only state 2) that shouldn't be explicitly reflected in your server-side data model 3) produced without coordination by different independently-enhanced components sharing a page 4) which causes unexpected interactions between them.
SPA is not the only way to solve that, solving it is not the only benefit of SPA, you could just ignore it and accept the combinatorial growth of your state space, a hundred other caveats. It's an engineering question which should get an engineering answer maximizing benefit by balancing tradeoffs, but IMO that's not the treatment it usually gets.
>I think a move to SPA gets more attractive when you have 1) ad-hoc client-only state 2) that shouldn't be explicitly reflected in your server-side data model 3) produced without coordination by different independently-enhanced components sharing a page 4) which causes unexpected interactions between them.
That's a lot of what I was thinking about when I was thinking if discord really needed to b an SPA, all that ad-hoc client state would need to be reflected on the server.
Non-SPA feels slow. It doesn't matter that much if it's slower or not, because the perception is slow. If I'm on a page, click on something, and in the background it loads some new content and updates part of (or even the entire) page, at least while I'm waiting, there's usually something else to read or potentially interact with in some way. Maybe there's a spinner for requests over ~200ms. It feels like the app is doing some work but it otherwise present. If every click results in a new page render, my browser immediately clears the page and I'm left looking at a blank page waiting for content to render. Even if that somehow takes half the time, it feels like an eternity, and there's nothing for me to look at while I wait. And that full-page redraw is visually distracting.
Does anyone have a nice dev tool setup which adds auto page refresh and production processed assets?
One thing I noticed after making a small FastAPI/HTMX app was that I missed the hot reload of React. Also I noticed when I deployed to a live version of the site I found myself needing to hard refresh my browser because my assets didn't have hashes appended to bust the cache.
Just curious if anyone has some cool setups :) It would be awesome if there was a way to integrate ParcelJS as it has a nice reload server.
I have been using Parcel (https://parceljs.org) for building JS and CSS (from SASS) asset bundles for Django apps. It is pleasant to use because it takes almost no configuration to get going.
I was hoping to look for a way to get auto reload to work while being served by your Flask/FastAPI server. Maybe it's not a big deal to dev using "reload" but have your prod app served by Flask/FastAPI.
You can have the site reload whenever your backend server code changes. That's how I was using it. Perhaps I'm misunderstanding what you're asking for.
I can't work out what problem this solves. Personally, I'm not a fan of SPAs, but there's still a middle ground between that and a more traditional full-page reload, server-side rendered approach. React, Elm, etc, should all allow for smaller parts of a page to be dynamic while the rest remains static.
HTMX helps you create an SPA-like experience without using a full SPA framework. You can utilize the full power of your favourite backend framework (e.g form validation, template-system, authorization, etc.) without writing JS code directly. Some examples:
- Infinite scroll: HTMX detects the specified viewpoint and requests the next batch of content. The backend returns only the rendered partial HTML content that HTMX appends to the bottom of the page.
- Next page of a paginated content: if the users clicks on the 'Next page' button, the backend returns only the rendered HTML content of the next page, HTMX replaces only this part of the page.
- Form submission/validation: you can skip most of the frontend validation and use the backend for it. If the form has an error, HTMX replaces the new rendered form with the inlined error messages. Otherwise it can forward the user to the next page or shows some success message.
- Inline edit: e.g. click on the row in a table to load a small form just for that line. After the submission the backend returns the updated rendered table.
- Chained select input elements: when the user selects something in the first dropdown, it triggers an HTMX request that loads just the next select element that reflects the value of the first one.
- Background task with progress bar: just return a delayed, automatically triggered HTMX request from the backend until the task is finished. The status (e.g width) of the progress bar is also calculated on the backend.
- Search preview: with the builtin debounce filter trigger a search request that returns the search suggestions.
- Multiple small(er) updates on the page: one HTMX request can return multiple HTML partials that updates any part of the page. If you couple it with the builtin automated polling/websocket, you can build a live dashboard easily.
Of course you can do any of these with a SPA framework coupled to the backend API. But with HTMX you don't have to write a single line of JS, just put some htmx-something="..." attributes in the backend template files.
Anything works that way as long as it doesn't come with a built in router and you are careful not to accidentally bundle two different versions of your runtime.
HTMX is a middle ground - using it involves not having "full-page reloads" like traditional server rendered apps, but still having the productivity of server only apps.
The main advantage I see with this approach is you'll have only one set of models/actions in the server, instead of models in server + models in client. The logic won't be spread between client and server, which make for easier testing among other benefits. For larger apps, this is a significant win.
I developed almost exclusively in django for many years before moving to react or vue for frontends.
The switch from django templates was painful and a tremendous learning curve, so I get the value proposition of drop-in interactivity tools like HTMx. But when you compare the two frontend ecosystems (javascript vs htmx) it's night and day. The support, the DX tooling, the variety of libraries... that's not to say HTMx couldn't one day mature to a comparable place, but it seems unlikely, and in the meantime investing in "eating the elephant" by learning a JS framework seems worthwhile for anyone planning to spend a significant amount of time building frontends
Back when I was learning AngularJS (the 1.x days) I spent what felt like hours staring at some code wondering why the hell it wasn't working.
I eventually realized I had a typo in a template that was all too easy to overlook. Since there wasn't any tooling to catch it, it behaved like an html attribute and did nothing.
I seriously don't know that I would want to go back to such an anemic dev experience unless it is for a toy project.
Preact / React + TypeScript largely does away with this. For most of my projects, fixing the compiler errors means the UI largely works (other than plain logic errors). I did AngularJS, too, and it's a totally different, terrible ballgame. I recommend giving Preact a try.
trying to figure out how this compares to Phoenix's frameworks LiveView, does HTMx use websockets to communicate state change? Seems like I could just end up using HTMx in lieu of learning Elixir and Phoenix
The way I think about it is htmx takes the "full page refresh" user experience & programming model, and expands it to "partial page refresh" and goes from there. It also patches some annoying gaps in html, like forms only being able to GET and POST. Finally, it lets you trigger these requests with things other than clicking a link/submitting a form.
LiveView tries to replicate the architecture of a native app toolkit and slap a network boundary in the middle of it, whereas htmx tries to keep the programming model of Web 1.0 apps while radically expanding the user experience possibilities
HTMx supports web sockets [0], but my understanding is that it isn't really an alterantive to something like LiveView.
HTMx is more about simplicity - an easy alternative to AJAX that doesn't require a full-blown front-end framework. It isn't really designed for optimized real-time communication and long-running connections, but you could probably use it for that if you wanted.
I see its more fair to compare to AJAX...then I'm curious in what ways does liveview create "magic" over HTMx here, to my knowledge the mechanics here with HTMx seem a lot simpler and less bloat doing the same things.
With LiveView, it seems to be just sending application state up and down the websocket wire, does HTMx not do this as well if it was setup that way with WS?
htmx is a lower-level extension of HTML, with no server-side component to it
it tries to extend HTML as a hypermedia, which makes it more general (it can be used with any backend that produces HTML) but also more work to achieve things that, in live view, work magically
what sort of magic does LiveView do here that HTMx doesn't? seems like the difference here is that the article sends a server rendered partial HTML down the wire with HTMx sprinkled on it that gets rendered on the client side. From my basic understanding, LiveView sends HTML to client first, establishes bi-directional WS connection, and proceeds to send JSON data to the client and synchronizes the app state via sending diffs over WS.
Our operating theory was that using a JS FE framework was overkill for a CRUD app. So we went with stock Django and server-rendered HTML.
It became clear that parts of our UX would benefit greatly from client-side interactivity, which is what we eventually expected to happen. We sprinkled in HTMX (on top of our Jquery) on certain pages and it's been a breath of fresh air. We even built a nice Kanban board w/ HTMX and a Jquery plugin. Key benefits include:
1. When you're looking at a template the HTMX syntax makes it obvious what happens
2. HTML is rendered server-side in templates (imho where it should be) and is sent down the wire
3. We get a lot of stuff for free from Django (routing, back button handling, etc) that we don't need to build with a FE framework
Even though we're devs we believe the best code is no code (in the literal sense, not the de rigeur "No Code" sense). Maintenance costs are important to us. Getting stuff for free is important to us. Building for a specific use case is incredibly important to us.
With that in mind, the Django + sprinkled HTMX experiment has been pretty successful thus far.