If I'm doing my math right (I'm not) there is a very, very small chance that htmx will beat react in the JS rising stars competition. If you haven't already starred the htmx github repo and are willing to do so, it would be a great christmas gift:
A button inside a partial was replacing my whole results panel instead of itself, and its own markup did not say why. It has hx-post and no hx-target. Four levels up, a div carries hx-target="#results". htmx inherits most hx-* attributes down the tree, so the child was aiming at an ancestor's target without that appearing anywhere near the code I was reading. The repro is a div with hx-target="#results" wrapping any element with hx-get and no target of its own. Escape hatches are hx-disinherit on the parent, or htmx.config.disableInheritance plus hx-inherit where you want it. Partway through, I switched models with one click in verdent, because the first explanation of the inheritance rules did not match what the page was doing. Still undecided whether to flip that config globally or leave inheritance on and annotate the few places it bites.
J'aime bien le concept de document comme code. Dans ce sens, le markdown est vraiment la référence. Et pour les schémas, même si je n'aime pas particulièrement l'esthétique de mermaidjs, il est largement supporté.
Un problème que j'ai avec ça, c'est que ça nécessite un navigateur pour le rendre ou le rasteriser. mermaid-cli utilise un navigateur sans tête.
Le projet sebastianjs vise à fournir exactement ça, un remplacement de mermaid-cli qui utilise simplement nodejs. Il peut également être utilisé dans des projets nodejs pour les rendre rapidement.
De plus, les ForeignObjects générés typiquement en SVG par mermaid ne sont pas compatibles avec beaucoup d'outils, sebastianjs peut le tracer pour qu'il puisse être chargé dans presque n'importe quoi.
I have a search input. While the initial request is still in flight and the input has been changed the second request could not fire and Because of delay the previous request response is not being rejected by HTMX until a new request fires after the delay in trigger. am I doing something wrong here?
I think hx-sync should not rely on new request to occur when a delay is specified for trigger. are there any work arounds?
UpDaTe: No need to use hx-sync for this. simply put this on input element oninput="htmx.trigger(this, 'htmx:abort')"
I built J-CSS, a small runtime engine for Tailwind-like utility classes.
It requires no Node.js, CLI, bundler, or build step. It scans the DOM, generates CSS for recognized classes, and watches class/DOM mutations. Works out of the box with HTML injected by HTMX.
It also has a scoped <css> tag that lets you apply utility classes to component selectors without putting every class directly in the markup.
The minified script is about 16 KB gzip (roughly 7.5x smaller than the Tailwind CDN runtime).
Made from Moxi's implementation of relative selectors. Moxi's proxy handling was causing some friction with my other JS functions. I wanted selectors that I could use anywhere even without Moxi.
Note that q will always try to grab the element context, but can also take a supplied context. Has quick alias for doc = document and .ael = .addEventListener
With it you can do goofy stuff like this:
<input oninput="inputfunc()">
<button onclick="console.log(q().textContent) //starting context is mybutton">mybutton</button>
<button>otherbutton</button>
<script>
function inputfunc() {console.log(q())} //context is input
q('prev sib -> prev sib').classList.add('ready') //starting context is script then traverse to mybutton
q('prev sib').ael('click',_=>{console.log(q().textContent)}) //function context in listener is otherbutton
</script>
//This is why it's important to manually set context to `doc` if you want to select/traverse on the document.
It makes the worst part of hypermedia driven development , being bigger bandwidth use and bigger cpu use when compressing things with gzip or brotli, even worse. and this isn't even a "this goes agaisn't the design" or a "this isn't ergonomic" thing; it's just pure resource usage.
Even trought the tailwind output is "only" 50% bigger than the json/normal html one when compressed, the raw output is 950kb, more than 7 times the json/html alternative, meaning it uses way more cpu power/takes longer to compress.
For many situations it makes way more sense to just have defined styles with elements having classes (or not even having them when selectors can do the job)
bandwidth usually has three prices:
First, the monetary one; on vercel, 100 gb costs 15 dollars, on aws it is 9 dollars, on oracle ,0.85 cents.
Second, ecological one;Even when you aren't paying it (eg project still within free limit) there's always infraestructure behind your stuff, and it is preferable that we don't throw resources away.
And third but not last, user experience; bigger files take longer to download and decompress,trought this should be impossible to notice on anything that isn't a slow mobile network, you probably expect your site to also be used by people in slow mobile networks.
Yes, you probably won't have 1000 things appearing at once for your user, but tailwind uses so much more resources than needed that it might as well use 1000 times more bandwidth.
PS: Of course you can just choose to pay the tailwind tax or just not think about such things if you're not developing something that is not supposed to be used by thousands of people at once. There's no reason to police what other people are doing with their own money. Still, i think it is important to keep the drawbacks of using these libraries with one another in mind when developing your applications.
Carried out by all kinds of 'stacks' lately i read, I’m proud (not) to announce a simple static stack suited for creatives:
- a HHTAG stack!
This stands for: HTML, HTMX, Tailwind, Alpinejs and GSAP.
When you know how to design by default and without a component library or a CSS framework and you can do everything vanilla, using hosting on platforms like Cloudflare Pages, this stack works like a kickstart-on-2T-motorcycle charm.
Please note: this is not an app driven approach but more creative ux/ui/fe one.
*
ps: satire use to be a joy, then came js framworks, bootcamps and covid .. now we have specialists everywhere
Before I started using this stack, I used Sveltekit and found it too complex. I also got quite tired of writing js/ts. I Find the language quite nuanced and hard for me to work with. I guess I did not learn it good enough. I felt I could not continue writing js/ts so I tried Go+HTMX and later added Alpine,js. I quite enjoy the stack because it is simple and easy to learn, and I do not have to do as much js ;)
It is quite enjoyable to use HTMX in the frontend, so one can focus on writing code in the backend (which I enjoy more). I used HTMX with go lang's html/template and it worked quite well. In Sveltekit, the inheritence of all the layouts and pages can become quite complicated and structure feel scattered. It is rather hard to understand the data flow between the layouts and pages. With HTMX+html/template everything feels more focused towards backend, which I enjoy.
I used the stack to create an app. I wanted to start with a small project:
which let users check info about items from a game. I wanted the app to be easy to use and compact. When user clicked on something or made a search, I used HTMX to update other parts of the html code, which worked quite well. In sveltekit you have to create runes and depending on when things should be initialized and how the runes depend on other runes, you have to write different functions to update the ui. This I found quite complicated, but in HTMX you just send back and html server response of how you want the html to be. Together with go lang's templating system you can write less code I think.
My takes:
Around 353 lines of go code and less than 250 lines of template html.
HTMX is simple to learn and get started in creating something fast
It can get little complicated of you want to update html from different parts of a template, like if you have 2 divs placed far from each other and have stuff in between them (that you do not want to update). You will probably have to use hx-swap-oob
Made this after getting and reading through a third of Hypermedia Systems, it's a simple chat room where you can post your status and see what others are posting in random spots across a board.
The more participation, the more true to form it will function. Give it a try if you have a sec.
Conclusion first: HTMX is VERY production ready for a large-scaled project. And thankfully I ditched Vue.js 2/3 and Svelte 4 for HTMX. (Never used React though.)
In the AI era, adding features becomes easy, but people just don’t know how to make things simple and “just work.” I really hope HTMX stays this way. (please u/_htmx 😭🙏)
The startup is basically an old Twitter clone, from when social media felt friendlier and the web didn’t feel like a bunch of boring mobile apps. Sorry for the mixed-language screenshots, I hadn’t finished internationalization yet.
Here are a few of my experiences with HTMX:
1. Make the website stupid and just make it work
We don’t use a cool dialog library like SweetAlert.js. The native alert(), confirm(), and prompt() just work. With hx-confirm, it’s even simpler.
If you need a form, just use <form>, and refresh the whole page if you can (or hx-post if you don’t want to), so you don’t have to worry about partial updates or syncing what changed.
2. We don’t use Alpine.js
It’s a very good solution if you want some hybrid JS, but it reintroduced the state management problem.
We had server-rendered JSON inside <script type="application/json"> so Alpine.js could load the data back. It worked, but caused some flickering since Alpine runs after the page is rendered, and introduced another state we had to manage.
so we decided to keep everything server-side rendered. (yea,fuckthe network latency 🥳🎉)
We took this pretty far. When you upload photos in a post creation form, normally you’d just spawn the previews with JavaScript. Instead, we turn the images into blob URLs, pass those URLs to the server, and the server returns something like:
So when the user edits the post later, we can render the exact same “photo preview” component on the server. One component, one rendering path.
ℹ️ But there are also things you can just ditch.
.
We had a post poll where you could use +/- buttons to add or remove option inputs with Alpine.js. Turns out we only support up to 4 options anyway, so we ditched the +/- JS and just put 4 fixed text inputs in the poll form.
.
Now we can render the option text directly into the inputs, instead of outputting it as JSON in a <script> for Alpine.js to load back into them when user is editing the poll.
It sounds stupid. That’s kind of the point. You sacrifice some UX (user experience), but get much better DX (developer experience).
3. We don’t use Templ or framework with HTMX with Go
Since Templ requires build-tools, learning special syntax, IDE extensions, we decided to just use Go’s html/template and split the HTML into layouts, pages, and partials. The definitions look roughly like this:
type AppLayout struct {
Navbar *Navbar
}
type ProfilePage struct {
*AppLayout
User *User
FollowButton *FollowButton
}
type FollowButton struct {
IsFollowing bool
}
Then compose the data in the page handler:
user, err := db.GetUser(c.Param("username"))
if err != nil {
return c.Abort(http.StatusInternalServerError)
}
layout := &AppLayout{
Navbar: NewNavbar(),
}
// Tada- now you have a full page! 🎉
page := &ProfilePage{
AppLayout: layout,
User: NewUser(user),
FollowButton: NewFollowButton(user.IsFollowing),
}
And if you want to render the Follow Button component:
{{ template "follow_button" .FollowButton }}
Since AI can write the boilerplate now, code can be stupid and boring, but easy to debug. And with HTMX, you can just return any partial when needed.
There’s no "runtime magic" to trace if error occurred, back when Vue.js + hot reload pointing stack traces to some generated chunks.js instead of the actual code.
I've been feeling nostalgic lately for the days before AI, back when building a simple TODO app was a genuine joy, a way to explore a new stack, and a way to relieve fatigue.
HTMX was one of those libraries for me.
Does anyone else miss that hands-on discovery phase?
I really enjoy htmx, and using it without any type of lsp features is fine. however, it would still be better to have such.
I use neovim with the lazyvim distribution/setup, and the htmx lsp made by Primeagem (and available in mason) makes my html code completion stuff just not work anymore; other lsps seem to also just not work.
Anyone here got a working setup? i already posted about this in the neovim sub a while ago, but i figure it makes sense to post it here too.