[HN Gopher] Django, HTMX and Alpine.js: Modern websites, JavaScr...
___________________________________________________________________
 
Django, HTMX and Alpine.js: Modern websites, JavaScript optional
 
Author : czue
Score  : 282 points
Date   : 2021-11-23 15:37 UTC (7 hours ago)
 
web link (www.saaspegasus.com)
w3m dump (www.saaspegasus.com)
 
| jamesgeck0 wrote:
| It's worth noting the security tradeoffs of these micro-
| frameworks.
| 
| HTMLX uses innerHTML/outerHTML extensively, meaning that XSS is a
| real concern. Any sanitation of user-generated content must
| happen server-side. This how traditional server-side frameworks
| generally work, but it's the opposite of how sanitation tends to
| be handled in large JS frameworks such as Angular.
| 
| https://htmx.org/docs/#security
| 
| Alpine.js requires an alternative syntax to avoid running afoul
| of unsafe-eval Content-Security Policy. With this more verbose
| syntax, there no inline expressions in templates; everything is
| bound to attributes in Alpine.data instead.
| 
| https://alpinejs.dev/advanced/csp
 
  | ketzu wrote:
  | > it's the opposite of how sanitation tends to be handled in
  | large JS frameworks such as Angular.
  | 
  | But they still do server side input validation, right?
  | Otherwise, _that_ would be a security concern.
 
| btown wrote:
| An alternative that requires even less server-side work is to use
| PJAX https://www.npmjs.com/package/pjax which is the spiritual
| successor to Turbolinks from the early Rails days. It's really a
| two-step process:
| 
| - create a quick JS file that loads and configures PJAX to
| automatically intercept links and - wherever you would have
| $(function() {}) ensure that it's also triggered on the PJAX load
| event, and is idempotent (e.g. check if you initialized a
| component before initializing it again)
| 
| Then you just render pages server-side like it's 2000, without
| any pjax-specific code needed in your templates themselves.
| 
| If you're building a data-focused product either solo or with a
| small team, it allows you to focus on your Python code, and
| anything frontend is as easy as accessing the variable in a
| Django template. Of course, it's a massive accumulation of
| technical debt - when you're successful you'll need to rewrite in
| a modern framework for maintainability and agility. But when you
| need to "punch above your weight class" and just get a product
| out into the world, it can be an amazing technique.
 
  | hermes8329 wrote:
  | Since when is Django not a modern framework?
 
    | acdha wrote:
    | I read that as a modern JavaScript framework. I think there's
    | definitely a good debate about what "modern" means in that
    | case because I think it's less about "modern" and more along
    | the lines of "suitable for a large team working on complex
    | client-side functionality". Reaching for that prematurely can
    | add a massive toolchain to your critical path, which adds a
    | lot of frictional cost you might not see sufficient benefit
    | from.
    | 
    | One of the challenges we have is that people tend to hear
    | about practices from very large tech companies because they
    | have enough people to have things like developer evangelists
    | and time to write lengthy blog series or produce videos. That
    | often leaves people without the nuance that some of the
    | tradeoffs make more sense when you have 50 developers
    | including a dedicated support group but smaller teams might
    | not make back the cost of entry. I like posts like this for
    | reminding people that there are other options which might be
    | appropriate for different projects, especially since even at
    | large organizations it's usually easy to find small projects.
 
      | hermes8329 wrote:
      | I figured they meant js frameworks. This is definitely my
      | slanted point of view but I rarely consider anything
      | JavaScript modern. Django 4 seems much more so
 
  | recursivedoubts wrote:
  | pjax (first released 8 years ago) preceeded turbolinks (6 years
  | old), and was the inspiration for it
  | 
  | htmx is an attempt to drive HTML forward as a hypermedia, so it
  | exposes explicit, client-side attributes, rather than hiding
  | them as with pjax/turbolinks, although there is an attribute,
  | hx-boost, that acts similar to them both
  | 
  | worth noting that intercooler.js, which was the predecessor for
  | htmx, is 8 years old as well
 
| joelbluminator wrote:
| I like how many frameworks end up cloning what Rails is doing
| (Stimulus / Turbolinks etc).
 
| cosmotic wrote:
| What makes it 'modern'?
 
| joseferben wrote:
| I wrote about my experience evaluating the same stack here:
| https://www.joseferben.com/posts/hoarddit_a_website_to_disco...
 
