Join me while I learn HTMX and talk at you about it
Twitter: @htmxlabs
The podcast hx-pod is created by Lazarus. The podcast and the artwork on this page are embedded on this page using the public podcast feed (RSS).
Adam Stepinski, creator of Hyperview and co-author of Hypermedia Systems, explains how and why developed Hyperview.
Hyperview lets you create a shell for your iOS/Android app, then populate it using XML and hypermedia, htmx-style inspired concepts.
Hyperview is extensible, so you can find or build your own plugins.
Links discussed:
Website: https://hyperview.org
Hyperview Github Repo (best place to ask questions): https://github.com/instawork/hyperview
Discussion about client-side validation: https://github.com/Instawork/hyperview/discussions/332
Examples of defining multiple behaviors: https://hyperview.org/docs/reference_behavior
Lazarus is joined by guest Lazarus to talk about his new project, hypecp.com, which bears a striking resemblance to his old project, htmxlabs.com
Eric Harrison, MakeStartups
Original twitter post:
https://twitter.com/blister/status/1752357600547545356
For-Profit: https://makestartups.com
Non-Profit (school): https://makestartups.org
Personal website: https://ericharrison.info
Home site: https://alexanderpetros.com/
Utah JS talk (100 year web service): https://www.youtube.com/watch?v=lASLZ9TgXyc
Big Sky Dev Con Talk (Life and Death of Htmx): https://www.youtube.com/watch?v=1g5ruM-16_Y&t=2684s
Triptych Proposals: https://alexanderpetros.com/triptych/
Blog: https://unplannedobsolescence.com/
Tanner Bass claims to speak on behalf of the CEOS
Got a problem? Tell me all about it at
https://htmxlabs.com
Lucas Pires of CheckSec on when to use htmx and django -- and when NOT too
Links:
PyCon PT 23 | Building advanced back-office interfaces using Django & HTMX
https://www.youtube.com/watch?v=hdLWZQb8pkE
Ok, so different build (no Node js, no npm, no yarn)
https://tailwindcss.com/blog/standalone-cli
Sahil's tweet:
https://x.com/shl/status/1839686512767627310
Where is our ShadCN? Where is our Flux UI? Where is our Tailwind UI?
Hypermedia contrained by ajax and network calls?
No way -- Delaney is here to expand your mind with 60fps hypermedia streaming to your browser!
Data Star:
https://data-star.dev
Grugs around the Fire:
https://data-star.dev/essays/grugs_around_fire
John is ready to build something real.
What if it went straight into production as a dashboard widget?
See what I'm talking about:
https://x.com/htmxlabs/status/1831510008946708959
Shoutout to reddit user Thoram
https://www.reddit.com/r/htmx/comments/125gha4/prevent_scrolling_on_hxboost/
My father in law runs his business using a CAD app running on a floppy disk. No, I'm not kidding
Ben Croker is building Sprig for CraftCMS, a reactive framework for CraftCMS built using htmx.
As one of the top contributors to htmx, Ben also shares his tips on contributing to open source.
Sprig Cookbook: https://putyourlightson.com/sprig/cookbook
Ben on Twitter: https://x.com/ben_pylo
Craft CMS: https://craftcms.com
http://devMode.fm
Ben Croker + Carson Gross podcast episode: https://devmode.fm/episodes/dynamic-html-with-htmx
An HTMX success story
https://www.sheenaoc.com/articles/2024-06-30-htmx
Sheena joins to talk about how she teaches her junior devs to teach noob devs how to become junior devs
Practice over theory. hx-swap-oob. optimistic uis. the secret to making memes
<dialog> tag is great
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog
Ignorance is bliss
John says what's up with marketing for small businesses
Youtube: https://www.youtube.com/watch?v=S7BX2ocn7XM
What's an efficient/great way to add modals using htmx?
Anthony's talk at Big Sky Dev Con:
https://www.youtube.com/watch?v=uVKSmR_hBMs&t=9142s
This episode on youtube (i.e. see faces)
https://www.youtube.com/watch?v=LQfKmpx7QZ8
Mentioned, how to submit and reset a form on success using htmx:
<form hx-post="/admin/candidates"This assumes the last row is the add form, and places the newly added item directly above it.
"We've done them all now"
All headers grouped
===========> REQUEST HEADERS
======> Flags
*HX-Boosted - was it a boosted link
*HX-Request - is it an htmx request
*HX-History-Restore-Request - is it a back button restore request
======> Auto-sent variables
*HX-Current-URL - current url page is at
*HX-Target - id of target if has id
*HX-Trigger-Name - which element triggered it by name
*HX-Trigger - which element triggered it
======> User Variables
*HX-Prompt - user is asked to provide prompt, this is what they typed
============> RESPONSE HEADERS
======> Browser & history commands
*HX-Location - hx-boost reload to page
*HX-Redirect - regular redirect
*HX-Refresh - refresh page
*HX-Push-Url - push url to top bar
*HX-Replace-Url - replace url in top bar
======> override attributes
*HX-Reswap - sets hx-swap value
*HX-Retarget - set hx-target value
*HX-Reselect - set hx-select value
======> Trigger events
*HX-Trigger - trigger an event on client immediately
*HX-Trigger-After-Swap - trigger an event after swapping in html
*HX-Trigger-After-Settle - trigger an event next lifecycle
i went to #BSDC2024 (not an htmx con) so you don't have to.
here's my own recap of all the talks
Every talk is available to watch at: https://bigskydevcon.com
Use this response header to send event trigers to ANY client side browser event (javascript, htmx, custom, etc)
HX-Trigger - as soon as response received
HX-Trigger-After-Swap - after new html is swapped in
HX-Trigger-After-Settle - after new html is settled and processed by browser
{ "HX-Reselect": "#one-div-inside-html" }
This episode explores what an optimistic ui might look like in htmx. Also: is it what we want to do? Is it even possible? Or is it incompatible with the idea of having the dom as the true application state?
Original tweet:
https://x.com/noahflk/status/1795758603577545035
DHH responses:
https://x.com/dhh/status/1796163806650868149
Htmx guy responses:
https://x.com/htmx_org/status/1796182554883539236
Override your "hx-swap=" attribute.
Correct your hx-swap mistake! Do it now!!!
Decide from your server side what url the user sees!
https://htmx.org/headers/hx-push-url
Speaking with a prolific developer who recently switched from React to htmx
Redirect your users to a new page from your back-end server in SPA-mode (no refresh for them)
https://htmx.org/headers/hx-location/
This header is to make sure your system loads the full page when
1) You are suing hx-push-url to work with the url bar
2) Users click the back button.
3) The full page cached history snapshot isn't there
Useful links mentioned:
https://github.com/bigskysoftware/htmx/issues/497
The htmx request header that tells you
EXACTLY where the user is making the request from
The full url string with all ids and params
A case for taking the extra steps. It's a good thing
hx-prompt="what's your favorite size turtle?"
Request Headers:
Hx-Prompt: small
How can your server tell if its a regular link click or an hx-boost SPA-mode link click??
I'll tell you everything about it in these 5 minutes!
Let's your server know what the id is of the hx-target!
You need 2 things to send this request header:
1. Use the attribute: hx-target="some_id"
2. Use a DOM id as the target: some_id needs to be an id, not another css selector
You can use these headers to conditionally branch your response based on *which element* the request was triggered from
example of format:
Request Headers:
Hx-Trigger: search_input
Hx-Trigger-Name: search
An example in the wild: The Laravel blade documentation:
https://laravel.com/docs/11.x/blade#rendering-blade-fragments
We're (Me're) 43 episodes in. What's next?
We talk integrating htmx with Wordpress!
Andrew Rhyand
https://andrewrhyand.com/
Mentioned links:
HTMX movies demo: (very slick & educational)
https://htmx.andrewrhyand.com/
Author of the Wordpress/Inertia Adapter:
https://github.com/boxybird/inertia-wordpress
Alpine/Livewire in Wordpress:
https://github.com/boxybird/morph
Advanced htmx: Recap & grouping each of the 13 advanced attributes we went over this "season"
This means we have now gone through every attribute! (not counting extensions)
1. Browser & History
Hx-push-url - set your url
Hx-replace-url - replace your url, save no snapshot
Hx-history-elt - change snapshot from default to particular element
Hx-history - prevent something from being saved in the htmx snapshot
2. Customizing Requests
Hx-request - set no headers or timeout on request
Hx-headers - set custom headers, dynamic or static json
Hx-sync - allows you to set rules for multiple htmx requests at once
3. Submitting Data
Hx-validate - allows you to use validation rules outside of forms
Hx-disabled-elt - disables a button once you’ve clicked it
Hx-encoding - allows you to upload files via Ajax
4. Overriding Htmx
Hx-disable - allows you to disable htmx for user comments, posts, etc
Hx-disinherit - breaks inheritance chain for one or more attributes
5. Fun!
Hx-select-oob - lets you place element from your response wherever you want
Reddit thread with an example:
https://www.reddit.com/r/htmx/comments/1bukz76/hxselect_reset/
What if you wanted a part of your site to persist even using the back and forward on your browser?
Here is the reddit thread I mention in the episode, with an example:
https://www.reddit.com/r/htmx/comments/1bu14sg/how_to_make_a_audio_player_that_survives_the_back/
This one might actually be essential, not just an advanced attribute. Keeps you and your users from accidentally submitting things multiple times.
An amazingly simple file uploading form *with a progress bar* using htmx:
<form id='form'
hx-encoding='multipart/form-data'
hx-post='/[where-you-want-post-it]'
hx-target='#target-div'>
<input type="hidden" name="_token" value="" />
<input type='file' name='file'>
<button>
Upload
</button>
<progress id='progress' value='0' max='100'></progress>
</form>
<script>
htmx.on('#form', 'htmx:xhr:progress', function(evt) {
htmx.find('#progress').setAttribute('value', evt.detail.loaded/evt.detail.total * 100)
});
</script>
What if you could "select" snippets out of your response and send them to anywhere on the page ("out-of-band") of the target?
that's hx-select-oob
Server traffic cop: hx-swap-oob
Client traffic cop: hx-select-oob
Let's talk big ideas like Locality of Behavior vs. Separation of Concerns by relentlessly attacking one of the best websites ever created
Set the outer layer of settings of your request with THESE THREE OPTIONS
Question: Do you want your users in the comment section to write htmx that runs on your site?
If the answer is yes, please ignore this episode.
What if you don't want your page kept into the browser history local storage?
This is a somewhat open thought process looking at the question I see online: what is htmx good for?
Mentioned in the episode: the htmx movies example from Andrew Rhyand:
https://htmx.andrewrhyand.com/
A great looking page with smooth animations and educational htmx content on it.
Your browser has built in types and validation on inputs in a form. But what happens when you use inputs without a form??
Note: I accidentally posted an incomplete episode at first, if you dont hear the end, try to re-download!
Every request has secret hidden headers. But what if you wanted to make your own?
https://htmx.org/attributes/hx-headers/
When you make your life easier, that's a win.
Having any weird async ajax request issues?
htmx got yer back 🤜 🤛
Push your ajax route to the url bar! Now you've got access to the back button again.
.. but what happens when you refresh?
Work with the browser history on any htmx request with hx-push-url and hx-replace-url.
PUSH it to the Browser history stack:
hx-get="/account/details" hx-push-url="true"
REPLACE the current browser history stack:
hx-get="/account/details" hx-replace-url="true"
Per listener request: Same episode as last, but without the soundtrack!
Keeping the other up for posterity's sake.
Every developer should have their own custom to-do app. Join me for my journey building this simple app in my head using htmx
Every attribute so far and where they fit together.
What if.. you wanted just a part of the html from the response?
In a perfect world, you could just use a simple css selector to get only what you need and filter everything else out.
Well, welcome to the perfect world -- hx-select style.
NOTE: This is some Star Trek computer shit. You gotta hear it to believe it
BIG interview today.
We delve into where htmx fits in the broader dev world, how we might build a calendar with htmx, and even how to build and publish our own hx-load-class attribute.
Updating a chunk of the DOM is easy -- but what if you wanted to leave one element alone?
<div id="leave-me-alone" hx-preserve>Content preserved</div>
Content will NOT be swapped out in the request, as long as the id in the request data matches.
Do you ever want to let the user know you are loading something?
Of course you do. Just add the htmx-indicator class to any element (loading div, svg, gif), and the parent requests will make it show up.
We discuss the magic you get for free in htmx and the way to customize it!
ok, you are submitting a form.. but what if you don't want to submit the whole thing?
Use what only i call "the mysql selector of htmx"
hx-params="first_name, last_name, state"
or what if you wanted to exclude a field?
hx-params="not secret_field"
How do you feel about setting your request values right there inline?
STATIC
<button hx-get="/my/weather/data"
hx-trigger="click"
hx-vals='{"location": "01245"}'>
Click for weather in one static location
</button>
DYNAMIC
<button hx-get="/my/weather/data"
hx-trigger="click"
hx-vals='js:{location: document.getElementById("zipcode").value}'>
Click for weather in one static location
</button>
OR
<button hx-get="/my/weather/data"
hx-trigger="click"
hx-vals='js:{location: someJavascriptCalculationFunction()}'>
Click for weather in one static location
</button>
Your built-in advantage of building html on the server: everything important is already there.
Here are the two server/client mental model discussions referenced in the audio:
1. Primagean "The truth about HTMX"
Front end backend s=discussion starts around 12m
https://www.youtube.com/watch?v=2hMrk7A8Wf0
2. Mostly Technical Podcast
"High Floor vs. High ceiling"
https://mostlytechnical.com/episodes/13-the-sql-injection-slide-with-sam-selikoff#t=9m6s
How can you change your entire site to be faster and snappier with just one attribute?
How can you recreate the entire libraries of turbolinks and pjax in a single line?
How can you make your entire site essentially an SPA?
<body hx-boost="true">
Or, "How I learned to stop worrying and stack this stack on all other stacks."
Essay on HOWL from htmx.org:
https://htmx.org/essays/hypermedia-on-whatever-youd-like/
ALERT ALERT hx-on is changing tomorrow!
...sort of
1->2 guide:
https://v2-0v2-0.htmx.org/migration-guide-htmx-1/
hx-on attribute:
https://htmx.org/attributes/hx-on/
What, you're too good for a regular javascript confirmation?
Fine
https://htmx.org/examples/confirm/
Who gatekeeps the Gatekeepers? the coast guard?
Thank you to rick @maverism for tweeting out the podcast!
What on earth are PUT PATCH and DELETE and why would I use them instead of POST?
Well, which do you like better?
A) <button hx-delete="/articles/1">
B) <button hx-post="/articles/1/delete">
How to load a bunch of links to the after the page loads and place them anywhere you want with hx-swap-oob
On site:
<div hx-get="/load-podcast-links" hx-trigger="load"></div>
In response:
<div id="placement-1" hx-swap-oob="true">Placement 1 text and link</div>
<div id="placement-2" hx-swap-oob="true">Placement 2 text and link</div>
<div id="placement-3" hx-swap-oob="true">Placement 3 text and link</div>
.....
This is a new idea: let your response decide its own target(s)!
<div id="my-update-div" hx-swap-oob="true">Updated html</div>
<div id="my-update-div-2" hx-swap-oob="true">More updated html elsewhere on the page</div>
Uh oh. Your inputs are outside a <form> tag, what's to be done?
Want to use POST requests in ajax, and submit forms from anywhere on the page?
As promised in the episode, here are three ways to set up your CSRF token headers:
1. Like normal in your forms:
<input type="hidden" name="_token" value=""/>
(the regular html way works with htmx, of course)
2. Javascript
<script>
document.body.addEventListener('htmx:configRequest', (e) => {
e.detail.headers['X-CSRFToken'] = '';
})
</script>
(add this to the bottom of your </body> so that EVERY request gets the right headers. I love this one!)
hx-headers
<div hx-post="/your-endpoint" hx-headers='{"X-CSRF-Token": "YourCSRFTokenHere"}'>
<!-- Your content -->
</div>
(add this attribute along with your hx-post)
You got your data back and your target, now where does it fit?
Is this really learning? It might be.
What would "tailwind but for javascript" feel like?
What if your browser could skip the json-processing step of an api?
Consider this: you have to add a fancy feature to a legacy app.
Who you gonna call?
En liten tjänst av I'm With Friends. Finns även på engelska.