Merge branch 'master' into dev

This commit is contained in:
Carson Gross 2023-07-14 13:50:25 -06:00
commit 4e97877047
14 changed files with 319 additions and 17 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
_site
test/scratch/scratch.html
.DS_Store
.vscode

View File

@ -157,7 +157,7 @@ This extension adds support for Server Sent Events to htmx. See /www/extensions
};
source.onopen = function (evt) {
api.triggerEvent(elt, "htmx::sseOpen", {source: source});
api.triggerEvent(elt, "htmx:sseOpen", {source: source});
}
// Add message handlers for every `sse-swap` attribute

View File

@ -8,7 +8,7 @@ insert_anchor_links = "left"
</div>
<div style="border: 1px solid lightgrey; margin:24px;padding:12px;border-radius: 8px; background-color: whitesmoke; filter: drop-shadow(3px 3px darkgray)">
<b>NEWS:</b> We are excited to announce that htmx has been accepted into the first class of the <a href="https://accelerator.github.com/">Github Open Source Accelerator!</a>
<b>NEWS:</b> We are excited to <a href="/posts/2023-06-06-htmx-github-accelerator/">announce</a> that htmx has been accepted into the first class of the <a href="https://accelerator.github.com/">Github Open Source Accelerator!</a>
</div>
<h2>introduction</h2>

View File