| miki_tyler wrote:
| This is a very promising architecture! We are actually building a
| template for Kit55 (http://stack55.com) that illustrates the use
| of Alpine,js. I think we should look into HTMX as well. Do you
| know if there is a comparison of Alpine.js vs HTMX somewhere?
 
  | czue wrote:
  | I'm not sure! As I say in the article, I kind of think of HTMX
  | as "alpine for AJAX"
 
  | recursivedoubts wrote:
  | From a sibling comment:
  | 
  |  _htmx is for syncing client side actions with the server
  | effectively within the hypermedia model
  | 
  | AlpineJS (and hyperscript) are better for purely front end
  | needs.
  | 
  | htmx and Alpine pair well together, as does htmx/jQuery,
  | htmx/VanillaJS or, if you are brave, htmx/hyperscript _
 
| awinter-py wrote:
| 'django saas startup kit' concept of the author is really smart
| 
| there's a hole in the market for people wanting to use frameworks
| to make saas sites -- frameworks provide great primitives that
| are subtly unusable for some modern web apps. Login but not saml,
| admin but not multitenant, forms but not multiple forms on a page
| 
| feels like this scratches an increasingly common itch of 'the web
| as a platform isn't shaped like what people use the web for'
 
| jpe90 wrote:
| Any opinions on how this (or a PETAL stack) compares to using
| Clojure & Clojurescript?
 
| Mizza wrote:
| I've been moving from Django to Elixir/Phoenix/LiveView and
| loving it so far. I hated the Angular/React era of the web and
| mostly moved to doing backend development, but the Live App era
| has reinvigorated my interest in web development as a whole. I'll
| miss Python a lot and hope they can come up with something that
| solves the concurrency issues, but Elixir is really pretty good
| in its own right.
 
  | SoylentOrange wrote:
  | Can you explain what you mean by "Live App" era vs React era?
  | Can you point towards resources which might disambiguate the
  | two?
 
    | dgb23 wrote:
    | The term "era" in this context has to be interpreted as a
    | personal perspective to not be confusing. The mentioned
    | paradigm is not new nor does it replace/evolve from React and
    | similar.
 
    | Mizza wrote:
    | Sure! Basically, the idea is that rather than requests in
    | JavaScript going through an API, each user connection is
    | maintained by a lightweight process on the server (which
    | Elixir can scale easily), and then interactions with the page
    | are pushed as a diff via WebSockets and then magically merged
    | into the DOM. Interactive pages, no JavaScript required. I'm
    | still pretty new to it, but after learning the ropes it's
    | seeming very productive, and most importantly, fun.
    | 
    | https://dockyard.com/blog/2018/12/12/phoenix-liveview-
    | intera...
 
      | adamddev1 wrote:
      | So then this can never work offline like a single page
      | React PWA could then I guess? For me after seeing offline-
      | first PWAs it's hard to want to go back to building stuff
      | that's only available online, but I guess everyone's use-
      | case is different.
 
        | BoumTAC wrote:
        | what is your use case of offline ? I've never seen the
        | point. For example what the purpose of a social offline
        | app ? I can't refresh feed, I can't upload post or react
        | to any thing in my feed.
        | 
        | The only use case I know is for map where you can
        | download map so when you don't have 4G you will not be
        | lost but that's the only use case I know.
 
        | recursive wrote:
        | Working on stuff, not communicating. e.g. Google docs,
        | Photopea.
 
        | pjerem wrote:
        | Not saying offline-first apps have no interest, they
        | totally can have some.
        | 
        | But in more than ten years, offline mode have never been
        | a requirement on any of the projects I worked on.
        | 
        | What I'm saying is that offline mode is just a feature
        | like any other and it's one with a huge cost in
        | architecture complexity.
        | 
        | And, although it's just my own opinion, I think if you
        | want to be offline first, odds are that better stacks
        | than the web exists for those needs.
 
      | drbw wrote:
      | So pretty much the Blazor Server approach in the Dot Net
      | world then?
 
        | shijie wrote:
        | Yes, basically. Fun fact: Blazor and LiveView were
        | developed independently, around the same time as each
        | other! Just two similar implementations in disparate
        | communities.
 
        | pantulis wrote:
        | Guess that was due to browser-land innovations that made
        | this a possibility.
 
        | culturedsystems wrote:
        | It's also not unlike JSF in the Java world, which went
        | out of fashion 10 or so years ago, and for good reason:
        | relying on a framework to paper over the distinction
        | between client and server side turned out to be much more
        | complicated and fragile than a cleanly defined
        | separation. I haven't seen any authors or users of these
        | recently developed server-side-first frameworks discuss
        | this prior art, but I'd be interested to see if they've
        | come up with a way around what seemed like a fundamental
        | problem in the approach.
 
        | keewee7 wrote:
        | Blazor Server and Blazor WebAssembly needs to be marketed
        | separately. Most people have heard about Blazor
        | WebAssembly but are unaware that LiveView-style web
        | development is possible in the .Net world using Blazor
        | Server.
 
        | SketchySeaBeast wrote:
        | Yes, yes they do. I don't know why you'd name pretty much
        | the exact opposite techs the exact same thing.
 
        | jmnicolas wrote:
        | I don't use Blazor, however when I went to get basic info
        | about it every article I have read were very clear that
        | there's 2 ways to dev a Blazor app.
 
    | trymas wrote:
    | OP probably talking about Phoenix's "LiveView"
    | (https://www.phoenixframework.org/ check the video about it).
    | 
    | Phoenix LiveView is a framework where it keeps websocket open
    | with the client and renders DOM changes server side and
    | passes it to the client [0]. Thus with fully server side
    | development without any JS you can have almost full SPA
    | experience.
    | 
    | [0] Have no experience with it, and only read about it some
    | time ago, so don't judge me on the details, but the gist of
    | the "LiveView" idea should be like that.
 
      | beardedetim wrote:
      | But you still need JS to update the DOM and handle the
      | websocket stuff, right? Or is this all somehow done with JS
      | disabled?
 
        | dgb23 wrote:
        | Right. It uses JS but you don't write any. Or very
        | little. Or in a custom DSL/framework.
 
        | hunterb123 wrote:
        | Important distinction, as it wouldn't work when JS is
        | disabled in browsers.
        | 
        | I don't see the point of going back to full server side,
        | you have to scale more with more users.
        | 
        | The only benefit would be if it all worked without
        | running JS in browsers, but it doesn't.
 
        | BoumTAC wrote:
        | Don't you have to scale your api too ?
 
        | hunterb123 wrote:
        | Yes, but now you have to scale both the data layer logic
        | and view layer logic when doing server side rendering.
 
        | BoumTAC wrote:
        | So now it's two times the hassle, two times the money
        | spent
 
        | porker wrote:
        | 99% of the time no one runs into scaling issues and
        | worrying about it is premature optimisation. I have to
        | remind myself that all the time.
        | 
        | And no, same hassle, same money spent. Thought about from
        | the start server-side rendered pages are almost as
        | cacheable as API responses will be. If you can't cache
        | you're in for a world of expense at scale whichever way
        | you go.
 
        | beardedetim wrote:
        | I have (limited) experience scaling long-lived websocket
        | connections and it _sucked_. It is _way_ easier to scale
        | out little Node servers that are "stateless" than it is
        | to ensure that Client A is connected to Socket A.
        | 
        | I would much rather scale out my REST/Graph/RPC API
        | instead of having to scale out a WS API.
 
        | dqv wrote:
        | > as it wouldn't work when JS is disabled in browsers.
        | 
        | You can make it work when JS is disabled as well, you
        | fall back to rendering regular HTML. It does require a
        | little extra work, but it's not insurmountable (e.g.
        | using @conn instead of @socket).
        | 
        | >you have to scale more with more users
        | 
        | I might opt for additional optimizations once it gets
        | bigger, but I'm not too worried about scaling Erlang
        | processes.
 
        | beardedetim wrote:
        | Yup, this is my thinking as well. If I go back to fully
        | server side, it's because I can somehow instruct the
        | browser to update without JS involved.
 
        | [deleted]
 
        | sodapopcan wrote:
        | It's done with JS but that's all written for you. But as
        | a bonus, LiveView apps do work without JS (they just
        | aren't updated over web sockets anymore).
 
        | bcrosby95 wrote:
        | I assume you have to specifically design your site to
        | work with both the request/response model and the
        | LiveView model in order for this to actually work, as
        | opposed to LiveView being able to plug that hole
        | automatically for you.
 
        | sodapopcan wrote:
        | To be a little more concrete, here's an example:
        | <%= live_patch "about", to: Routes.about_path(@socket,
        | :index) %>
        | 
        | which creates:                 about
        | 
        | The data attributes are read by the LiveView HTML and are
        | otherwise ignored by a JSless broswer.
        | 
        | Edited to fix glaring code sample error.
 
        | sodapopcan wrote:
        | Nope, all you need to do is make sure that everything has
        | a route (which is very much encouraged in LiveView) and
        | it works.
 
        | dqv wrote:
        | You can design singularly for LiveView and it handles
        | everything. But if you want both request/response and
        | LiveView (e.g. to mix the two or fallback to r/r when no
        | js) you have to be more explicit in your design. It's
        | mostly trivial though. I have authentication pages that
        | use the old controllers but pages that use only LiveView
        | without any hassle.
 
  | emodendroket wrote:
  | I haven't done frontend work for a few years, but Angular was
  | really a revelation to me when it first came out. For all the
  | headaches, it made it practical to do stuff that was really
  | cool.
 
  | [deleted]
 
  | simonw wrote:
  | There's a thriving ecosystem these days around the ASGI
  | standard for building concurrent web applications in Python -
  | it came out of the Django project originally but Starlette and
  | FastAPI are the most widely used implementations of it.
 
    | Starlevel001 wrote:
    | ASGI is a bad solution to the concurrency issues as the
    | ecosystem is heavily centralised around asyncio (which is
    | ``java.lang.Thread`` for async/await, with all the pitfalls
    | included).
 
  | [deleted]
 
  | koyote wrote:
  | Having recently looked into Blazor Server (similar to LiveView
  | but in C#), one of the cons Microsoft listed was the
  | scalability (compared to a typical SPA) as each client now
  | needs an active websocket connection to the server, which will
  | require more server resources.
  | 
  | Do you have any experience in that? I'd love to know where
  | server resource requirements sit between SPA, this and a
  | typical SSR site like Django.
 
| amenod wrote:
| I agree that the way modern JS (need to?) download half the
| Internet for a semi-useful app is annoying, wasteful and
| dangerous.
| 
| However, I still remember the hell that was updating the state
| and keeping the rendering in sync with it when using jQuery.
| Native JS of course doesn't improve on that, and (judging by the
| description - no experience with it) Alpine.js doesn't either.
| For me, the paradigm of rendering from the internal state is what
| makes React (and Vue,...) useful. Too bad that npm ecosystem
| sucks and that everyone is inventing new shiny useless new things
| all the time... But React makes non-trivial single-page apps
| possible.
| 
| Of course, if you need server-side rendering (for example because
| of SEO) then the equation changes, and maybe using Alpine.js
| makes sense.
 
  | acdha wrote:
  | > However, I still remember the hell that was updating the
  | state and keeping the rendering in sync with it when using
  | jQuery. Native JS of course doesn't improve on that
  | 
  | I think this varied a lot depending on how teams approached it
  | and that a lot of the appeal to something like React, Vue, etc.
  | was simply that there was one way to do it.
  | 
  | The approach I've been quite happy with is to use JavaScript
  | classes (IE11 is less than 1% of global web usage) for internal
  | state, where you follow standard practice for having ownership
  | and updates between different parts of your app, and the HTML5
  | data APIs for the public elements which are managed by
  | different codebases. Web Components has something like 95-97%
  | availability these days but this can be as simple as using
  | element.dataset.whatever as needed. React is definitely good
  | for huge apps but a significant fraction of the web sites I use
  | are solidly in the level of functionality which in 2021 doesn't
  | need functionality outside of what a modern browser provides.
 
  | stepbeek wrote:
  | That internal state is a burden on small teams though - you're
  | efectively implementing the persistence layer twice. I'm
  | totally onboard for SPAs as an option when breaking down an
  | organization, or for solving a particular kind of problem.
  | 
  | But they're just not worth the effort for a form-oriented
  | website with a small-medium team behind it. Almost everything
  | about a web-app is harder with an SPA.
 
  | grayrest wrote:
  | Keeping all state server side is a completely reasonable
  | approach. The 37Signals guys have been advocating for it since
  | 2006 or so and as long as you have a low latency connection to
  | the server then it usually works great.
  | 
  | What doesn't work well (and what tended to happen with jQuery
  | apps) is having state both on the client and on the server and
  | having to coordinate between the two. My personal preference is
  | for client side state with a lighter setup than React (i.e.
  | Svelte). I like the predictable latency and I feel you don't
  | run into a complexity barrier (e.g. multi-step forms) as the
  | app grows.
 
  | deergomoo wrote:
  | > Alpine.js doesn't either
  | 
  | While it won't fit the needs of a complex app with dozens of
  | components, it does drive the UI from the state. In fact, it
  | uses Vue's reactivity engine.
 
  | smolder wrote:
  | I was very good at making reliable apps and managing states
  | manually in the jquery days. Having a scaffolding helps overall
  | and in many ways, but now in the dense jungle that is the JS
  | "ecosystem", there is sometimes a productivity loss searching
  | for "the right way to do X in framework Y" or troubleshooting
  | underlying tools instead of just writing the code to do the
  | thing. Easier, maybe, but not at all satisfying.
 
    | scaryclam wrote:
    | I think the trick is, that state needs to be carefully
    | considered at an overall systems level, not just client vs
    | server. That's quite hard, so many (most?) devs don't do it.
    | Certainly, I've seen state managed well using jquery, and
    | even vanilla JS in the ES5 era, so frameworks don't make it
    | possible, it's always been so.
    | 
    | So the question is, do frameworks make it easier? I don't
    | think they really do. I think they make it easier to
    | manipulate state, but not designing your system will still
    | mean state being mismanaged.
 
| gavinray wrote:
| Can someone genuinely explain to the the desire/interest to use
| HTMX/Hotwire/LiveView etc?
| 
| I was writing web apps when rendering templated HTML views on
| your server was standard, and you had controller endpoints that
| returned HTML content, or things like Rails "Unobtrusive
| Javascript" where you had code like:                 $('#user-
| list').html("<%= j render('index', users: @users) %>")
| 
| As an automatic callback to some action.
| 
| Whether or not you love or hate this model of development is
| irrelevant, because if at some point you need to render on a
| client other than a browser -- you have to start from the
| beginning and write an API now.
| 
| IE, so that your Android/iOS app in Java/Swift or whatnot, can
| ask your backend for data and render it using the tools available
| on that platform.
| 
| When we turned apps into pure API's and just exchanged data with
| them, it opened up the ability to be platform-agnostic.
| 
| I guess I don't understand why someone would choose to build an
| app that sends HTML over the wire instead of JSON/XML/whatever,
| that any client can render. All it means is that you have to
| write this functionality later when you want it, in addition to
| now having this HTML stuff.
 
  | roywiggins wrote:
  | If you already have an app with no AJAX going on, HTMX is
  | _hugely_ helpful in progressively bringing it in. You just
  | provide endpoints for the forms or other pieces of pages that
  | need updating, and wire them up to the page with the right HTMX
  | tags.
  | 
  | Even starting from scratch, it can be very productive to keep
  | all your HTML in one place- eg Django templates- and use HTMX
  | and a sprinkling of JS to provide client-side interaction. You
  | can jump straight into laying your app out without building the
  | whole thing up as platform-agnostic APIs first. When you need
  | API endpoints you can start adding them based on the context
  | objects you're providing your Django templates, since all the
  | information is in there anyway. There's _real_ benefits to
  | putting all your presentation and _most_ of the logic on the
  | server.
  | 
  | And keep in mind that many web apps will _never ever_ need to
  | also be a native app.
 
  | acdha wrote:
  | First, many sites do not need a mobile app -- people who sell
  | apps like to present that as a requirement but there large
  | categories where it doesn't make sense and most users won't
  | install it because it takes space on their device and they
  | [correctly] fear ads, notification spam, and possible invasions
  | of their privacy. I've seen figures for this where pretty well-
  | known organizations spent millions on the app and then saw
  | install rates under 10% with most users opening it only once or
  | twice.
  | 
  | Second, this is something of a false dichotomy: if you have a
  | website, you need to have HTML somewhere. One approach is to
  | use an SPA but that increases the cost somewhat significantly
  | and absent a significant engineering effort will reduce
  | performance and reliability because you are moving
  | functionality out of a high-performance data center where you
  | control everything onto the users' devices where you have to
  | work with whatever browser and extensions/ad blockers they have
  | installed.
  | 
  | An alternative approach is to render HTML on your servers --
  | quite possibly using the same JSON API as the source -- and
  | then progressively enhance it with the functionality which
  | makes sense to do on the edge. This gives you a hefty
  | performance win for the initial page-load times, helps with
  | things like search engines, and ensures that your users get at
  | least the basic experience when something goes wrong with
  | client side JavaScript (network errors, browser compatibility
  | issues, ad blockers, etc.) rather than nothing working at all.
 
    | tata71 wrote:
    | Can you name one, that the group would know, that wouldn't be
    | improved by a convergent phone or tablet offering?
 
      | acdha wrote:
      | When was the last time you used an application from a
      | gallery, archive, museum or library? How many people use
      | https://apps.apple.com/us/app/wikipedia/id324715238 instead
      | of visiting wikipedia.org? I'm not naming names but this
      | came up a number of times at meetings I was involved with
      | in the GLAM community where people mentioned having spent
      | considerable amounts of money on apps, even winning design
      | awards or getting featured in the Apple AppStore, and then
      | seeing that their daily active users never came within 4
      | orders of magnitude of their web traffic.
      | 
      | What they generally had in common is that they're content-
      | heavy (i.e. solidly in what the web was designed for),
      | might not require authentication, and most importantly
      | aren't something most of the users wanted to use all of the
      | time. If you are trying to get the hours for a tourist
      | destination or even a restaurant, look at public
      | information, etc. the time needed to login to the app
      | store, authenticate to approve the purchase, wait for a
      | large file to download, open the app and complete any
      | mandatory enrollment, wait for it to retrieve content, etc.
      | was often orders of magnitude slower than using the
      | website. Restaurants and bars are a great example of this:
      | if it's your hangout and they have something like
      | integrated ordering, maybe a trivia night or something like
      | that, the app can be useful. For most people, however, a
      | webpage with the contact info and a menu with
      | Apple/Google/Stripe buttons to pay is going to be better
      | than an app they use a couple of times a year.
      | 
      | The other key thing to understand is that this is a
      | question of priorities and budgets. It wasn't that there is
      | no possibility of doing anything useful for these
      | organizations in a mobile app but rather than the cost
      | wasn't worthwhile for the incremental benefit to the users,
      | especially when you considered the opportunity cost of not
      | spending that much money on something else, especially
      | since most of the cool things you could do in an app could
      | also be done on the web with very similar quality but with
      | the difference that you only had to build one version
      | rather than 2+ and the web version required much less
      | ongoing maintenance.
 
      | dec0dedab0de wrote:
      | Hn would be worse as an app, but more notably Twitter, and
      | reddit would be better as pure web pages if they didn't
      | purposely cripple them to funnel people into the app.
 
        | scns wrote:
        | Well, i usually read HN on my mobile with Materialistic.
        | It is one of the apps i use the most often.
 
        | hunterb123 wrote:
        | Same, it works offline, loads faster with bad mobile
        | connection, better gestures & UX overall.
 
    | systemvoltage wrote:
    | I am open to HTMX. Seems refreshing but I am a little
    | confused about how to structure the backend API returning
    | small bits of HTML? Wouldn't that be a colossal nightmare to
    | reason about?
    | 
    | I can think over time I'll have endpoints like this:
    | POST https://foo.com/bar-section/baz-button
    | 
    | No? Haven't quite thought about it deeply but I can imagine
    | logic mixed with UI bits in the backend.
 
      | recursivedoubts wrote:
      | Not really, as long as you keep your HTML-driven
      | interactions from becoming too fine grained.
      | 
      | For example, if you have a search page that provides
      | management of contacts + active search & click to load
      | functionality, it might look like this:                 GET
      | /contacts - get a list of contacts + search & click-to-load
      | functionality       POST /contacts - create new       GET
      | /contacts/:id - get the details for the contact       PATCH
      | /contacts/:id - update the contact       PUT
      | /contacts/:id/archived - archive the contact       DELETE
      | /contacts/:id - remove the contact
      | 
      | All pretty reasonable and all can reuse the same few
      | templates and sub-templates for rendering responses.
 
      | acdha wrote:
      | I think you can get pretty far by having good conventions
      | and not over-thinking it, but remember also that this is
      | all about being pragmatic instead of taking a one-size-
      | fits-all approach -- if you found yourself doing a _ton_ of
      | highly-granular requests, that might be a clue that you're
      | not in the sweet spot and an API client might be a better
      | fit.
 
      | deniz-a wrote:
      | > API returning [...] HTML
      | 
      | The endpoints that return endpoints are not API endpoints,
      | they are UI endpoints like `/index.html` or `/login` or
      | `/Results.aspx?id=3984272`. Now you can have `/login/email`
      | or `/login/google` and switch between them like
      | .
      | 
      | As for the machine-consumed API, you have quite a few
      | options. e.g.: The server that serves these resources may
      | serve JSON to the same URLs through content negotiation, or
      | the API may be separate, or you can have a generic API that
      | is consumed by mobile app, desktop app and HTML-producing
      | server (as opposed to JS app delivered by static file
      | server or framework SSR).
      | 
      | The UI runs on the server, using REST to change client
      | state over a stateless protocol similarly to how a React
      | app may use Redux.
 
      | jspash wrote:
      | Have a look at how Phoenix(Elixir) does it with LiveView.
      | You simply write everything as a server rendered view and
      | the framework pulls things apart and sends just what
      | changed over a web socket. Its mind blowing how fast it is
      | (can be. Latency is real)
      | 
      | I have no doubt that this style of front-end management is
      | going to be a game changer in the next few years. Of course
      | full-on SPA frameworks will still have their place. But if
      | you aren't writing the next Google Maps clone, maybe you
      | don't need all that. It's made me love web dev again after
      | hating the complexity explosion of recent years.
      | 
      | https://m.youtube.com/watch?v=8xJzHq8ru0M
 
    | 0des wrote:
    | > First, many sites do not need a mobile app -- people who
    | sell apps like to present that as a requirement
    | 
    | Yes, Testify! Also, I'd like to mention, so many of these
    | upsold apps end up being a wrapper around the normal web
    | view. I've seen this being advertised/proposed as a plus, as
    | well "No need for your customers to learn a new interface, we
    | specifically engineer your app experience to be _just_ like
    | the web experience ". It's interesting to see heads nodding
    | in reply to this.
 
      | acdha wrote:
      | Oh, yes -- definitely saw those. My favorite were the ones
      | in the pre-WKWebView era where the app was basically the
      | website, except slower because it didn't have the
      | JavaScript JIT enabled.
 
  | Mikeb85 wrote:
  | Honestly because sometimes it's all you need.
  | 
  | Take Rails Hotwire for example. It's easy to write, easy to add
  | JS when you need it, easy to make mobile apps since they've
  | already done the work. It's live on Basecamp and Hey.com apps,
  | it works very nicely. Hey is easily the snappiest email client
  | I've ever used.
 
  | javajosh wrote:
  | This is a specific example of a class of problems I refer to as
  | "Where the indirection go?" In this case, the indirection is in
  | the form of a function that takes structured data and produces
  | html. That function can execute in the server, or on the
  | client. Which we can term moving a function "closer" or
  | "further" from the client. This is easier to imagine with
  | isomorphic javascript code, but it applies to anything (with an
  | extra translation step as you cross the network boundary).
  | 
  | What you've discovered is a general property of systems that
  | you want to keep your entropy low for as long as possible, and
  | defer the final boost in entropy until the last possible
  | minute. This keeps your options open. It also means publishing
  | low entropy APIs and boosting in the client. In your case,
  | you've correctly noted that it allows you to support different
  | clients more easily.
  | 
  | There are 3 reasons to pay the price to boost entropy on the
  | server: to intentionally make it harder to consume your API, to
  | protect a proprietary boosting function, and because you didn't
  | realize it was bad design.
 
  | kirse wrote:
  | Lots of reasons:
  | 
  | 1) No need for 3.7GB of node_modules to crank out a simple site
  | 
  | 2) Single solution, easier to bring on junior developers and
  | reason about application logic
  | 
  | 3) Caching much easier, too many people think they need real-
  | time push when NRT-polling + caching is far easier and more
  | performant
  | 
  | Broadly speaking it's often a case of YAGNI. The JS ecosystem
  | really does still suck for its complexity, I remember that
  | every time I ramp up a new developer onto a React project. It's
  | smoothed out with tooling but the litany of JSON configuration
  | files and the mess created by hot-reload + proxying +
  | microservices etc etc. Often just YAGNI.
  | 
  | People today don't remember the VB6 IDE days where you could
  | slap a button on a Form, write a line of code for a MessageBox,
  | and smash that play button with zero effort. JS development is
  | often about working your way through a tangled spider-web of
  | helper utilities and config files and JS modules at which point
  | when it finally works you're afraid to rev anything.
 
    | recursivedoubts wrote:
    | bang on, especially that last part
    | 
    | a bit focus of htmx, alpinejs (and htmx's sister project,
    | https://hyperscript.org) is putting the logic _on the
    | element_ , so you can see exactly what a button, etc. does
    | just by looking at it, and without trawling through ten files
    | of indirection
    | 
    | i am trying to popularize the term Locality of Behavior to
    | describe this design goal:
    | 
    | https://htmx.org/essays/locality-of-behaviour/
 
      | lhorie wrote:
      | I'm curious about your thoughts on that locality of
      | behavior idea vs aspects of precision and composability.
      | For example, the argument goes that the behavior of `hx-
      | get` is obvious upon inspection, but the terseness is
      | achieved by omitting the event type (i.e. it's
      | assumed/implied that hx-get runs on click). The
      | quintessential widget where that breaks down is the table
      | w/ checkboxes for batch operations over an arbitrary subset
      | of rows. That's where less DSL-ish frameworks' abstraction
      | via state management tend to shine, since they allow the
      | developer to more precisely specify how disparate
      | checkboxes relate to a bigger picture that may also involve
      | table sorting (both client and server varieties) or nested
      | modal structures or other forms of complexity.
 
  | dagw wrote:
  | _you have to start from the beginning and write an API now._
  | 
  | Is it really that much more work? Much of the time the big
  | difference is just be replacing                  return
  | render(my_template, my_data)
  | 
  | with                  return to_json(my_data)
 
    | acdha wrote:
    | A few years back, I implemented this as a Django CBV which
    | worked quite well:
    | 
    | https://github.com/LibraryOfCongress/concordia/blob/main/con.
    | ..
    | 
    | That handles a few things like pagination for list views,
    | calling get_absolute_url() on objects in the template context
    | which have that method defined, and running all URLs through
    | request.build_absolute_uri().
 
  | recursivedoubts wrote:
  | Because of the simplicity, flexibility and power of the
  | hypermedia programming model.
  | 
  | - simplicity: e.g. something like active search can be
  | implemented with a few attributes:
  | https://htmx.org/examples/active-search/
  | 
  | - flexibility: e.g. because of the uniform interface,
  | versioning is much less of an issue
  | 
  | - power: e.g. deep linking is trivial
  | 
  | Additionally, there is increasing awareness[1] that Application
  | APIs and Data APIs have different needs and "shapes", and, once
  | you have split them up, reconsidering using hypermedia for your
  | application API[2] is a reasonable thing to do
  | 
  | [1] - https://max.engineer/server-informed-ui
  | 
  | [2] -https://htmx.org/essays/splitting-your-apis/
 
  | lhorie wrote:
  | Worth pointing out that HTML is more ubiquitous than you're
  | making it out to be: just plop a WebView in your native app,
  | and you're done. I know, for example, that the Uber app does
  | webviews in some places; you probably wouldn't even be able to
  | figure out where just from looking at it as a user.
  | 
  | Another case in point: is your dev team going to support PSP
  | devices[0]?
  | 
  | [0] https://shkspr.mobi/blog/2021/01/the-unreasonable-
  | effectiven...
 
  | [deleted]
 
  | sodapopcan wrote:
  | > because if at some point you need to render on a client other
  | than a browser -- you have to start from the beginning and
  | write an API now.
  | 
  | The answer lies in the "if" there. The speed and lack of
  | complexity developing server-side with no API is unparalleled
  | to doing client -> api -> backend. Not to mention, you aren't
  | tying yourself into several different JS technologies (Which
  | GraphQL or REST lib? Which view framework? What testing
  | frameworks? And what's the whole backend stack? etc. etc.) I
  | can only speak for LiveView but the whole top-down experience
  | is in Elixir with sprinkles of vanilla JS (the community is big
  | into Tailwind and AlpineJS as well, but not exclusively).
  | 
  | I have real world experience of dev'ing API-first only to have
  | the company nix any plans to open up the API. Adding new
  | features is always a slog as we have to think about if the
  | business logic needs to be on the client, the server, or
  | both... not to mentioning have to update about 18 different
  | places the name of a new field you're adding.
  | 
  | The company I work for actual has a LiveView widget that is
  | embedded on their client's apps. I can't speak very well to it
  | since I only just started working there and don't actually
  | start until next week, haha.
  | 
  | But ya, I'll also echo the whole idea that a lot of companies
  | don't need mobile apps. I'm certainly one of those people who
  | uses the browser on my phone whenever I can.
 
  | joelbluminator wrote:
  | > Whether or not you love or hate this model of development is
  | irrelevant, because if at some point you need to render on a
  | client other than a browser -- you have to start from the
  | beginning and write an API now.
  | 
  | That's not true generally since many mobile apps are simply
  | wrappers around a WebView. Rails Turbolinks basically has
  | mobile shims that allows you to deploy to all platforms. Sure,
  | if you can't use a Web View on your mobile app (idk, for
  | performance reasons) that's something else. But that's not the
  | rule.
 
  | interactivecode wrote:
  | because you still want server rendered html? because you focus
  | on building websites?
  | 
  | Being platform specific makes it easier to have a higher
  | quality and integration on that specific platform.
 
    | gavinray wrote:
    | I build exclusively web apps and I still use the backend as
    | an API.
    | 
    | You fetch data from the API and render it with JavaScript.
    | 
    | React, Vue, Svelte, Angular, Alpine, pick whatever.
    | 
    | Not sending HTML over server endpoints, or using templated
    | views like ERB/EJS/EEX/etc doesn't mean you inherently have a
    | worse quality app.
    | 
    | If you do this in something like Next.js with
    | "getServerSideProps()", it's functionally equivalent.
    | 
    | React even went so far as to make "Server Components":
    | 
    | https://reactjs.org/blog/2020/12/21/data-fetching-with-
    | react...
 
      | senko wrote:
      | You build web _apps_. The parent talks about web _sites_.
      | 
      | Not everything on the web is a full featured interactive
      | application, this is exactly what they're talking about.
 
      | sodapopcan wrote:
      | I feel like I gotta call out the LiveView is a bit in a
      | class of its own. HEEx is rendered on the server, but the
      | diff sent over the wire is the absolute minimal diff it can
      | be with a map of where it in the DOM. Often this is just
      | text. LiveView also gives you a running process on the
      | server (a virtual machine process, not a linux process)
      | that holds the user's state (like if they're logged in, for
      | example) and makes things like "who's online?" and other
      | concurrent features almost trivial.
 
      | roywiggins wrote:
      | If you render everything with JavaScript then HTMX is not
      | really going to be useful at all. It's useful for
      | developing apps that simply don't need the sort of complex
      | client-side interaction that those frameworks enable. The
      | article points this out- if you want to write a SPA in
      | React, HTMX is not going to help at all. But if you want a
      | mostly-server-rendered page with some AJAXy interactivity,
      | HTMX is _much much easier_ than trying to shoehorn in
      | _some_ client-side rendering just for the AJAXy bits.
      | 
      | The main thing is is that there is still a substantial
      | demand for tools that let you mostly avoid writing lots of
      | JavaScript, whether on the server or the client.
 
        | gavinray wrote:
        | This is a super valid answer, thanks.
        | 
        | Psychological bubble from the sorts of apps I build I
        | suppose, I hadn't considered:                 > It's
        | useful for developing apps that simply don't need the
        | sort of complex client-side interaction that those
        | frameworks enable.
 
      | [deleted]
 
  | hedgehog wrote:
  | I've used Intercooler.js (the predecessor to HTMX) a bit on top
  | of Django and small Go apps (no framework). If you don't need a
  | lot of complex state and interactivity on the front end it can
  | work well. This approach avoids the complexity of having two
  | codebases, you can get the performance/usability benefits of
  | partial page updates while keeping 99% of the codebase in one
  | language.
 
  | czue wrote:
  | The need for a native mobile app (or any kind of platform-
  | agnostic behavior) probably negates much of the value of these
  | stacks.
  | 
  | That said, many projects don't have or need mobile apps, and
  | many more can probably get away with a web-first mobile app.
  | 
  | For those apps this stack can vastly simplify and streamline
  | development
 
    | gavinray wrote:
    | > That said, many projects don't have or need mobile apps,
    | and many more can probably get away with a web-first mobile
    | app.
    | 
    | To me this is like building a house that can never be
    | expanded, instead of starting with an open-ended design.
    | > For those apps this stack can vastly simplify and
    | streamline development
    | 
    | I guess this is an opinion/subjective?
    | 
    | I am very open-minded and experimental. I love trying new
    | things.
    | 
    | I've tried these technologies (HTMX, it's precursor
    | Intercooler.js, Turbolinks + Hotwire, LiveView, etc) and for
    | me they are less productive than the ways I know how to build
    | API-first, JavaScript web apps.
    | 
    | Have nothing against them, just genuinely having a hard time
    | seeing the appeal.
 
      | nauticacom wrote:
      | I've tried these technologies ... and for me they are less
      | productive than the ways I know how to build API-first,
      | JavaScript web apps
      | 
      | I think I feel the same way you do, except the other way
      | around. I genuinely can't understand how you build apps
      | productively with a separate client/server model.
      | 
      | How do you do form validations? How about authentication
      | and authorization? What about a consistent domain model? Is
      | there one copy of it on the server and one on the client?
      | Or does your client just treat everything as dumb data and
      | make network requests for every question of business logic?
      | What about data consistency throughout the interface--when
      | you update e.g. Document(id=45) with new data, how does
      | that update get propagated to every other place in the app?
      | Does that involve a client-side identity-map? Or are you
      | manually trying to send updated data to other places with
      | callbacks/whatever? etc. for ever and ever.
      | 
      | Every time I try to build an app where the frontend and
      | backend are split into a separate client and API, it ends
      | up adding _so_ many more considerations and _so_ much more
      | complexity than the traditional model. Mostly because now
      | everything that just required a database query or method
      | call before now _also_ requires a network request, but also
      | because data consistency in a long-running app is _so_ hard
      | to get right.
 
        | porker wrote:
        | > How do you do...
        | 
        | Those are all questions I have, as a 2-decade
        | "traditional web app" developer who is now doing frontend
        | work & hybrid mobile apps. I know the backend sucks for
        | some of them too, so this isn't a set of questions to
        | bash with.
        | 
        | They are the questions I'd spend money on a book or
        | learning materials to answer. They are philosophical
        | questions that seem overlooked.
        | 
        | I think the answer is JS/TS on server and client-side for
        | a lot of them, so models/classes/structs are shared; form
        | validation rules are shared (something let's face it that
        | "traditional" web apps suck massively at).
        | 
        | The one Q I feel qualified to answer is: > What about
        | data consistency throughout the interface--when you
        | update e.g. Document(id=45) with new data, how does that
        | update get propagated to every other place in the app?
        | Does that involve a client-side identity-map? Or are you
        | manually trying to send updated data to other places with
        | callbacks/whatever? etc. for ever and ever.
        | 
        | Assuming you're not talking realtime (because that's a
        | problem for both) then this is why the concept of data
        | stores (Redux, Vuex, Mobx to name a few) are so popular.
        | Because when the data is changed, and you're using a
        | reactive frontend framework, it updates all components
        | that use that data. It is, frankly, magical and
        | wonderful. But as you say, data consistency can be a
        | problem...
 
        | nawgz wrote:
        | Your questions are all... contrived?
        | 
        | > How do you do form validations?
        | 
        | How do YOU do form validations? Is it entirely on the
        | backend so it requires a round-trip before the user gets
        | feedback, and additionally requires you to wire both the
        | HTML endpoint for user feedback AND for rendering some
        | results?
        | 
        | For myself, I have a reusable Form component I can plug
        | in arbitrary tests. You can run the tests when the user
        | changes an input or on submit, with some
        | options/conditions for when you clear the feedback.
        | 
        | Then, of course, my API gives feedback as well; usually,
        | it's harder / more awkward to wire the API feedback to
        | highlight the offending Form fields, and I certainly
        | don't see how HTMX would accomplish this, so without some
        | machinery I already feel your side lacks QOL features
        | like "highlight error fields" and "autofocus first
        | offending entry".
        | 
        | > How about authentication and authorization
        | 
        | You are joking or what? There is no difference in how an
        | HTMX app would authenticate to its endpoints and how an
        | SPA would
        | 
        | Finally, you ask a bunch of questions that clearly aren't
        | any better in an API-endpoint-randomly-renders-HTML
        | paradigm...
        | 
        | > Is there one copy of it on the server and one on the
        | client
        | 
        | Obviously, but you load the client version from the
        | server at API request time... just like an HTMX powered
        | client... except an SPA keeps objects instead of a
        | rendered representation so you can do more in-depth
        | things without network trips...
        | 
        | > What about data consistency throughout the interface--
        | when you update e.g. Document(id=45) with new data, how
        | does that update get propagated to every other place in
        | the app?
        | 
        | Because you use singletons like a not-crazy person... how
        | does this happen in HTMX world where you have no data
        | representation on the front-end? Does your form have to
        | be manually wired to update every single present data
        | view that is holding that document? Seems like you're
        | worse off than me. I hold a stateful representation and
        | update the views when that representation changes,
        | automatically... Wow, literally no work required because
        | it's declarative
        | 
        | > Does that involve a client-side identity-map? Or are
        | you manually trying to send updated data to other places
        | with callbacks/whatever?
        | 
        | Laughable. the HTMX paradigm is clearly worse off here
        | 
        | > Every time I try to build an app where the frontend and
        | backend are split into a separate client and API, it ends
        | up adding so many more considerations and so much more
        | complexity than the traditional model
        | 
        | You clearly did not bother to understand how state &
        | views relate in an SPA then. Your complaints make no
        | sense either, this happens in HTMX world more than mine:
        | 
        | > now everything that just required a database query or
        | method call before now also requires a network request,
        | but also because data consistency in a long-running app
        | is so hard
        | 
        | I honestly can't tell if you're trolling me. Let me break
        | it down for you.
        | 
        | In client/server world, client asks APIs for the data.
        | Easy. Imagine a paradigm like GraphQL, the client
        | literally just loads the data. It's the same as it would
        | be on your server endpoint for HTMX, that's literally the
        | client in your world. I hold a global singleton
        | representation if my app is interconnected, or I load
        | different singleton representations for unrelated
        | subtrees if it's only partially interconnected.
        | 
        | Next, if "collaboration"/real-time features are
        | important, you make this data loading "aware" of when the
        | data changed server-side, and you refresh your data. Easy
        | as pie; you use the same function to reload. Lots of
        | options on how to update the data, but if you correctly
        | make your "load" function idempotent it is clear this is
        | trivial.
        | 
        | Finally, you write views that describe, declaratively,
        | how to render the data. Since application state
        | automatically re-renders these views, ideally not in
        | their entirety if you used a good state management,
        | you've already solved every single concern you listed
        | about "stale data" by how you wired your data loading.
        | 
        | So, great, in conclusion, HTMX endpoints are like a
        | scattered version of a client that makes all nice
        | "application" tricks virtually impossible, giving you no
        | gains in any fashion that relates to data consistency or
        | continuity, and requiring loads of manual wiring and
        | awkward data-HTML manipulation in places that have no
        | business doing it.
 
        | nauticacom wrote:
        | How do YOU do form validations?
        | 
        | I use some server-side library to do it (take your pick
        | for your language/framework of choice) which then sends
        | it back to the user, in most cases automatically wiring
        | up old field values and error messages. Checking string
        | lengths or whatever is equally easy in both cases, but
        | what's really difficult is the part you conveniently
        | hand-wave away:                 usually, it's harder /
        | more awkward to wire the API feedback to highlight the
        | offending Form fields
        | 
        | This is _the entire point_ of validations. When I render
        | everything on the server, I have my entire application
        | and its associated logic to play with; can this Person
        | access that Document? Has this Person already enabled
        | Notifications for new Revisions on this Document? etc.
        | Most server-side libraries make it equally easy to
        | surface validation errors for those questions as they do
        | questions like  "Is this Password no shorter than 10
        | characters." Every time I've tried to do this on the
        | client there's been no easy way or you have to wire it up
        | manually every time.                 There is no
        | difference in how an HTMX app would authenticate to its
        | endpoints and how an SPA would
        | 
        | I've found this not to be the case. Here are the
        | potential options I see:
        | 
        | - The client contains all the logic for who can view
        | what, and redirects or shows a message appropriately
        | using whatever mechanism is appropriate (e.g. Angular has
        | route guards, I'm sure other routers have similar
        | functionality). Because you want real data protection,
        | this logic is _also_ on the server, so now you have
        | duplicated logic and you have to hit the server multiple
        | times on every navigation, which is basically
        | impractical. - The server contains all the logic for who
        | can view what, and when the client asks the server for
        | some data, if it responds with 403 it can show a message
        | or redirect or whatever. This is okay, but now you have
        | so little information on what happened on the client side
        | that it 's a much worse experience. e.g. if I try to
        | access a document that I don't have access to on the
        | server-side, I can redirect_back and maybe show a pretty
        | message that says "hey you can't access that, maybe click
        | this link to ask for permission." If I just get a 403
        | from the server, all I can say is "uhh I don't know, you
        | can't do whatever you just tried to do."
        | 
        | This is much easier if all your logic resides on the
        | server. To check if a Person can access a Document, you
        | just call person.owns?(document) or whatever. If they
        | don't, you just redirect_to wherever, and since you
        | haven't actually rendered anything yet it's all in a
        | single HTTP request-response cycle.
        | Obviously, but you load the client version from the
        | server at API request time
        | 
        | I'm not sure you understand my problem here; it seems
        | like perhaps client-heavy people just aren't doing this
        | anymore? Ember, Backbone, et al got this part right, and
        | everything since then seems to have forgotten about the
        | "M" part of MVC.
        | 
        | What I mean is that on the server I have a Document
        | class, a Person class, etc. and the associated business
        | logic for dealing with it. Maybe a document has a bunch
        | of Revisions, and they're stored in an array or something
        | and I can get the newest revision by calling
        | document.latest_revision, or I can get properties of the
        | latest revision by just doing document.latest.title.
        | Maybe when I update a field on a Document I really want
        | to create a new Revision or something. Whatever, I'm just
        | making stuff up here, but you get the kind of business
        | logic I'm talking about.
        | 
        | How do I do _any_ of this on the client? Do I have a
        | separate Document class that maintains all the same
        | logic? Do I split the logic so some of it is on the
        | client and some is on the server? Do I put it all on the
        | client...oh but wait I can 't do that because the server
        | needs to do integrity checks or make database calls that
        | the client simply can't do.
        | 
        | In an ideal world, what I want is essentially like my ORM
        | on the server-side: a cache of every instance of every
        | model that I've loaded from the server, normalized with
        | references to one another and an easy way to retrieve an
        | object with its relationships either from memory or from
        | the database (network/API). It's then easy to update
        | Document(id=45) in one place and have it propagate to the
        | rest of the app, and if it's referenced by any related
        | objects to have the update propagate to them, too. This
        | is a _hell_ of a lot of work to create, and basically
        | none of the modern frameworks provide anything resembling
        | this.
        | 
        | ---
        | 
        | Your final few paragraphs are essentially all the rosy
        | writing out there about client-heavy approaches: look how
        | wonderful it is! Just fetch your data and we'll rerender
        | it! I understand all that. And maybe it's evidence that
        | we're just living in such different worlds that there's
        | difficulty explaining requirements to one another.
        | 
        | If I was creating Desmos or something, where basically
        | every ounce of logic exists on the client, and the
        | client's job is just to do a bunch of stuff with client-
        | generated data and display it, then yeah I'd probably
        | reach for a client-centric approach. But I'm not. Most of
        | the time I'm creating GitHub or Wikipedia or Fastmail or
        | something, where there could be some nice benefits of
        | having a fat-client that talks to an API, but the massive
        | complexity increase just isn't worth it.
 
      | andybak wrote:
      | > To me this is like building a house that can never be
      | expanded,
      | 
      | Or alternatively it's a good application of YAGNI.
      | 
      | There's always a difficult balance between that as a
      | principle and "do work upfront as it will take you longer
      | to do later down the line"
      | 
      | Everyone makes this decision based on client budget, time
      | constraints and a host of other factors. My clients tend to
      | prefer to save money in the short term. That's not uncommon
      | and it's a rational position to take for many.
 
  | andybak wrote:
  | > because if at some point you need to render on a client other
  | than a browser
  | 
  | Been doing this for decades and this has cropped up so few
  | times I can't actually think of any.
  | 
  | Your clients might not be my clients. Your projects differ from
  | mine. Don't generalise from your own experience. There's a lot
  | more websites than there are apps.
 
  | ethnt wrote:
  | Depending on your architecture, an API or rendering HTML is an
  | implementation detail, rather than the meat of the application.
  | Have your business logic elsewhere and have the API or
  | controller endpoints call out to those and just do the business
  | of rendering JSON or HTML in the controllers.
  | 
  | (I think this is inversion of control, someone can correct me
  | if I'm wrong)
 
  | dnautics wrote:
  | can't speak for the others, because they are still stateless,
  | but LiveView is stateful and this is the point, you're not
  | constantly rocketing perfectly good content into the trash can;
  | it's essentially a "content-aware cache layer":
  | 
  | https://www.youtube.com/watch?v=XhNv1ikZNLs&list=PLqj39LCvnO...
 
  | simion314 wrote:
  | >you have to start from the beginning and write an API now.
  | 
  | You could refactor your code to share mostly everything . I
  | have no idea how this templates system work though so maybe you
  | need a different one.
  | 
  | so the API returns an array of users object as a json the html
  | side of things would have a render function that has as input
  | the same array of user objects. What you will probably lose
  | versus complex frameworks is magic stuff like 2 way data
  | bindings but from my experience those always caused issue, I
  | prefered the old react way of doing things, it was more
  | "functional style" and less magic under the hood and I
  | could(and used) JS and not a special template language with
  | special keywords to render stuff.
  | 
  | Amway my point is yu can reuse the API code for the html render
  | stuff too.
 
| bingohbangoh wrote:
| I'm a big fan of these setups but has anybody ever successfully
| used a minimal-JS setup for anything useful?
| 
| I mean, there's apps like Pinboard but React & Redux do handle a
| lot of complexity and most modern apps demand that complexity.
 
  | deniz-a wrote:
  | People have done plenty of useful things with htmx, just like
  | people did (and some continue to do) useful things with links &
  | forms.
  | 
  | Here's the example that's most convenient for me to pull up:
  | https://www.youtube.com/watch?v=zHoAwVcSLdE (via
  | https://www.commspace.co.za/)
  | 
  | > most modern apps demand that complexity.
  | 
  | Citation needed.
 
  | nnoitra wrote:
  | Whatever you can do with React you can do with pure JS.
 
  | infamia wrote:
  | Basecamp and Hey.com for starters.
 
| streamofdigits wrote:
| would it possible to have a browser _ship_ with htmx so that it
| is possible to have truly  "javascript optional"? (in principle
| this applies to any full js framework but I suppose it is natural
| in the htmx context)
| 
| are there any unsurmountable issues around security and the
| sandbox etc (not terribly familiar with browser internals)
 
  | deniz-a wrote:
  | Most of what htmx does is a direct extension of the browser's
  | capabilities. Some issues I can think of are
  | 
  | - maintaining the "accessible by default" nature of HTML
  | 
  | - swapping. htmx takes html from the server and uses one of
  | innerHTML, outerHTML and insertAdjacentHTML to put it into the
  | document, but it also does a whole lot more to avoid unexpected
  | behavior. This would all need to be specified and implemented
  | natively
 
| pjs_ wrote:
| HTMX really kicks ass, I simply love it.
 
| chrisfinazzo wrote:
| Smells like Turbo (and related frameworks) to me, which isn't a
| bad thing. From my brief use of CRA, I can see why many people
| are attracted to it, but the fact that a bunch of JS has to
| download before anything happens is never far from my mind.
| 
| In the meantime, I'll keep waiting until we get native HTML
| imports/includes - hopefully before the heat death of the
| Universe.
 
| Savageman wrote:
| It reminds me a bit of [MooTools
| Behavior](https://mootools.net/blog/2011/12/20/mootools-behavior)
| (from 2011!) where interactivity was created by adding tags to
| HTML, similar to the article!
 
| synergy20 wrote:
| If I use alpine.js why do I need htmx still? I would use either
| of them but not both. Using both seems making a supposed-to-be-
| simple approach immediately back to complicated-again-now-you-
| need-two-components.
| 
| alpine increases client side interactivity, it can also do ajax
| to talk with server, why do I still need htmx then?
| 
| On the other hand if I use htmx I will probably use its
| hyperscript for interactivity on the client side, to be
| 'consistent'.
| 
| Note both projects are trying to make frontend simpler, mixing
| them seems not to help that goal to me.
 
  | nop_slide wrote:
  | I don't think Alpine has any similar AJAX directives as HTMX.
 
  | deniz-a wrote:
  | The pattern is that you use htmx for anything it can do, then
  | use Alpine for things that shouldn't/can't require a server
  | round-trip (toggling sidebar, animations etc).
  | 
  | You can reimplement htmx functionality with Alpine, but htmx is
  | a lot better than `@click="fetch('/partial').then(res =>
  | res.text()).then(frag => $el.innerHTML = frag)"` all over the
  | place (with a slight variation in that one component that you
  | miss because of the noise).
  | 
  | Don't use _hyperscript just to be "'`consistent`'", use it
  | because you want to. Being agnostic and playing well with other
  | tools is a big thing for htmx. _hyperscript is lots of fun and
  | lets you write very readable code, but you also need to stomach
  | a 26mb bundle just to toggle some classes :/
  | 
  | (if anyone reading this can help us make it smaller, LMK)
 
    | recursivedoubts wrote:
    | _> 26mb_
    | 
    | ackshully, 21.2 _kB_ :
    | 
    | https://bundlephobia.com/package/hyperscript.org@0.9.0
    | 
    | Which compares pretty well w/ alpine, which comes in at
    | 21.7kB with its dependency:
    | 
    | https://bundlephobia.com/package/alpinejs@3.5.2 - 17kB
    | https://bundlephobia.com/package/@vue/reactivity@3.2.22 -
    | 4.7kB
    | 
    | :)
 
  | recursivedoubts wrote:
  | htmx is for syncing client side actions with the server
  | effectively within the hypermedia model
  | 
  | AlpineJS (and hyperscript) are better for purely front end
  | needs.
  | 
  | htmx and Alpine pair well together, as does htmx/jQuery,
  | htmx/VanillaJS or, if you are brave, htmx/hyperscript
 
| nawgz wrote:
| I take so much issue with HTMX being branded as "JavaScript
| optional". It's a project built for people who hate JS by people
| who hate JS, and as the resulting developer workflows aren't JS-
| based have managed to convince themselves they're not using JS.
| 
| It's totally false. Your HTMX app does not work for JS-disabled
| people any more than someone's React/Angular/Vue first-render-on-
| server app.
 
  | VWWHFSfQ wrote:
  | I think you misunderstand what HTMX is
 
    | nawgz wrote:
    | Explain it closely to me then. What is HTMX doing that
    | enables someone to write HTML attributes that make arbitrary
    | actions that update the DOM possible?
 
      | post-it wrote:
      | My understanding of HTMX is that the main draw is not
      | having to _write_ JS as a dev, not not having to _run_ JS
      | as a user.
 
        | hunterb123 wrote:
        | Optional JS is a term already for web pages that degrade
        | gracefully when JS is turned off.
        | 
        | It's a shady marketing technique to hijack that term when
        | it doesn't work that way.
 
        | VWWHFSfQ wrote:
        | it does work that way though
 
      | VWWHFSfQ wrote:
      | when there's no javascript those attributes do nothing and
      | your webpage acts like normal. ie, link clicks do a full
      | page load. so your website works with or without
      | javascript.
 
| colbyhub wrote:
| Another one to consider is https://www.django-unicorn.com if you
| want that LiveView feeling for Django.
| 
| For my latest project[1], I've opted for https://unpoly.com
| instead of Alipine+htmx as Unpoly allows me to write 100% server-
| side code and sprinkle some progressive enhancement where
| desirable. As a result, I can offer a no-JS experience (minus the
| Stripe Checkout) for those who may want/need it. Additionally, it
| forces me to focus solely on the server-side, and I write more
| idiomatic Django code as a result.
| 
| [1]: https://heraldsms.com
 
  | porker wrote:
  | I've been looking at these libraries and Unpoly looks the most
  | promising for my needs. HTMX looks good as well but Unpoly's
  | infinite layers feature [1] rather grabbed my attention :)
  | 
  | Stimulus is the one I can't get myself to like. Separate JS
  | controllers is clever but the DSL and general nature - it just
  | doesn't click with me.
  | 
  | [1] https://unpoly.com/up.layer
 
  | benbristow wrote:
  | https://www.django-unicorn.com/examples/count-characters
  | 
  | Sending an AJAX request every time you enter characters just to
  | count them. Ewwww.
 
    | alpha_squared wrote:
    | I guess that's the extreme end of no-js. Wanting to use
    | compute, but philosophically sticking-to-your-guns on where
    | that compute happens.
 
      | benbristow wrote:
      | Well it's still using JS to send the AJAX request, so in-
      | fact something along the lines of 'on text change, set some
      | element text to text.length' is a lot less JavaScript code
      | than 'on text change, format and POST an AJAX request and
      | then set the element text to a value within the response'.
 
        | RussianCow wrote:
        | The difference being that the code to send an Ajax
        | request an update the DOM based on the response is
        | already coded and already used in other places, whereas
        | updating the text length client-side would have to be
        | custom code. Not that I'm arguing one way or another, but
        | the reason it's done that way is to reuse the same set of
        | primitives for everything.
 
