<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Benjamin Lacy</title>
    <description>The latest articles on DEV Community by Benjamin Lacy (@bl42).</description>
    <link>https://dev.to/bl42</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1121451%2F95c6ab02-1f12-4c65-85a8-baa4691434f8.png</url>
      <title>DEV Community: Benjamin Lacy</title>
      <link>https://dev.to/bl42</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bl42"/>
    <language>en</language>
    <item>
      <title>The web has been waiting for HTMX</title>
      <dc:creator>Benjamin Lacy</dc:creator>
      <pubDate>Mon, 17 Jul 2023 16:36:47 +0000</pubDate>
      <link>https://dev.to/bl42/the-web-has-been-waiting-for-htmx-aim</link>
      <guid>https://dev.to/bl42/the-web-has-been-waiting-for-htmx-aim</guid>
      <description>&lt;h2&gt;
  
  
  Why now?
&lt;/h2&gt;

&lt;p&gt;Modern web features didn't just stop with Flexbox and View Transitions. New features are constantly being added, and its time to let go of our bloated javascript Libraries/Meta-Frameworks/Frameworks.&lt;/p&gt;

&lt;p&gt;With the significant advancements in browsers, our architecture needs to catch up&lt;/p&gt;




&lt;h2&gt;
  
  
  Wait, What Features??
&lt;/h2&gt;

&lt;p&gt;Let me provide you with a small sample of underrated features that are often overlooked. While this list is not exhaustive, it aims to expand your knowledge of what is possible. The best part is that everything I mention can be used today in all major browsers and even older ones with polyfills.&lt;/p&gt;

&lt;p&gt;You don't need to install packages found on a 5-year-old Stack Overflow post.&lt;/p&gt;




&lt;h3&gt;
  
  
  Intl namespace
&lt;/h3&gt;

&lt;p&gt;Moment.js has been a go-to package for date parsing, timezones, and localization. However, it comes with the cost.&lt;/p&gt;

&lt;p&gt;That cost is embedding a database encoded in json holding various translations, timezone preferences, and other locale-specific information.&lt;/p&gt;

&lt;p&gt;This database has thing like&lt;br&gt;
... the Tamil translation of "in 3 Days"&lt;br&gt;
... or the fact that Mexico prefers 24-hour Time.&lt;br&gt;
... or the preference of "PM" in the US and "p.m." in Canada&lt;br&gt;
... or every time a city in Indiana decided change its timezone over the last century  &lt;/p&gt;

&lt;p&gt;You get the idea, we dont need to ship all this data.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; and &lt;code&gt;Intl.RelativeTimeFormat&lt;/code&gt; APIs provide a simple and flexible solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RelativeTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// en-us (for me)&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// output:&lt;/span&gt;
&lt;span class="c1"&gt;// in 3 days&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-ca&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;America/Chicago&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;timeStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// output:&lt;/span&gt;
&lt;span class="c1"&gt;// Sunday, July 16, 2023 at 3:09:44 p.m. CDT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These APIs are supported today and offer powerful date and time formatting capabilities.&lt;/p&gt;




&lt;h3&gt;
  
  
  Form Validation
&lt;/h3&gt;

&lt;p&gt;Instead of installing one of the 2,000+ form validation packages available on &lt;a href="https://www.npmjs.com/search?q=form%20validation"&gt;npmjs.com&lt;/a&gt;, consider utilizing the built-in form validation in browsers. It covers the vast majority of use cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"/[A-z0-9]{3,0}/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"/[A-z]/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"lastname"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"/[A-z]/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Create Account&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach, combined with CSS pseudo-selectors, enables powerful styling and validation feedback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:invalid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"You are missing some stuff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:invalid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Password needs to be 8 chataters long..."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Side-note: The form submission is disabled until all requirements are met.&lt;/p&gt;




&lt;h3&gt;
  
  
  HTMLDialogElement
&lt;/h3&gt;