@ -13,7 +13,7 @@ the HTML into the DOM using a swap strategy:
This example will cause the `button` to issue a `DELETE` to `/account` and swap the returned HTML into
the `innerHTML` of the `body`.
## Notes
* `hx-delete` is not inherited
@ -21,3 +21,4 @@ This example will cause the `button` to issue a `DELETE` to `/account` and swap
* You can control the swap strategy by using the [hx-swap](@/attributes/hx-swap.md) attribute
* You can control what event triggers the request with the [hx-trigger](@/attributes/hx-trigger.md) attribute
* You can control the data submitted with the request in various ways, documented here: [Parameters](@/docs.md#parameters)
* To remove the element following a successful `DELETE`, return a `200` status code with an empty body; if the server responds with a `204`, no swap takes place, documented here: [Requests & Responses](@/docs.md#requests)

View File

@ -26,4 +26,4 @@ in the response and swap it in for div in the DOM with the same ID.
## Notes
* `hx-select` is inherited and can be placed on a parent element
* `hx-select-oob` is inherited and can be placed on a parent element

View File

@ -34,7 +34,7 @@ The `hx-swap` attributes supports modifiers for changing the behavior of the swa
#### Transition: `transition`
If you want to use the new (View Transitions)[https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API] API
If you want to use the new [View Transitions](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) API
when a swap occurs, you can use the `transition:true` option for your swap. You can also enable this feature globally by
setting the `htmx.config.globalViewTransitions` config setting to `true`.

View File

@ -0,0 +1,159 @@
+++
title = "10 Tips For Building SSR/HDA applications"
date = 2022-06-13
updated = 2023-06-13
[taxonomies]
tag = ["posts"]
+++
Building web applications using traditional Server-Side Rendering (SSR) or, saying the same thing another way, building
[Hypermedia-Driven Applications](@/essays/hypermedia-driven-applications.md) (HDAs) requires a mindset shift when
compared with building web applications with Single Page Application frameworks like React.
If you come at this style of development with an SPA-engineering hat on, you are likely to be frustrated and miss out
on many advantages of this particular architectual choice.
Here are 10 tip to help you make the mental shift smoothly, taking advantage of the strengths of this approach and
minimizing the weaknesses of it:
### Tip 1: Maximize Your Server-Side Strengths
A big advantage of the hypermedia-driven approach is that it makes the server-side environment far more important when
building your web application. Rather than simply producing JSON, your back end is an integral component in the user
experience of your web application.
Because of this, it makes sense to look deeply into the functionality available there. Many older web frameworks have
incredibly deep functionality available around producing HTML. Features like
[server-side caching](https://guides.rubyonrails.org/caching_with_rails.html) can make the difference between an incredibly
snappy web application and a sluggish user experience.
Take time to learn all the tools available to you.
A good rule of thumb is to shoot to have responses in your application take less than 100ms to complete, and mature
server side frameworks have tools to help make this happen.
### Tip 2: Factor Your Application On The Server
Server-side environments often have extremely mature mechanisms for factoring (or organizing) your code properly. The
[Model/View/Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) pattern is well-developed in
most environments, and tools like modules, packages, etc. provide an excellent way to organize your code.
Whereas SPAs user interfaces are typically organized via _components_, hypermedia-driven applications are typically
organized via _template inclusion_, where the server-side templates are broken up according to the HTML-rendering needs
of the application, and then included in one another as needed. This tends to lead to fewer, chunkier files than you
would find in a component-based application.
Another technology to look for are [Template Fragments](@/essays/template-fragments.md), which allow you to render only
part of a template file. This can reduce even further the number of template files required for your server-side
application.
### Tip 3: Specialize Your API End Points
Unlike a [JSON API](@/essays/hypermedia-apis-vs-data-apis.md), the hypermedia API you produce for your hypermedia-driven
application _should_ feature end-points specialized for your particular application's UI needs.
Because hypermedia APIs are [not designed to be consumed by general-purpose clients](@/essays/hypermedia-clients.md) you
can set aside the pressure to keep them generalized and produce the content specifically needed for your application.
Your end-points should be optimized to support your particular applications UI/UX needs, not for a general-purpose
data-access model for your domain model.
### Tip 4: Aggressively Refactor Your API End Points
A related tip is that, when you have a hypermedia-based API, you can aggressively refactor your API in a way that is
heavily discouraged when writing JSON API-based SPAs. Because hypermedia-based applications use [Hypermedia As The Engine
Of Application State](@/essays/hateoas.md), you are able and, in fact, encouraged, to change the shape of them as your
application developers and as use cases change.
A great strength of the hypermedia approach is that you can completely rework your API to adapt to new needs over time
without needing to version the API or even document it.
### Tip 5: Take Advantage of Direct Access To The Data Store
When an application is built using the SPA approach, the data store typically lives behind a JSON API. This level of
indirection often prevents front end developers from being able to take full advantage of the tools available in the
data store. GraphQL can help address this issue, but comes with [security-related issues](https://intercoolerjs.org/2016/02/17/api-churn-vs-security.html)
that do not appear to be well understood by many developers.
When you produce your HTML on the server side, on the other hand, the developer creating that HTML can have full access
to the data store and take advantage of, for example, [joins](https://www.sqltutorial.org/sql-left-join/) and
[aggregation functions](https://www.sqltutorial.org/sql-aggregate-functions/) in SQL stores.
This puts far more expressive power directly in the hands of the developer producing the HTML. Because your hypermedia
API can be structured around your UI needs, you can tune each endpoint to issue as few data store requests as possible.
A good rule of thumb is that every request should shoot to have three or fewer data-store accesses.
### Tip 6: Avoid Modals
[Modal windows](https://en.wikipedia.org/wiki/Modal_window) have become popular, almost standard, in many web applications
today.
Unfortunately, [modal windows do not play well with much of the infrastructure of the web](https://youdontneedamodalwindow.dev/)
and introduce client-side state that can be difficult (though not impossible) to integrate cleanly with the hypermedia-based
approach.
Consider using alternatives such as [inline editing](https://htmx.org/examples/click-to-edit/), rather than modals.
### Tip 7: Accept "Good Enough" UX
A problem many SPA developers face when coming to the HDA approach is that they look at their current SPA application and
imagine implementing it _exactly_ using hypermedia. While htmx and other hypermedia-oriented libraries significantly
close the interactivity gap between hypermedia-based applications and SPAs, that gap still exists.
As Roy Fielding [said](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5) with respect
to the web's REST-ful network architecture:
> The trade-off, though, is that a uniform interface degrades efficiency, since information is transferred in a
> standardized form rather than one which is specific to an application's needs.
Accepting a slightly less efficient and interactive solution to a particular UX can save you a tremendous amount of
[complexity](@/essays/complexity-budget.md) when building a web application.
Do not let the perfect be the enemy of the good.
### Tip 8: When Necessary, Create "Islands of Interactivity"
At some point in your web application, there may come a point where the hypermedia approach, on its own, just doesn't
cut it.
A good example of this is re-ordering a list of things. This can be done in "pure" hypermedia by clicking up and down
arrows or having order # drop-downs next to items. (I am ashamed to admit I have built both of these!)
But this experience stinks compared to what people are used to: drag-and-drop.
In cases like this, it is perfectly fine to use a front-end heavy approach as an "Island of Interactivity".
Consider the [SortableJS](@/examples/sortable.md) example. Here you have a sophisticated area of interactivity that allows for
drag-and-drop, and that integrates with htmx and the broader hypermedia-driven application via events.
This is an excellent way to encapsulate richer UX within an HDA.
### Tip 9: Don't Be Afraid To Script!
Scripting is [explicitly a part of the web architecture](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_7)
and developers adopting the hypermedia approach shouldn't be afraid to use it. Of course there is scripting and then
there is scripting.
As much as possible, you should try to use the [hypermedia-friendly scripting](@/essays/hypermedia-friendly-scripting.md)
approach, retaining hypermedia-exchanges as the primary mechanism for communicating system state changes with the
server.
Inline-style scripting, as enabled by [alpine.js](https://alpinejs.dev/) & [hyperscript](https://hyperscript.org) for example,
is worth exploring as well, as it refocuses your scripting on the hypermedia (HTML) itself and imposes an aesthetic
constraint on just how much code you can write.
### Tip 10: Be Pragmatic
Finally, do not be dogmatic about using hypermedia. At the end of the day, it is just another technology with its own
[strengths & weaknesses](@/essays/when-to-use-hypermedia.md). If a particular part of an app, or if an entire app,
demands something more interactive than what hypermedia can deliver, then go with a technology that can.
Just be familiar with [what hypermedia can do](@/examples/_index.md), so you can make that decision as an informed
developer.
## Conclusion
Hopefully these tips help you adopt hypermedia and server-side rendering as a tool more effectively and smoothly. It
isn't a perfect client-server architecture, and it involves explicit tradeoffs, but it can be extremely effective for
many web applications (far more than most web developers today suspect) and provides a much simpler overall development
experience in those cases.

View File

@ -4,6 +4,7 @@ insert_anchor_links = "left"
+++
* [Hypermedia Friendly Scripting](@/essays/hypermedia-friendly-scripting.md)
* [Hypermedia On Whatever you'd Like (HOWL)](@/essays/hypermedia-on-whatever-youd-like.md)
* [When To Use Hypermedia?](@/essays/when-to-use-hypermedia.md)
* [A Real World React to htmx Port](@/essays/a-real-world-react-to-htmx-port.md)
* [How Did REST Come To Mean The Opposite of REST?](@/essays/how-did-rest-come-to-mean-the-opposite-of-rest.md)
@ -18,7 +19,9 @@ insert_anchor_links = "left"
* [Two Approaches To Decoupling](@/essays/two-approaches-to-decoupling.md)
* [A Response To "Have SPAs Ruined The Web"](@/essays/a-response-to-rich-harris.md)
* [Template Fragments](@/essays/template-fragments.md)
* [10 Tips For Building SSR/HDA applications](@/essays/10-tips-for-SSR-HDA-apps.md)
* [View Transitions](@/essays/view-transitions.md)
* [REST Copypasta](@/essays/rest-copypasta.md)
### Older [intercooler.js](https://intercoolerjs.org) Essays

View File

@ -189,9 +189,9 @@ the resource it is working with that must be derived from some other source beyo
This API is, in spirit, nearly the opposite of REST.
Let's call this style of API RPC-EST.
Let's call this style of API "RESTless".
## How "REST" came to mean "RPC-EST"
## How "REST" came to mean "RESTless"
Now, how on earth did we get to a spot where APIs that are _obviously_ not RESTful are called RESTful by 99.9% of the
industry?
@ -285,7 +285,7 @@ That's the one sentence version of how we got here.
### The REST Wars
Despite the JSON API world never consistently achieving truly RESTful APIs, there were plenty of fights over whether
or not the RPC-EST APIs being created were "RESTful": arguments over URL layouts, over which HTTP verb was
or not the RESTless APIs being created were "RESTful": arguments over URL layouts, over which HTTP verb was
appropriate for a given action, flame wars about media types, and so forth.
I was young at the time, and the whole thing struck me as opaque, puritanical and alienating, so I pretty much gave up
@ -319,7 +319,7 @@ Eventually most people got tired of trying to add hypermedia controls to JSON AP
worked well in certain specialized situations (e.g. paging), they never achieved the broad, obvious utility
that REST found in the general, human-oriented internet. [(I have a theory why that is.)](https://intercoolerjs.org/2016/05/08/hatoeas-is-for-humans.html)
Things settled into this intermediate RPC-EST state, with REST slowly cementing its meaning as a JSON API at Level 1
Things settled into this intermediate RESTless state, with REST slowly cementing its meaning as a JSON API at Level 1
or 2 of the RMM. But there was always the possibility that we would break through to Level 3 and the glory of REST.
Then Single Page Applications (SPAs) hit.
@ -339,7 +339,7 @@ Even though they were doing things like publishing swagger documentation for the
churn of their RESTful APIs](https://www.infoq.com/articles/no-more-mvc-frameworks/), things that wouldn't be occuring
if they were actually creating RESTful APIs.
Finally, in the late 2010s, people had had enough: REST, even in its RPC-EST form, simply wasn't keep up with the needs
Finally, in the late 2010s, people had had enough: REST, even in its RESTless form, simply wasn't keep up with the needs
of increasingly complex SPA applications. The applications were becoming more and more like thick clients, and thick
client problems need thick client solutions, not bastardized hypermedia client solutions.
@ -385,7 +385,7 @@ Regardless, there is an opportunity here to explain REST and, in particular, the
developers who may have never heard of those concepts in their original context, and who assume REST === JSON APIs.
[People sense something is wrong](@/essays/a-response-to-rich-harris.md), and maybe REST, real, actual REST,
not RPC-EST, could be a part of [the answer to that](@/essays/spa-alternative.md).
not RESTless, could be a part of [the answer to that](@/essays/spa-alternative.md).
At the very least, the ideas behind REST are interesting and worth knowing just as general software engineering knowledge.

View File

@ -131,7 +131,7 @@ After all, both htmx and hyperscript are _built in JavaScript_. We couldn't hav
JavaScript, which, whatever else one might say, has the great virtue of [_being there_](https://en.wikipedia.org/wiki/Being_There).
And we even go so far as to _recommend using_ JavaScript for front-end scripting needs in a hypermedia-driven
application, so long as you script in a [hypermedia-friendly](/hypermedia-friendly-scripting/) way.
application, so long as you script in a [hypermedia-friendly](/essays/hypermedia-friendly-scripting/) way.
Further, we wouldn't steer someone away from using JavaScript (or TypeScript) on the _server side_ for a
hypermedia-driven application, if that language is the best option for your team. As we said earlier, JavaScript now

View File

@ -0,0 +1,96 @@
+++
title = "REST Copypasta"
date = 2023-06-26
updated = 2023-06-26
[taxonomies]
tag = ["posts"]
[extra]
show_title = false
+++
## REST copy-pastas
## Ackshually...
<div style="font-family: monospace">
I'd just like to interject for a moment. What you're referring to as REST,
is in fact, JSON/RPC, or as I've recently taken to calling it, REST-less.
JSON is not a hypermedia unto itself, but rather a plain data format made
useful by out of band information as defined by swagger documentation or
similar.
Many computer users work with a canonical version of REST every day,
without realizing it. Through a peculiar turn of events, the version of REST
which is widely used today is often called "The Web", and many of its users are
not aware that it is basically the REST-ful architecture, defined by Roy Fielding.
There really is a REST, and these people are using it, but it is just a
part of The Web they use. REST is the network architecture: hypermedia encodes the state
of resources for hypermedia clients. JSON is an essential part of Single Page Applications,
but useless by itself; it can only function in the context of a complete API specification.
JSON is normally used in combination with SPA libraries: the whole system
is basically RPC with JSON added, or JSON/RPC. All these so-called "REST-ful"
APIs are really JSON/RPC.
</div>
<button _="on click
get the innerText of the previous <div/>
then writeText(the result) with the navigator's clipboard
put 'Copied!' into the next <output/>
wait 2s
put '' into the next <output/>">
Copy
</button>
<button _="on click
get the innerText of the previous <div/>
get result.split('\n').map( \ l -> ' ' + l ).join('\n')
then writeText(the result) with the navigator's clipboard
put 'Copied for HN!' into the next <output/>
wait 2s
put '' into the next <output/>">
Copy For HN
</button>
<output></output>
<br/>
## l, t thē ¢ຖtrคrฯ
<div style="font-family: monospace">
In a world of digital wonder, allow me to take a moment to clarify. What many name as REST is, in truth, JSON/RPC, or as
I've lately begun to refer to it, the REST-less. JSON is not a magical script unto itself, but rather a simple parchment
of data made meaningful by wisdom from unseen sources, shaped by the likes of the Swagger tomes and their ilk.
Countless keepers of the code interact with a revered form of REST each day, oblivious to its presence. Through an
unexpected twist of fate, the interpretation of REST most commonly employed today is frequently dubbed "The Web", and
many of its inhabitants are unaware that they are, in essence, dwelling within the architectural dominion of REST, as
laid out by the sage Roy Fielding.
Indeed, there exists a true REST, and these individuals are making use of it, but it is merely a facet of The Web they
engage with. REST is the great network architecture: hypermedia inscribes the state of resources for the hypermedia
voyagers. JSON is a vital element of Single Page Applications, yet worthless in solitude; it can only exhibit its power
within the realm of a comprehensive API specification. JSON is typically deployed in alliance with SPA libraries: the
entire realm is fundamentally RPC embellished with JSON, or JSON/RPC. All these entities hailed as "REST-ful" APIs are
in actuality, the embodiment of JSON/RPC.
</div>
<button _="on click
get the innerText of the previous <div/>
then writeText(the result) with the navigator's clipboard
put 'Copied!' into the next <output/>
wait 2s
put '' into the next <output/>">
Copy
</button>
<button _="on click
get the innerText of the previous <div/>
get result.split('\n').map( \ l -> ' ' + l ).join('\n')
then writeText(the result) with the navigator's clipboard
put 'Copied for HN!' into the next <output/>
wait 2s
put '' into the next <output/>">
Copy For HN
</button>
<output></output>

View File

@ -23,7 +23,7 @@ table body:
```
The table body has a [`hx-confirm`](@/attributes/hx-confirm.md) attribute to confirm the delete action. It also
set the target to be the `closest tr` that is, the closest table row, for all the buttons ([`hx-target`](@/attributes/hx-target.md)
set the target to be the `closest tr` that is, the closest table row, for all the buttons ([`hx-target`](@/attributes/hx-target.md)
is inherited from parents in the DOM.) The swap specification in [`hx-swap`](@/attributes/hx-swap.md) says to swap the
entire target out and to wait 1 second after receiving a response. This last bit is so that we can use the following
CSS:
@ -37,9 +37,9 @@ tr.htmx-swapping td {
To fade the row out before it is swapped/removed.
Each row has a button with a [`hx-delete`](@/attributes/hx-delete.md) attribute containing the url on which to issue a `DELETE`
request to delete the row from the server. This request responds with empty content, indicating that the row should
be replaced with nothing.
Each row has a button with a [`hx-delete`](@/attributes/hx-delete.md) attribute containing the url on which to issue a `DELETE`
request to delete the row from the server. This request responds with a `200` status code and empty content, indicating that the
row should be replaced with nothing.
```html
<tr>
@ -138,4 +138,4 @@ tr.htmx-swapping td {
</table>`;
}
</script>
</script>

View File

@ -0,0 +1,36 @@
+++
title = "htmx is part of the Github Accelerator!"
date = 2023-06-06
[taxonomies]
tag = ["posts", "announcements"]
+++
We are excited to announce that htmx has been accepted into the first class of the
[Github Open Source Accelerator](https://accelerator.github.com/)! This is a tremendous opportunity to work with and
learn from some of the most successful open source developers and projects, and a great chance to get the message
out about hypermedia and htmx.
We plan on using this opportunity to begin work on htmx 2.0 and, we hope, possibly learn how to make working on htmx
a full time job!
Here are some of the other open source projects that we have met through the Github accelerator and that we recommend
people check out:
<ul>
<li><a href='https://boxyhq.com'>BoxyHQ</a> - BoxyHQs suite of APIs for security and privacy helps engineering teams build and ship compliant cloud applications faster.</li>
<li><a href='https://cal.com'>Cal.com</a> - Cal.com is a scheduling tool that helps you schedule meetings without the back-and-forth emails.</li>
<li><a href='https://www.crowd.dev'>Crowd.dev</a> - Centralize community, product, and customer data to understand which companies are engaging with your open source project.</li>
<li><a href='https://documenso.com'>Documenso</a> - The Open-Source DocuSign Alternative. We aim to earn your trust by enabling you to self-host the platform and examine its inner workings.</li>
<li><a href='https://erxes.io'>Erxes</a> - The Open-Source HubSpot Alternative. A single XOS enables to create unique and life-changing experiences that work for all types of business.</li>
<li><a href='https://formbricks.com'>Formbricks</a> - Survey granular user segments at any point in the user journey. Gather up to 6x more insights with targeted micro-surveys. All open-source.</li>
<li><a href='https://forwardemail.net'>Forward Email</a> - Free email forwarding for custom domains. For 6 years and counting, we are the go-to email service for thousands of creators, developers, and businesses.</li>
<li><a href='https://gitwonk.com'>GitWonk</a> - GitWonk is an open-source technical documentation tool, designed and built focusing on the developer experience.</li>
<li><a href='https://www.hanko.io'>Hanko</a> - Open-source authentication and user management for the passkey era. Integrated in minutes, for web and mobile apps.</li>
<li><a href='https://infisical.com'>Infisical</a> - Open source, end-to-end encrypted platform that lets you securely manage secrets and configs across your team, devices, and infrastructure.</li>
<li><a href='https://novu.co'>Novu</a> - The open-source notification infrastructure for developers. Simple components and APIs for managing all communication channels in one place.</li>
<li><a href='https://openbb.co'>OpenBB</a> - Democratizing investment research through an open source financial ecosystem. The OpenBB Terminal allows everyone to perform investment research, from everywhere.</li>
<li><a href='https://www.sniffnet.net'>Sniffnet</a> - Sniffnet is a network monitoring tool to help you easily keep track of your Internet traffic.</li>
<li><a href='https://typebot.io'>Typebot</a> - Typebot gives you powerful blocks to create unique chat experiences. Embed them anywhere on your apps and start collecting results like magic.</li>
<li><a href='https://www.webiny.com'>Webiny</a> - Open-source enterprise-grade serverless CMS. Own your data. Scale effortlessly. Customize everything.</li>
<li><a href='https://webstudio.is'>Webstudio</a> - Webstudio is an open source alternative to Webflow</li>
</ul>

View File

@ -5,3 +5,9 @@ Software Breakthroughs for the 21s Century,https://www.youtube.com/watch?v=O4ZFI
Django Chat,https://djangochat.com/episodes/htmx-carson-gross
Talk Python,https://talkpython.fm/episodes/show/321/htmx-clean-dynamic-html-pages
.NET Rocks!,https://www.dotnetrocks.com/?show=1749
"PyCharmIDE - Simple, Fast Frontends With htmx",https://www.youtube.com/watch?v=cBfz4W_KvEI
JetBrainsTV - htmx: Writing JavaScript to Avoid Writing JavaScript,https://www.youtube.com/watch?v=u2rjnLJ1M98
"DjangoConUS - REST, HATEOAS & Django - It's OK to not use JSON... or Javascript",https://www.youtube.com/watch?v=L_UWY-zHlOA
"airhacks.fm - HATEOAS, Data APIs, Java and How htmx Happened",https://airhacks.fm/#episode_200
ChariotSolutions - Return To Hypermedia: Solving Javascript Fatigue Using Fundamental Web Architecture,https://www.youtube.com/watch?v=LRrrxQXWdhI
Go Time - Is htmx the way to Go?,https://changelog.com/gotime/266

1 Name URL
5 Django Chat https://djangochat.com/episodes/htmx-carson-gross
6 Talk Python https://talkpython.fm/episodes/show/321/htmx-clean-dynamic-html-pages
7 .NET Rocks! https://www.dotnetrocks.com/?show=1749
8 PyCharmIDE - Simple, Fast Frontends With htmx https://www.youtube.com/watch?v=cBfz4W_KvEI
9 JetBrainsTV - htmx: Writing JavaScript to Avoid Writing JavaScript https://www.youtube.com/watch?v=u2rjnLJ1M98
10 DjangoConUS - REST, HATEOAS & Django - It's OK to not use JSON... or Javascript https://www.youtube.com/watch?v=L_UWY-zHlOA
11 airhacks.fm - HATEOAS, Data APIs, Java and How htmx Happened https://airhacks.fm/#episode_200
12 ChariotSolutions - Return To Hypermedia: Solving Javascript Fatigue Using Fundamental Web Architecture https://www.youtube.com/watch?v=LRrrxQXWdhI
13 Go Time - Is htmx the way to Go? https://changelog.com/gotime/266