| sbussard wrote:
| I always have the fear that something I write will be too
| complicated for someone else. This has become particularly
| irksome when integrating OIDC into a single page app. It's gut
| wrenching to double check every random header for every domain it
| needs to serve, to set up SSL for localhost, to include the right
| headers on the fetch request, and maybe edit the /etc/hosts file
| to make it work. That process is a joy killer. The tools
| mentioned here can help stop that madness and bring joy back into
| development. So thank you! Please evangelize these ideas to
| browser standards committees and whoever will listen.
 
| polyrand wrote:
| After reading some HTMX criticism, there's one point people seem
| to miss. Making HTML your application interface does *not*
| prevent you from having a JSON (or something else) API. If
| anything, it probably forces you to split your functions better.
| e.g:                 def get_user_data(user_id: int) -> Dict
| (JSON-looking data):           ...            def
| render_user_view(user_id: int) -> HTML:           user_data =
| get_user_data(user_id)
| render_template("user_detail_view.html", context=user_data)
| 
| If you need the user data in a JSON API, nothing prevents you
| from exposing `get_user_data` as a JSON endpoint. You can also
| use WebViews in a mobile app.
| 
| People tend to overestimate the "interactivity" needs of their
| apps and underestimate what they can achieve by just swapping
| HTML. HTMX also lets you swap "Out of Band" [0]. This makes it
| easy to model more complex interactions (like "reactions"), for
| example, updating a counter somewhere else in the app when a form
| is submitted. Reactive frameworks can also become a Rube Goldberg
| machine if an app is not properly designed from the beginning.
| Then you start fighting rendering loops, build dependencies,
| components' side effects, etc.
| 
| Personally speaking, HTML-driven apps are not just about easy vs.
| hard development, it's also about your users [1]. Maybe a big
| React app runs fine on 8 CPU cores and 32 GB of RAM, but very
| often, your users just want to read some content, maybe submit a
| few forms, and leave. They may not want to download 2 MB of JS so
| that the page can render boxes with text, even more if your
| browser can already do that if you give it some HTML.
| 
| [0] https://htmx.org/attributes/hx-swap-oob/ [1]
| https://shkspr.mobi/blog/2021/01/the-unreasonable-effectiven...
 
  | abstract_put wrote:
  | Big +1 on all of this. I have terrible rural internet, and just
  | recently tried developing my first app with HTMX (wasn't aware
  | of Alpine.js), and _man_ is it fast. For city slickers with
  | their symmetrical gigabit connections it may be unnoticeable,
  | unfortunately. Not saying SPAs have to be bloated, it just
  | seems like most sites that turn into SPAs are bloated.
  | 
  | All that said, trying to push everything server-side if you've
  | been working in a heavy client takes some getting used to. In
  | my real life job I've seen feature flags shipped as an API so
  | the client queries whether a feature flag is enabled - this is
  | something that always struck me as silly, the server serving
  | the front end already knows if the feature flag is enabled.
  | While that might be justifiable in some cases, it is definitely
  | not so much in the on-prem-only product I worked on.
 