&lt;p&gt;Meet the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element, which can be fully customized for handling modals and toasts without requiring any JavaScript.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element has a unique feature — it renders outside of the DOM tree, even above elements with the highest z-index values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"overflow: hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- overflow: hidden doesnt effect &amp;lt;dialog&amp;gt; --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dialog&lt;/span&gt; &lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;To confirm type delete&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"dialog"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"delete"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;'/delete'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"delete"&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"/delete/"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;OK&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dialog&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Its just data!
&lt;/h2&gt;

&lt;p&gt;Consider the following JSON and HTML, What is the difference?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Joe_Black"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nl"&gt;"tweet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wow, that's incredible! 🎉 Thanks for sharing!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-07-16T10:30:00Z"&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"tweet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Joe_Black:&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Wow, that's incredible! 🎉 Thanks for sharing!&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"timestamp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Posted on: 2023-07-16T10:30:00Z&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One is encoded in &lt;code&gt;JSON&lt;/code&gt; other is encoded in &lt;code&gt;HTML&lt;/code&gt;. It is the same thing but in 2 different formats.&lt;/p&gt;

&lt;p&gt;After the data is loaded, the process of displaying differ significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON as Data
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Wait for &lt;code&gt;app.js&lt;/code&gt; to download. &lt;/li&gt;
&lt;li&gt;Parse and run inside the V8 engine.&lt;/li&gt;
&lt;li&gt;Rush to the First Paint, rendering an app shell and "loading" state.&lt;/li&gt;
&lt;li&gt;We segmented our application by code-splitting, so we need to repeat step first two steps with more code.&lt;/li&gt;
&lt;li&gt;Make a JSON request to fetch the tweet.&lt;/li&gt;
&lt;li&gt;Convert the data to HTML (or some JavaScript equivalent).&lt;/li&gt;
&lt;li&gt;Re-render the html with the new data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  HTML as Data
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Request the HTML.&lt;/li&gt;
&lt;li&gt;Append the HTML to the DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There has been two key problems with HTML as Data.&lt;br&gt;
First, it lacks fine-grained control over which parts of the UI change, often resulting in a full refresh. Second, sometimes we need to modify the data on the client side.&lt;/p&gt;


&lt;h2&gt;
  
  
  Modifying Data on the Client
&lt;/h2&gt;

&lt;p&gt;Lets focus on the timestamp from the previous example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"timestamp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Posted on: 2023-07-16T10:30:00Z&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may think have been painting a contradiction here "hey there is this really cool javascript API to handle dates... but lets stop using javascript".&lt;/p&gt;

&lt;p&gt;There will be times where we need to execute javascript to help render information. The solution is to use &lt;code&gt;customElement&lt;/code&gt; api to create atomic components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"timestamp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Posted on: 
    &lt;span class="nt"&gt;&amp;lt;intl-formatted-time&lt;/span&gt; &lt;span class="na"&gt;datetime=&lt;/span&gt;&lt;span class="s"&gt;"2023-07-16T10:30:00Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/intl-formatted-time&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These Custom Elements can be used to render the entire application (see &lt;a href="https://blog.youtube/news-and-events/a-sneak-peek-at-youtubes-new-look-and/"&gt;youtube's rewrite&lt;/a&gt;), but this should be the exception to the rule and not the default for the sites we build.&lt;/p&gt;

&lt;p&gt;Svelte has an interesting &lt;a href="https://svelte.dev/docs/custom-elements-api"&gt;Custom elements API&lt;/a&gt; that can play a roll here. &lt;/p&gt;




&lt;h2&gt;
  
  
  HTMX
&lt;/h2&gt;

&lt;p&gt;From htmx.org:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://htmx.org/"&gt;HTMX&lt;/a&gt; is a small library extending html using custom attribute tags. HTMX is a library that allows you to access modern browser features directly from HTML, rather than using javascript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All the extending of html is using custom attribute tags prefixed with &lt;code&gt;hx-&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gives the building blocks to make single page applications based on HTML communicating with servers responding in HTML (instead of JSON)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/htmx.org@latest"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;  &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/@user/tweets"&lt;/span&gt; 
        &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt; 
        &lt;span class="na"&gt;hx-target=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      User's Tweets
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;  &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/profile"&lt;/span&gt; 
        &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt; 
        &lt;span class="na"&gt;hx-target=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Profile
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;main&amp;gt;&amp;lt;/main&amp;gt;&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So lets break this example down.&lt;/p&gt;

