8 ms·
The Hypermedia-Driven Application (HDA) Architecture
- wtatum 5y agoI find this approach really interesting and have spent some time browsing HTMX docs in the past but there's one thing I feel like I'm missing. Most existing server-side rendering frameworks / templating engines I'm familiar with tend to assume they're rending a complete HTML document rather than just an HTML "fragment" needed by something like HTMX to do dynamic page updates. What does the server-side look like with an HDA stack look like in practice? From TFA, they use the example POST /search where a snippet of HTML is returned from the /search call and is injected into the page. What would the backend look like? Presumably you still want HTML templating and component-based design instead of regressing to hand building the response, but what frameworks/packages/utilities exist in that space that don't assume they are rendering a complete page? In particular, "whole app" frameworks like NextJS or SvelteKit are automatically mapping URLs onto a root component that is automatically decorated with all the chrome needed to make it a complete page. Is the approach to just overload those root page components and take all the chrome away to get a partial document in the response?
- recursivedoubts 5y agoa few different ways to skin this cat: htmx includes headers, `HX-Request` which will be true if the request is an htmx request, and `HX-Target` that will be the id of the target element, if any, that allow you to modify your response as needed on the server side. This is very common: you have a single URL that satisfies both the htmx and non-htmx request (e.g. /search) and in the htmx case, you don't render the surrounding layout, but in the "normal" case you do. If a server side option isn't available or is inconvenient, you can instead use the client-side attribute `hx-select` to select a bit of the HTML from the response for inclusion in the DOM.
- Induane 5y agoWith Django and flask and everything else I've ever used, there is a templating system at play. I use the request headers to determine if I should return a whole page or a portion of a page. For example I have a form that's something like form_partial.html: partial form template: <form hx-post="{{ request.path }}" hx-swap="outerHTML" hx-encoding='multipart/form-data' hx-target="this"> {% csrftoken %} ... some other form stuff from django </form> form.html: A normal page that includes that form: {% extends core.html %} {% include partial_form.html %} Then in the controller code I choose whether to render the entire page (form.html) or a partial page (partial_form.html) depending on the presence of the htmx headers. So the full load might look something like: 1. Visit mysite/coolform 2. Server renders whole page 3. Browser submits form data 4. If the form is invalid, return only the partial form, swapping the forms html and if the form IS valid, return a redirect Another cool thing (checkout hx-boost ) about htmx is that even if you return a whole page you can actually still avoid a full page reload and only swap out the body component. So even though you're returning a few extra bytes the site isn't re-executing the entire JavaScript bundle every time you navigate to a new page.
- no_wizard 5y agoOther than returning html responses and the proprietary hyper script format how is this difference from something like API Platform[0]? The unspoken claim is you can’t do the same thing with an SPA yet that shows you can. [0]: https://api-platform.com/ https://api-platform.com/
- ledgerdev 5y agoThere is absolutely nothing proprietary about the format. It's just plain html and vanillajs works fine if that's what you'd like to use. Hyperscript is no different than any other open source compile to js lang.
- no_wizard 5y agoCan't edit this apparently, so this is what I really mean: I understand the appeal of what they are laying out here. I'm just wondering why the htmx approach has more benefits over the HATEOAS approach of something like API Platform that I linked to, which doesn't have any opinion on something being an MPA, SPA, or something in between Also to clarify: I mean proprietary as in proprietary to htmx, this is a poor word choice on my part, no different to how Vue has its Single File Components which are "proprietary" to Vue. I'm specifically trying to understand the advantage of something that ties your APIs to markup rather than using an interchange format such as JSON, as such when building scalable systems it not uncommon to need some form of interchange functionality. Even at a smallish company I work for we need to make sure it is digestible on web, and mobile applications. I'm just trying to apply some intellectual rigor to the model, as something I do think about is scaling, not say, Instagram Scale, even just something like a company with a 100+ million ARR may bubble these concerns
- southerntofu 5y ago> why the htmx approach has more benefits over the HATEOAS approach of something like API Platform that I linked to My understanding is that HTMX is based on the HATEOAS approach: https://htmx.org/essays/hateoas/ https://htmx.org/essays/hateoas/ About API Platform you linked to, the homepage is not very clear (full of buzzwords but little info) but it appears to be a Backend+Frontend framework/distro based on PHP+JavaScript. Compared to that, HTMX is an HTML extension (just additional fields in the markup) which any backend/frontend can implement: even web browsers which don't have a JS runtime could implement HTMX and that's pretty cool. > I mean proprietary as in proprietary to htmx I believe HTMX is free software and i don't see a reason the specification can't be implemented by other projects. It's therefore not proprietary in my definition of the word. > something that ties your APIs to markup rather than using an interchange format such as JSON HTML/XML isn't that different from JSON. Just like your markup can evolve with your data structures and use-cases, so can your JSON. If you want interoperability, you should probably be using XML/JSON schemas and API versioning.
- throw_m239339 5y agoContext OP? What does that thing do that hasn't been done since the inception of Javascript and the DOM in the browser?
- murkt 5y agoThis thing preserves your sanity!
- throw_m239339 5y agoI'm waiting for anyone to demonstrate me how this method isn't 3 step backward in 2022.
- murkt 5y agoIt is three step backwards. And one step to the side. Which is what I needed, and many others too.
- throw_m239339 5y agoOk, you mean this thing isn't worth my attention as a front-end developer? Carry on.
- murkt 5y agoYes, this is not for a front-end developer, this is for all the other people who don’t want to be front-end developers and don’t want to spend months every year to keep up with JS churn. Since we began using this approach, we can be full-stack developers again. One person can easily implement both parts, which is so much faster.
- recursivedoubts 5y ago:) I think it's worth at least taking a look at the core idea is to use hypermedia, rather than an RPC-style architecture, and that is, at the least, an interesting alternative approach to consider when creating front end code
- jonathan-adly 5y agoI have htmx running in production with a Django backend. It’s honestly like having a cheat code for web development. Simple, scalable code that does the job perfectly!
- ledgerdev 5y agoThis exactly. I just started a new project with htmx this past week, and it absolutely amazing. It brings the magic of the web back we first experienced moving away from 90's windows programs. I'm a firm believer that react/angular are grossly mis-used for information based apps and websites, they should really only be used for rich client apps like chat, music players, image editors, offline, etc.
- murkt 5y agoImage editors or offline stuff - sure. But even Chats and music players - there is not much going on in the browser. I’m using this approach (other library, though, which is called twinspark.js) for year and a half.
- arbenpurben 5y agoWe have htmx & hyperscript running in production powering a fintech saas. It is fantastic in the way that all really good technology is: it just does what it's supposed to do so simply and efficiently that you kinda forget it's there, so you end up spending time where it counts (UX and business logic), instead of fighting finicky frameworks. No-one in the real world cares about the supposedly great framework powering a web app - they just care that the app is fast, easy to use and saves them time and money.
- sdze 5y agoI love your pragmatism.
- arbenpurben 5y agoThanks!
- melony 5y agoLink to the SaaS?
- transfire 5y agoOn one hand, I like the simplicity of it. On the other, I fear it’s a backward move. We loose access to data as, well, data. If you get data from the backend it can be rendered in different ways by the front end. You loose that flexibility with HDA.
- southerntofu 5y agoIt appears HTMX supports non-HTML APIs. The json-enc extension encodes <form> fields as JSON, and client-side-templates allows templating from JSON (and others) API responses. Now, take my words with a grain of salt because i'm unaware of the details, but i don't see a reason HTMX couldn't support XML with proper schemas which would be great: - for structured/typed data and ensuring proper API protocol negotiation between client and server - for data structures closer to the DOM model (which has both fields and children for most elements, while a JSON key can point to a list or an object, not both) - for serialization formats the browser knows about and is optimized for - for interoperability with other systems/protocols based on XML schemas, such as XMPP Data can be served in many forms. Your API could be a DNS key-value server, or a JSON endpoint, or a HTML page. Just because most people don't structure their HTML semantically doesn't mean it can't (or shouldn't) be done, which means you don't loose "access to data as data". On the contrary, designing your API as semantic/structured HTML empowers users to parse/script your website to better suit their needs, whether that's for accessibility purposes or for developing 3rd party clients. Something that's become almost impossible in the age of SPAs and CAPTCHAs imposing the developer's will on my browsing experience.
- sdze 5y agoYou lose nothing. You just tell the backend by accept header what you expect it to return.
- recursivedoubts 5y agoI recommend splitting your hypermedia and your data APIs up, because they end up having very different usage patterns: https://htmx.org/essays/splitting-your-apis/ https://htmx.org/essays/splitting-your-apis/ https://htmx.org/essays/hypermedia-apis-vs-data-apis/ https://htmx.org/essays/hypermedia-apis-vs-data-apis/
- jrochkind1 5y agoCompare to turbo/stimulus from Rails world; I would put the approach in the same basic category, that being: Custom HTML attributes triggering standardized behaviors, with HTML sent over the wire for partial page updates. I wonder what other platforms are going on right now in this same category -- anyone have more examples? And in general how much "mind share" (or really development-share) it's getting.
- throwamon 5y agoNot exactly in the same category as htmx, but... I'm not super familiar with this but what I can say is that many of these things were inspired by Phoenix LiveView, and as far as I know LiveView is still the one that works best. Here's a list of LiveView-inspired projects (including StimulusReflex): https://github.com/dbohdan/liveviews https://github.com/dbohdan/liveviews
- southerntofu 5y agoI don't know much about this field, but as a WWW user i would be happy if such features became part of the HTML spec so that browsers can implement them natively without becoming an entire javascript-based operating system with all the problems involved by this endeavor.
- nvegater 5y agoSpecifically this html attribute in the delete button: `hx-delete="/contact/1"`. where the id of that contact is 1 and it is hardcoded as a string.[0] How do I dynamically generate a list of deletable items? In react would be something like (simplified obviously) `contacts.map(c => <button onClick={apiDelete(c.id)}/>`. I dont understand how could I generate dynamic lists without hardcoding Ids... is that a case where I would need to use normal vanilla js ? 0: https://htmx.org/examples/delete-row/ https://htmx.org/examples/delete-row/
- murkt 5y agoJust generate these ids on the server. For example, when I render a new field for which I need a delete button, I send numbers of other fields along with them, and server renders a new field for me with a new id.
- nvegater 5y agoThanks for responding. If I understand correctly, then I would need a server like nodejs or django generating and sending the "index.htmx" to the browser and then responding to users interactions by embedding the data from the server inside of the htmx files, correct?
- murkt 5y agoSounds about right. It’s the good old server templates (we use Jinja), and for interactivity I have additional attributes here and there, and sometimes additional endpoints. It’s miles better than full-fledged JS SPA. I’ve had React+GraphQL app that I’m migrating piece by piece when we need a new feature, and it’s a few times faster to do and easier to understand.
- recursivedoubts 5y agoYou generate all links on the server side, using Hypermedia As The Application of Engine State (HATEOAS): https://htmx.org/essays/hateoas/ https://htmx.org/essays/hateoas/
- mkl95 5y agoI have mixed feelings about htmx. It's wonderful, but it's going to take years for companies in my area to know it exists. I will totally pick it for some personal project though.
- recursivedoubts 5y agohttps://www.youtube.com/watch?v=tYzMYcUty6s https://www.youtube.com/watch?v=tYzMYcUty6s
- arbenpurben 5y agoBe the change you want to see in the world :)
- shrimpx 5y agoThe core assumption of stacks like htmx is that you don't need fine-grained client-side interactions implemented in custom Javascript; that when you need the UI to change, it's ok to go through the server. An example edge case where this fails completely is a canvas-based interactive game, where you (a) cannot "ask the server for html" in order to update your game UI and (b) going through the server for every UI update is unacceptable for performance. That said, people are realizing that in a very large percentage of practical cases (i.e., CRUD apps), you do not need the high fidelity of javascript and you can skip a lot of the related complexity by using simplified stacks. The big fail would be if you use htmx at first but over time you end up grafting a bunch of custom JS on top anyway, and your backend is a complicated Jinja mess, which is what made old school Rails/Django projects total messes and caused people turn to SPAs + JSON pumps. It probably takes some discipline to stick with pure htmx and push back on requests to graft random crap on top.
- midrus 5y agoYou still can write client side only JavaSCript with Unpoly compilers, alpine.js, and probably htmx also has a way to add custom javascript without making jquery spaghetti. A tool like this that rely on server rendering (or livewire, hotwire, etc) is a perfect replacement for when your user interaction will need to reach to the server anyway (to save data or fetch something, etc). For example, you're not forced to go back to the server to display a modal. You can have it already rendered on beforehand and when clicking a given button just toggle its visibility. Or if you want to mark a todo item as "done" you can just apply the "done" styles with alpine.js or similar and make an async call to the backend that will persist the state, etc. Going full "SPA" just because this is less ideal than state based react, etc does not compensate the overhead of everything else involved in any web application (SEO support, translations, security, authentication, etc) which are incredibly complicated to get right with SPAs.
- recursivedoubts 5y agoYes. Like any application architecture, the Hypermedia Driven Application architecture has strengths and weaknesses. In the case you outline, a canvas-based application, a hypermedia driven application is not going to be a good choice. However, that being said, it may be a good choice for parts of your application (e.g. the settings page.) Thankfully many SPA libraries are now embedable within an broader application, so you can use that approach when it fits best, and other, simpler approaches in other parts of your application.
- rchaves 5y agoapparently I’ve been doing a lot of HDA, by just placing inline javascript on my html pages, specially where first time to render is essential and interaction not so heavy I thought it was just laziness from my side of not wanting to set up the whole react scene Nice to have a name for it