| nop_slide wrote:
| Can anyone describe the use cases between HTMX/Alpine and Unpoly
| JS? I see the 3 routinely mentioned, but I am unsure what
| coverage Unpoly has vs HTMX/Alpine.
| 
| https://unpoly.com/
 
| thih9 wrote:
| Is anyone here using either HTMX or Alpine.js (or both) in
| production? What are your thoughts, are you happy with how these
| work in practice?
 
  | jonathan-adly wrote:
  | I am using HTMX in production in two applications - it's sped
  | development considerably.
  | 
  | I completely stopped using React
 
  | sgt wrote:
  | Am using AlpineJS on a new production Django app. Works fine.
 
  | werdnapk wrote:
  | I use Alpine.js in a handful of my production apps and have had
  | no real issues when Vue, etc is overkill, except that when
  | dealing with a lot of data, I found Alpine.js to be just way
  | too slow with rendering. Swapping out Alpine.js for Vue fixed
  | my problem. I likely was pushing Alpine.js beyond it's intent
  | of "small" snippets to enhance a page.
 
| strogonoff wrote:
| Downside of most HTMX examples (such as the form in TFA) seems to
| be lack of graceful degradation with non-JS-enabled user agents.
| 
| But then, the rest of the page is server-generated (taking care
| of SEO), and handling interactivity without JS may not be a
| priority for most sites nowadays.
 
  | recursivedoubts wrote:
  | progressive enhancement is possible with htmx (e.g. the hx-
  | boost attribute is p/e friendly) but often requires thought by
  | the programmer
  | 
  | for example, the active search example can be made p/e'd by
  | wrapping the input with a form that submits to the same page:
  | 
  | https://htmx.org/examples/active-search/
  | 
  | but it requires work by the end developer
  | 
  | the idea here is to be pragmatic: obviously some people care
  | deeply about p/e and are unwilling to sacrifice it for more
  | advanced U/X, but others are willing to do so, so let's make it
  | possible for both camps to improve their sites with the tool
 