&lt;h5&gt;
  
  
  hx-get
&lt;/h5&gt;

&lt;p&gt;This is a HTTP Verb that is setting the AJAX request method to a url... this can be replaced with other verbs like post, put, &amp;amp; delete.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are unfamiliar with "AJAX" (XMLHttpRequest) its like the &lt;code&gt;fetch()&lt;/code&gt; api. It was really cool back in the day.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5&gt;
  
  
  hx-swap
&lt;/h5&gt;

&lt;p&gt;The method to modify the DOM with the response of the HTTP request.&lt;/p&gt;

&lt;h5&gt;
  
  
  hx-target
&lt;/h5&gt;

&lt;p&gt;Which element to target the swap method.&lt;/p&gt;

&lt;p&gt;So with this knowledge lets rewrite &lt;code&gt;&amp;lt;a href ...&amp;gt;&lt;/code&gt; in htmx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/@user/tweets"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    User's Tweets
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- is equalivent to --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;  &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/@user/tweets"&lt;/span&gt;
    &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-target=&lt;/span&gt;&lt;span class="s"&gt;":root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    User's Tweets
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just with that small knowledge we can do alot and there is so much more to HTMX. This includes loading states, web socket support and even a scripting language called Hyperscript.&lt;/p&gt;

&lt;p&gt;It takes only a few minutes to get started and gain a good understanding of its capabilities.&lt;/p&gt;

&lt;h5&gt;
  
  
  Is HTMX the future?
&lt;/h5&gt;

&lt;p&gt;I have no idea but something like HTMX is a future that I am looking forwards to.&lt;/p&gt;




&lt;h2&gt;
  
  
  RESTful Components
&lt;/h2&gt;

&lt;p&gt;Components excel at isolating logic and concerns. However, they don't need to reside solely in the browser. I am introducing the concept of "RESTful Components," which are responsible for fetching data and presenting it in HTML format, powered by HTMX.&lt;/p&gt;

&lt;p&gt;For example, consider a user's post feed: &lt;code&gt;GET /user/:id/posts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/user/:id/posts?page=2"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-trigger=&lt;/span&gt;&lt;span class="s"&gt;"revealed"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"outerHTML"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Loading More...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Little bit of Recursion happing here.&lt;/p&gt;

&lt;p&gt;As you scroll to the bottom, &lt;code&gt;hx-trigger="revealed"&lt;/code&gt; triggers the loading of the next page, and the trigger for the 3rd page is subsequently loaded.&lt;/p&gt;

&lt;p&gt;Another example: &lt;code&gt;GET /post/:id&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"comments"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/post/:id/comments"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-trigger=&lt;/span&gt;&lt;span class="s"&gt;"intersect once"&lt;/span&gt; 
    &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"innerHTML"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        Loading Comments
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;



&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;/** inlined css for demo purposes */&lt;/span&gt;
    &lt;span class="nc"&gt;.post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   
        &lt;span class="py"&gt;container-name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.post&lt;/span&gt; &lt;span class="nc"&gt;.comments&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;@container&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
         &lt;span class="nc"&gt;.post&lt;/span&gt; &lt;span class="nc"&gt;.comments&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 
     &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we are conditionally loading the comments.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;/post/:id&lt;/code&gt; could be used on dedicated page for the post or as an aside on another page. Size constraints will determine whether comments are loaded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;All these pieces are there, HTMX is the missing glue to build complex HTML driven applications.&lt;/p&gt;

&lt;p&gt;There is still much more to explore and I have my reservations.&lt;br&gt;
One is HTMX's HyperScript scares me in a CoffeeScript kinda way ... another is the pattern for SSR type of templating on the backend.&lt;/p&gt;

&lt;p&gt;However, the technical advantages and tradeoffs are to strong to ignore.&lt;/p&gt;




&lt;p&gt;If you want to be friends reach out to &lt;a href="https://twitter.com/bl42"&gt;@bl42&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>hateoas</category>
    </item>
  </channel>
</rss>
