[HN Gopher] Building a fullstack app with Flask and HTMx
___________________________________________________________________
Building a fullstack app with Flask and HTMx
Author : sixhobbits
Score : 164 points
Date : 2022-03-29 14:49 UTC (8 hours ago)
(HTM) web link (codecapsules.io)
(TXT) w3m dump (codecapsules.io)
| [deleted]
| Darmody wrote:
| I love htmx. It allows me to write code on the server and forget
| about most of the boring client stuff.
|
| If you're a PHP dev check Yoyo Framework. It's like Laravel
| Livewire without all the bloat from Laravel.
| danjac wrote:
| This code looks like it has an XSS vulnerability in the submit()
| method: returning plain f-string i.e. return
| f"<tr> <td>{title}</td>
| <td>{author_name}</td> <td>...."
|
| Probably safer (and more maintainable) to just return a Jinja2
| template instead.
| batterylow wrote:
| 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!
| weakSignal wrote:
| You did impressive work mate.
| reducesuffering wrote:
| Looks very nice. How long did this take you? What's your
| deployment stack: Heroku, DigitalOcean, AWS, containers, CI?
| number6 wrote:
| Wow that looks amazing! Is it all tailwind CSS?
|
| How do you work with components e.g. buttons in django +
| tailwind? Do you {% include %} them or are all of them uniquely
| designed?
| jacktheturtle wrote:
| 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.
| erokar wrote:
| I think Rails is the best fit for this, alternatively something
| like SvelteKit + Supabase (the latter if you need a db).
| jacktheturtle wrote:
| 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.
| mekoka wrote:
| It really depends what you mean by _simple stack_.
|
| 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.
| danpalmer wrote:
| 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?
| sixhobbits wrote:
| if you don't want fancy partial-page reloads and UI
| interaction, then just Flask + HTML also works.
| keb_ wrote:
| Even better: Bottle.py; single-file dependency, includes
| routing and a simple templating engine.
| atoav wrote:
| 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.
| keb_ wrote:
| 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.
| dannywarner wrote:
| Agree. Simple Flask and HTML gets you a long way and is easy
| to deploy and manage.
| jacktheturtle wrote:
| Might want to give this a try. Thanks for sharing!
| dfinninger wrote:
| 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.
|
| This tutorial is a pretty in-depth guide that
| incrementally adds more features to a flask app:
| https://blog.miguelgrinberg.com/post/the-flask-mega-
| tutorial...
|
| By no means do you need to use everything in here, but I
| reference it from time to time. This is plenty:
| from flask import Flask, render_template app
| = Flask(__name__) @app.route("/")
| def index(): return "<h1>hello world<h1>"
| @app.route("/foo") def foo(): return
| render_template("foo.html", vars={"foo": "bar"})
| if __name__ == "__main__": app.run()
| bckr wrote:
| I work at a company pulling real cash, built mostly on
| Flask. Flask is one of the things I like the most about
| the stack.
| lambdaba wrote:
| Meteor does this, in JavaScript, with built-in database and no
| writing of APIs, code is shared between client and server.
| jacktheturtle wrote:
| I should give this another shot. I haven't touch it since
| 2017
| ramchip wrote:
| Phoenix LiveView works great for this.
| keb_ wrote:
| 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.
| farmin wrote:
| 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.
| jms55 wrote:
| 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.
| Townley wrote:
| 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
| digisign wrote:
| The use case here is to add some interactivity to your page,
| not implement an ecosystem inside it.
| zdragnar wrote:
| 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.
| christophilus wrote:
| 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.
| slig wrote:
| 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.
| [deleted]
| yakshaving_jgt wrote:
| 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.
| felipeccastro wrote:
| 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.
| sixhobbits wrote:
| They do, but they have a steeper learning curve and cause more
| separation between back and front end. Sometimes that's good,
| sometimes it isn't.
|
| [0] and [1] are relevant sections of a much longer guide that
| go into more detail about the tradeoffs.
|
| [0] https://www.saaspegasus.com/guides/modern-javascript-for-
| dja...
|
| [1] https://www.saaspegasus.com/guides/modern-javascript-for-
| dja...
| pythonaut_16 wrote:
| This is also one of the use cases that Vue targeted
| specifically and it greatly accelerated its adoption.
|
| Vue positions itself for anything from jQuery replacement all
| the way to a full SPA and everything in between.
| zdragnar wrote:
| It's how Facebook originally (still?) used react.
|
| 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.
| Dauros wrote:
| 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.
| nop_slide wrote:
| 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?
| pythonbynight wrote:
| 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.
|
| https://github.com/talkpython/htmx-python-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).
|
| https://github.com/mikeckennedy/jinja_partials
|
| Maybe that's what you're looking for?
| bityard wrote:
| 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.
| kitd wrote:
| HTMX has quite a few before/after events that you can respond
| to:
|
| https://htmx.org/reference/#events
| tomatowurst wrote:
| 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.
| recursivedoubts wrote:
| 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.
| clairity wrote:
| 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.
| pythonaut_16 wrote:
| 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.
| adfm wrote:
| HTMX + Alpine JS seems to be prevalent.
| reducesuffering wrote:
| It's hilarious to me that HTMX is JS code and Alpine.js is
| HTML.
| sgt wrote:
| A good (more conventional) alternative is to just use Django. You
| get all of this functionality built in, plus much more.
|
| Also possible to use HTMx so you avoid JavaScript as much as
| possible,
| andybak wrote:
| 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.
| saila wrote:
| 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.
| gen220 wrote:
| 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)
| saila wrote:
| 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.
|
| Upgrading a big Django app is much simpler IME.
| gen220 wrote:
| 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.
| digisign wrote:
| 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...
| gen220 wrote:
| 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.
|
| [1]: https://flask-oidc.readthedocs.io/en/latest/ they
| looked a lot like this, fwiw. Although to your point,
| this too, hasn't been updated in 5 years. :)
| CuriouslyC wrote:
| 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.
| saila wrote:
| 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.
| sgt wrote:
| First thing I do is disable the admin interface. I think
| most serious Django devs view it as a gimmick.
| andybak wrote:
| Not all of us.
| andybak wrote:
| > the ORM is hot garbage
|
| It really is not.
| peller wrote:
| 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:
|
| https://github.com/briancappello/flask-unchained
| nop_slide wrote:
| 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.
| vosper wrote:
| This worked for me
|
| https://www.npmjs.com/package/reload
| nop_slide wrote:
| Doesn't this just serve your files?
|
| 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.
| vosper wrote:
| 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.
| tga wrote:
| 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.
| rufugee wrote:
| 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.
| schlch wrote:
| 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.
| kareemm wrote:
| 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.
| recursivedoubts wrote:
| very glad you are finding htmx useful :)
|
| regarding point 1:
|
| _1. When you 're looking at a template the HTMX syntax makes
| it obvious what happens_
|
| I am trying to codify this design principle under the term
| "Locality of Behavior". I have written an essay on this idea
| here:
|
| https://htmx.org/essays/locality-of-behaviour/
|
| there are other newer libraries that exhibit this
| characteristic as well: tailwinds and alpine.js for example
| kareemm wrote:
| 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!
| dopeboy wrote:
| 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?
| felipeccastro wrote:
| 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.
| digisign wrote:
| 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.
| brtkdotse wrote:
| 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.
| kareemm wrote:
| 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.
| tomwojcik wrote:
| 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.
| robertoandred wrote:
| You don't need to build routing or back button handling with FE
| frameworks.
| xcubic wrote:
| You dont'?
| qudat wrote:
| It's handled for your with a library like react-router.
| xcubic wrote:
| That is precisely the point. You have to add more stuff
| on top.
| cactus2093 wrote:
| 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.
| CraigJPerry wrote:
| >> 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.
| theptip wrote:
| 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).
| number6 wrote:
| Can you elaborate on the render fragment on GET/POST part?
| That sounds interesting!
| brylie wrote:
| See the following video tutorial starting at 9:18 for an
| example of rendering a template fragment in a Django view
| that gets returned to HTMX
|
| https://youtu.be/H_m1g8XOtHY
| jameslao wrote:
| 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].
|
| [0] https://www.crocodile.dev/blog/css-transitions-with-
| tailwind...
| batterylow wrote:
| Sounds like my stack for https://PlotPanel.com. It's Alpine.js,
| htmx, Tailwind CSS, and Django on the back-end. Going to have a
| read of your article!
| tomatowurst wrote:
| 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
| sixhobbits wrote:
| 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.
|
| [0] https://htmx.org/extensions/web-sockets/
| tomatowurst wrote:
| 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?
| sixhobbits wrote:
| Good question - if you do some digging, I'd love to read
| about how they stack up!
| recursivedoubts wrote:
| 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
| tomatowurst wrote:
| 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.
| recursivedoubts wrote:
| yep, exactly, so LiveView needs to have that web socket
| doing diffs between the client and server side
|
| htmx is just html++: any element can make any sort of HTTP
| request (GET, DELETE, etc.) based on any event and replace
| any other element in the DOM.
|
| much simpler and "dumb" when compared w/ liveview, with no
| particular server-side implementation implied
| deniz-a wrote:
| 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
| bulatb wrote:
| 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.
| traverseda wrote:
| >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.
| caymanjim wrote:
| 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.
| e67f70028a46fba wrote:
| Many SPAs I use feel glacial compared with MPAs. You can
| tune either approach and htmx apps take away the clunkiness
| of full page refreshes.
| bulatb wrote:
| > 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.
| traverseda wrote:
| >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.
___________________________________________________________________
(page generated 2022-03-29 23:00 UTC)