| beebeepka wrote:
| I think it's great people who passionately dislike JavaScript
| have such powerful options.
| 
| Personally, I am not buying the whole "you can do anything this
| way" because it seems to me the main driver, implied or plainly
| stated, is always the "and no js!" part.
| 
| I get it, though. We are all capable of going to great lengths to
| prove a point. Having more viable options is great.
 
  | joelbluminator wrote:
  | It's not necessarily about disliking JavaScript. I can see Node
  | people using this as well, why wouldn't they? Not everyone
  | wants or needs to double their app code by building both a
  | server app and a SPA. I might be exaggerating by "double" but
  | it's for sure a major increase of code. Github is doing fine
  | without a SPA last I heard.
 
| 1270018080 wrote:
| This honestly sounds like a miserable tech stack.
 
| Wronnay wrote:
| https://archive.md/9YAJm
 
| ksec wrote:
| Sorry if this is off topic, I remember reading a proposal of
| including something similar to Alpine.js / HTMX within the HTML5
| spec.
| 
| But I lost the page. And the proposal itself doesn't mention
| Alpine.js or HTMX so no keyword bring it up in Google. I am
| wondering if anyone have any idea.
 
  | technobabbler wrote:
  | Web components? https://developer.mozilla.org/en-
  | US/docs/Web/Web_Components
 
  | deniz-a wrote:
  | This might be it https://discourse.wicg.io/t/extending-html-as-
  | a-hypermedia/5...
 
| resoluteteeth wrote:
| One major downside to HTMX is that as soon as there is any state
| you have to keep track of, you're teleported back to the late 90s
| or early 2000s where you have to keep track of all your state in
| hidden form fields, and you're extremely constrained in how you
| update pages.
| 
| IMO, it's annoying enough that it's probably not worth it unless
| you're doing something trivial. If you want to render html on the
| server you can still do that, but in many cases it is easier to
| just use custom javascript and maybe even receive the rendered
| html as json to simply updating pages rather than use htmx.
 
  | nlitened wrote:
  | Yeah, those damned early 2000s when back/forward buttons worked
  | perfectly and we didn't lose the entire rich client state upon
  | page refresh or wireless internet hiccup. Thank god we have a
  | lot of JavaScript libraries and ambitious programmers to save
  | us from those trivial things :)
 
    | kiawe_fire wrote:
    | But those were actual problems back then, and they were
    | solved only through significant engineering work to hide
    | them, each of which had their own problems.
    | 
    | Frameworks like .Net WebForms were created to abstract and
    | hide a lot of this from developers, with things like long
    | encoded strings of "view state" that would be re-posted on
    | each request, by serializing things to the URL, or by saving
    | them to Cookie-backed sessions.
    | 
    | But each of these has issues, from privacy concerns using the
    | URL, to security concerns with the "view state", to
    | concurrency and integrity concerns with sessions.
    | 
    | IMO, the biggest reasons these didn't stand out as huge
    | problems in the early 2000's was because:
    | 
    | (a) we didn't use the web like we do today, and our
    | expectations were very different in how things would work if
    | we, for example, added an item to a shopping cart
    | 
    | (b) most heavily interactive / app-like things that more
    | closely work "the way we expect" today, were either still
    | done as desktop apps (like business software) or were
    | implemented as Java applets, Flash, or something else of the
    | sort
    | 
    | (c) in the rare cases that neither (a) nor (b) applied, it
    | was because some very good engineers put in a lot of work to
    | make it work that way.
 
  | jon1628492 wrote:
  | I'm new to htmx and alpine, but isn't alpine's global store
  | what you'd want in this case? https://alpinejs.dev/magics/store
 
| austincheney wrote:
| I'm not sure I understand the motivation to avoid JavaScript. I
| completely understand not wanting 400mb of SPA/NPM nonsense, but
| otherwise what problem does avoiding JS solve in a webpage?
| 
| * Is it because JavaScript is too hard to learn or too unpleasant
| to write?
| 
| * Is it because training people to write JavaScript is too much
| effort?
| 
| * Is it due to a lack of trust in your fellow developers?
| 
| * Is it due to challenges in planning or forming architecture?
| 
| * Something else?
 
| jonatron wrote:
| Not sure about the snippet:                   // when the DOM is
| loaded         document.addEventListener('DOMContentLoaded', ()
| => {           // find every element with the class "close"
| (document.querySelectorAll('.close') || []).forEach((closeButton)
| => {             const parent = closeButton.parentNode;
| // and add a "click" event listener
| closeButton.addEventListener('click', () => {               //
| that removes the button's parent from the DOM
| parent.parentNode.removeChild(parent);             });
| });         });
| 
| It'd be clearer without useless comments and useless extra code:
| document.addEventListener('DOMContentLoaded', () => {
| document.querySelectorAll('.close').forEach((closeButton) => {
| closeButton.addEventListener('click', (event) => {
| event.target.parentNode.remove()                 })
| });         });
 
| robertoandred wrote:
| Don't use a framework, use three!
| 
| This sounds like a lot of effort just to brag about how you
| avoided whatever piece of tech we're considering to be evil this
| month.
 
  | ozzythecat wrote:
  | I did web development work in the early 2000s (PHP, MySQL) and
  | briefly in 2013-2014. In the past few years, I explored a
  | recent version of Angular, React, and some other framework.
  | 
  | The tooling seemed really nice at first, but I was actually
  | shocked at the number of dependencies and just the overall
  | complexity with all the layers of abstractions.
  | 
  | Fundamentally, these are still websites. I honestly see this as
  | people getting bored, inventing new things to deal with their
  | boredom, and the rest of the industry follows.
  | 
  | Meanwhile, the services I was writing in Java like 10 years ago
  | haven't really changed. We agreed Spring sucked and moved on.
  | At a FANG where I work, we use Java and Kotlin. A lot of my
  | data crunching jobs are in Scala. We did start using Rust for
  | shared libraries deployed on mobile operating systems...
  | because the entire team preferred it over C++.
  | 
  | But I come back to web development and there's always a new
  | flavor of solving the same problem. /shrug
 
    | BoumTAC wrote:
    | I do not understand it too.
    | 
    | The cost due to the complexity is at least 10 times more.
    | 
    | It feels strange to me that nobody in the hierarchy consider
    | it.
    | 
    | I do understand that developer like to play with new
    | technology and don't care about the cost as long as they can
    | play with it and get paid but the hierarchy must have seen
    | the millions dollars lost. Why did they do not say something
    | about it ?
 
  | recursivedoubts wrote:
  | alpine has one dependency and htmx is dependency-free, and both
  | are very small[1][2]
  | 
  | so it is a very lightweight combination on top of plain-ol'
  | HTML
  | 
  | [1] - https://bundlephobia.com/package/alpinejs@3.5.2 [2] -
  | https://bundlephobia.com/package/htmx.org@1.6.1
 
  | ttymck wrote:
  | This is unfair. HTMX and Alpine could hardly be considered
  | frameworks.
  | 
  | React, by comparison, is absolutely massive. It's complicated.
  | It requires compilation, and often a complex build
  | configuration. You still need a backend server, so it won't
  | obviate Django.
  | 
  | Your comment speaks to a larger debate, but it's a rather
  | disappointing contribution.
 
| jonathan-adly wrote:
| For people who want to see more advanced examples/tutorials built
| using Django and htmx- you can see a bunch here: https://htmx-
| django.com/
| 
| Anything that can be done with React/Vue can be done with htmx in
| a more "Django-way"- it's an amazing library that allows for
| complete web applications without the complexity of the JS
| ecosystem
 
  | robertoandred wrote:
  | All I see there is someone using s as fake s.
 
    | jonathan-adly wrote:
    | cool, right? You don't have to do this with htmx, but you can
    | if you want too and I did because I wanted too :)
    | 
    | Keep an open mind and continue reading on
 
      | robertoandred wrote:
      | Fake links break normal link behavior. Accessibility
      | issues, opening links in new tabs, etc.
 
| reidjs wrote:
| Can this stack easily handle 2-way data bindings on the frontend?
| For example, when you update a text input, the title of the text
| input changes?
 
  | mejutoco wrote:
  | Yes. You give ids to elements and the html indicates which id
  | to replace with which content. You can even replace ids in
  | other sections (might get complex quickly, but it works).
  | 
  | https://htmx.org/attributes/hx-swap-oob/
  | 
  | Source: I used this to implement my
  | https://fromzerotofullstack.com website.
 
  | czue wrote:
  | Alpine should be able to do this by itself.
 
  | recursivedoubts wrote:
  | purely front end use cases like this would be handled by alpine
  | 
  | syncing state with the back end would be handled by htmx
 
| fareesh wrote:
| A suggestion for folks writing articles like this - sell me the
| advanced but typical example. I want to see an image input which
| is then previewed and then uploaded asynchronously with a loading
| bar and error states.
 
___________________________________________________________________
(page generated 2021-11-23 23:00 UTC)