return to table of content

Show HN: htmz – a low power tool for HTML

Arch-TK
14 replies
3h48m

Given that this uses `target`, doesn't it mean that unlike htmx you can't easily make this gracefully degrade when JS isn't enabled?

And, yes, I know, saying "when JS isn't enabled" in 2024 is a bit like saying "when the user is on Mars and has a 10 minute RTT" but forgive me for being an idealist.

beretguy
4 replies
3h40m

I use Disable JavaScript extension with js disabled by default and only enable it if website is broken.

https://addons.mozilla.org/en-US/firefox/addon/disable-javas...

efilife
3 replies
3h30m

You should use uMatrix so you can only enable the scripts necessary to unbreak the site

SushiHippie
1 replies
12m

Or uBlock origin (from the same author) which is still maintained

pmontra
0 replies
7m

It is maintained but the UI for dealing with JS is horribly time consuming and overly complex compared to uMatrix. I'll never really understood it and I keep using uMatrix on my laptop. I switched to NoScript on my phone. Maybe I can install uMatrix now if Mozilla really unblocked many extensions. If uMatrix stops working, I'll switch to NoScript everywhere for JS and uBO for all the other issues.

account-5
0 replies
1m

Or uBlock advanced which is not abandoned/dormant like umatrix.

MatthiasPortzel
4 replies
2h44m

being an idealist

Could you describe your ideals for why websites should gracefully degrade without JS enabled? It’s not an unpopular view on HN, but from my perspective as a web developer, JS is a part of browser application just like HTML, and there’s no reason for the website to work if you’ve disabled a part of the browser.

I suspect “doesn’t have JavaScript” is being used as a proxy for a lot of other ideals that I do understand, like “should work on as many devices as possible” but that’s a rough correlation and doesn’t make the use of JS inherently bad.

tambourine_man
0 replies
12m

Because there's a case for a very useful Web without running a Turing-complete language on the visitor's end.

If you just want to consume text, images, audios and videos, follow links and fill in forms (and that's quite a lot and pretty awesome already), you shouldn't need JavaScript.

SigmundurM
0 replies
2h2m

A reason people might want to have JavaScript disabled, is because of the immense tracking possibilities that JavaScript has, which can't easily be safe-guarded against.

The people who do disable JavaScript completely are admittedly few and far between, but are, I would assume, more common among the Hacker News crowd.

J_Shelby_J
0 replies
2h18m

Chances are I’m on your website for information, mostly text content. Which really doesn’t require JavaScript.

So then, most JavaScript on the web is enabling revenue generation rather than improving the user experience. So yeah, disabling JS is a proxy for, “don’t waste my time.”

But I agree that it’s not inherently bad, but just mostly bad (for the user.)

Arch-TK
0 replies
1h59m

So I've been in numerous situations where having JavaScript enabled was either undesirable or impossible, granted, it's my own fault for using strange platforms like a Nokia N900 or whatever, with strange web browsers. But it's still nice when interactive websites continue to work even in contexts where JavaScript isn't a thing. I always thought of JavaScript as something you use to "upgrade" the web experience, not to build it. Although obviously there are some things you simply can't do without JavaScript and for which there exists literally no alternative. There's also situations where JavaScript is a liability. See, for example, the Tor browser.

Especially my ideal is that all functionality which can work without JavaScript should work without JavaScript. So, for example, I am not expecting someone to implement drag-and-drop calendars without JS, but there's no reason why the editing function of a calendar item should fundamentally require JS.

That being said, I know this is an idealist position, most companies which work on developing web-applications simply don't care about these niche use-cases where JS isn't an option and as such won't design their web-applications to accommodate those use-cases to save on development costs and time. But, while I am not really a web-developer, whenever I do deal with the web, I usually take a plain-HTML/CSS first approach and add JavaScript later.

Kalabasa
2 replies
3h29m

Yeah it breaks without JS. You could add the iframe behind JS, so the target would default to a new tab. But the server would still be designed to return HTML fragments. I never found a way for a server to check if the originating request is for an iframe or a new tab. It's not quite a graceful degradation.

simpaticoder
0 replies
3h12m

> I never found a way for a server to check if the originating request is for an iframe or a new tab.

There is no such technique. One way to distinguish is to pick a URL convention and modify the URL (before the hash) of the iframe URL. For example, add ?iframe=true to the URL, and then have the server check for that. Perhaps more usefully you could include information about the parent URL, e.g. url += '?parent=${document.referrer}'. Or something.

naasking
0 replies
3h24m

You could intercept the clicks with JS and add a special header, like htmx does, to return fragments, otherwise fall back to full documents.

Edit: rather than a header, dynamically adding a query parameter to the URL of the element that was clicked would probably fit better with htmz's approach.

pmontra
0 replies
12m

It breaks without JS but many JS blocker extensions can be configured to always allow JS from the host serving the page. For example NoScript on my phone has the "Temporarily set top-level sites to TRUSTED" option.

With only 181 bytes it could even be included in the page. It's much less than the sum of the meta tags on many sites.

tambourine_man
11 replies
3h34m

That's a great hack and it shows how close the browser is to offering SPA natively.

Just a few attributes and we could avoid the iframe.

It's probably more useful to prove a point than an actual day to day tool. And the point seems to be: htmx is too much trouble for what it offers. We just need HTML native ajax.

Kalabasa
6 replies
3h14m

Yes this was a response to htmx. It was a half-parody half-I wanna make it work project. Like https://github.com/vilgacx/aki

I would fear if anyone wants to use this in production BUT I would love someone to get inspired and use the concepts rather than the actual code. Hmm maybe i should write a disclaimer...

noduerme
0 replies
23m

It's funny, I stumbled on a similar use for iframes a few years ago that I did put into production. I needed to have a rather large SPA for employees hosted locally - that is, on a server on a local network in retail stores, not accessible from the web or unless you're on the same network as the server. The employee had to be able to load it on a tablet (but wouldn't necessarily know the server's local, dynamically allocated IP address without checking). And it had to be deployable without any complicated local DNS setups, router changes, etc.

I solved it by writing a discovery service... a wrapper that's accessible on a public (non-SSL) web page that basically opens a pile of hidden iframes and uses them to war dial local IP addresses until it finds the app and replaces the page's content with the winning frame's. Amazingly this janky thing has held up ;)

Anyway, nice work, and a cool idea!

detritus
0 replies
2h54m

It sounds like 'probably, yes' to adding a disclaimer, if only because I rather took it at face-value seeing it posted here on QBN so bookmarked for investigation later... .

briantakita
0 replies
2h34m

Love it! I think this idea has some legs in that a programmer can build their own f****k. Bundling only the pieces that they actually use. I don't see why it should not be used in a production environment...other than someone in the internet disapproves...a fear many of us suffer from. It's a simple idea & can be easily managed in a codebase.

In he spirit of breaking apart HTMX piece by piece, I created hyop (Hypermedia/Hydration Operation). It weighs in at 61 B but uses the "hyop" attribute. I know, I know, I'm bad...but at least I save bytes.

https://github.com/hyopjs/hyop

I'm going to use some of your concepts, with credit of course...like the snippetware idea among others.

bachmeier
0 replies
1h25m

I would fear if anyone wants to use this in production

Why? How would it be different from using htmx?

NelsonMinar
0 replies
2h2m

Very nicely done. Your intent was quite clear reading the site and code.

IggleSniggle
0 replies
1m

I don't see why you wouldn't want someone to use this in production. This is pretty close to the way it should have been all along.

recursivedoubts
1 replies
1h28m

I'm the creator of htmx and think this is a great library/snippet. Much closer to what htmx-like functionality in HTML would/should look like in that it is following existing norms (iframes, the target attribute) much more closely than htmx.

From a practical perspective, a lot of the bulk of htmx is bound up in things like history support, collecting inputs, a lot of callbacks/events to allow people to plug into things, etc. I expect a lot of htmx-like libraries will come out now that it has some traction: it's not a super complicated idea, and many of them will pick smaller, more targeted subsets of functionality to implement. That's a good thing: the ideas of hypermedia are more important than my particular implementation.

tambourine_man
0 replies
26m

Sorry if I came across as dismissive, htmx is a much needed counterpoint to React's dominance and a great contribution to the industry. And I hope its core idea (Ajax from HTML with results loading inside a target element) will be adopted as a Web standard.

naasking
0 replies
3h13m

HTML native ajax is the right approach, and what the htmx devs fully support if I understand correctly, but I don't think this demonstrates htmx is too much trouble for what it offers. It offers considerably more than what's possible here, eg. DOM morphing, animations, graceful degradation, rich event model, server side events, etc.

alexpetros
0 replies
3h14m

"Just a few attributes and we could avoid the iframe" could be the htmx/z motto

kickofline
5 replies
4h2m

At what point does it cease to be a framework and become just a regular line of code?

p4bl0
4 replies
4h0m

From the FAQ:

* Is htmz a library or a framework?

htmz is a snippet.
vcg3rd
2 replies
3h46m

From the README:

htmz is a minimalist HTML microframework

So, some ambiguity.

Kalabasa
1 replies
3h38m

Author here. to be honest I have no idea

joshfarrant
0 replies
3h36m

Finally, a Hacker News comment I can relate to.

alexpetros
0 replies
3h14m

Hah that's amazing

internet2000
4 replies
3h51m

Apparently it breaks your back button too.

rnmmrnm
3 replies
3h47m

If you're talking about the tabs demo, I think it's reasonable for some use cases to respect back button as previous tab. as long as it's easy to opt out.

troupo
2 replies
3h31m

The inline editing demo also has a separate URL for the "we're editing" state

Kalabasa
1 replies
3h5m

Yeah it's terrible in some use cases.

If only HTML provided a way to navigate <a> without adding a history entry, like <a nohistory href=...>.

If this was a real product i would market it as "Native time travel debugging! Go through your application state as you would go through your browser history!"

devmor
0 replies
2h44m

That would be terrible UX.

The real answer is that web developers should stop using anchor tags to target non-stateful links and should properly handle navigation to pages that are short lived.

But that battle is a bit like asking people to use their turn signals when merging.

hanniabu
3 replies
3h6m

Not even a backend is required.

In a nutshell, htmz lets you swap page fragments with HTML from the server using vanilla HTML code.

So a backend is needed....

Kalabasa
2 replies
2h55m

Oops, it's just a mistake on word choice in the nutshell summary. This works on static files like on a local filesystem (in that case the "server" is the local filesystem that serves me files that happen to be html)

Edit: on second thought, direct filesystem access has different origins which would mess with iframes. I'm not on the computer now to test. But at the very least you need a basic web server that serves files.

hanniabu
1 replies
2h3m

Thanks for the clarification, so it would work the same as a static site where you just need a place to retrieve the files from

turnsout
0 replies
1h28m

Yes, aka a webserver

spankalee
2 replies
2h58m

Reusing the <slot> element like this is a bad idea - it has very specific behavior in browsers. In a shadow root it'll be replaced by the children of the host element, no matter what the library does.

HTML already has an inert <output> element for things like this.

KatrinaKitten
0 replies
2h34m

Slight correction - <output> is not inert for users who use screen readers, though in this case it shouldn't cause issues. If you need an actual inert element, use a div.

Kalabasa
0 replies
2h52m

Thanks for the suggestion, I'll update the examples.

Edit: that is, after I wake up...

koliber
2 replies
1h47m

In 2001 or so, I was building an HTML based email client. We used a hidden iframe to execute JS to load data from the server and manipulate the DOM with the result. It was not quite as neat and elegant as this—the browser support was not there. However, the basic mechanism was the same.

It warms my heart to see the basic mechanism in such a compact package, without libraries upon libraries and machinations to make things work. This is probably perfect for 90% or so use cases where react or similar FE frameworks are used at the moment.

We later used to joke that we used Ajax before Ajax was a thing.

smrtinsert
0 replies
12m

I think I posted it before, but I had SPA using Spring Webflow running in dom nodes (no iframes required) with animation event handling, csrf, all back around 2006 or so. The calling html was also pure save for a jQuery include at the top and my app include. The backend used JSP. No back button issues, no client or server state (I used a db instead of some options webflow gives you), it was a dream. Completely lost on the company I worked for at the time. I was up and running with a new user flow, in half a day or so. Static blocks suddenly would "do stuff" from the perspective of the business team in about half a day.

This is the problem with technology. When it works well and really solves the problem, it is invisible. No one gets promoted for invisible.

LispSporks22
0 replies
1h22m

This brings back memories. We did the same thing with a giant Fortran 77 app turned CGI app. It was my first job, fun times.

synergy20
1 replies
2h23m

I happened to spend a little more time on htmx this weekend which htmz was inspired by.

htmx/htmz does do well for simple use cases, htmx does well for SSR heavy cases(e.g. django).

in the end I returned to vue.js, with a few lines code(put in a library) I can mimic htmx easily plus all the extra stuff vue.js brings, and no I do not need use a build tool for that, vuejs works fine via CDN inside a html for simple use cases the way htmx does, but vuejs can do more, e.g. draw live chart from data returned via ajax calls where vuejs is json by default, htmx is html by default instead.

angra_mainyu
0 replies
1h52m

This.

I think Vue.js "scales down" excellently. You can just load it via the cdn and write some widgets and go about your day.

In the past I've tried to make use of "microframeworks" like alpine.js and such but often found myself returning to Vue.js.

overstay8930
1 replies
3h18m

htmx in shambles /s

recursivedoubts
0 replies
1h26m

always has been

moritzwarhier
1 replies
2h42m

It's a fun one liner, but what is the use case?

When I want to replace some element using JS as the user clicks a link, it is progressive enhancement.

Usually links enable history navigation. If you do stuff like this, you need to code it in a way that uses the history API to fix it for users with JS enabled (majority of users).

If you don't want history navigation and URLs, why do you use links?

This breaks history navigation and bfcache for no good reason, or am I missing something? bfcache already provides SPA-like speed, or even better.

No need to avoid regular links if you e.g. link from a list to a detail page.

Also:

No preventDefaults. No hidden layers. Real DOM, real interactions. No VDOM, no click listeners. No AJAX, no fetch. No reinventing browsers.

So many words saying nothing, just to cater to some sentiment. fetch is part of browsers by the way.

If I need to replace an element as the user clicks a link, I can code it myself (without using this abstraction layer, however thin it is). I also don't need an iframe for doing this. And preventDefault is aptly named and a good reminder for what progressive enhancement should do. If it's not meant to be a link, don't use a link.

And if you want to react to clicks, you know, use click listeners (event handlers). Where's the problem?

It is understandable to developers and uses native browser functionality as intended. As opposed to this hack, which I'd find pretty glaring, bug-prone and hard to understand, would I have to debug an issue on some page that uses this snippet.

To me this seems like useless indirection and technical debt. If you really need low-code AJAX "links" (who says you need that, if you don't want an SPA?), code yourself some understandable JS that is properly tailored to your site and respects history navigation, or use a library that is a good fit for your concrete use case.

As a joke, I like it though…

scwoodal
0 replies
1h55m

The use case is a fun one liner.

keepamovin
1 replies
2h30m

This is great. I had an idea to use named iframes and targeted forms for simple, server-rendered pages with built-in style-scoped widgets, without leaning into complex JS client-side. But, I never simplified it well nor expressed a polished and elegant realization of that idea, as this htmz looks to me to be.

A reminder to never give up good ideas, focus on excellence, and focus on refinement to a completion of an idea, and communicate well!

Also the comments here:

- This is a great hack and shows how close the browser is to offering SPA natively.

- This is a glorious demonstration of someone really understanding the platform.

- Simple and powerful, as the vanilla web should be. Thank you for this (small) gem :)

- This is a neat hack, I like it :). Thanks for sharing.

are exactly what I hoped to hear reflected about my creation, and are totally on point for what this type of thing should be. Close to the web-grain, using the given material of the web in the best way possible. Fuck yeah! :)

Thank you for being a genius! :)

And for inspiring about what's possible! :)

P.S - also your communication and marketing skills are top notch! I think the way you have communicated this elegant technical thing, from the choice of name, API, examples, copy -- is just awesome. I learn from it! :)

cschep
0 replies
40m

thanks for a high quality top comment!

flanbiscuit
1 replies
2h6m

Was curious to see the code so found the GitHub. Posting it here in case anyone is interested since the author doesn't link to it on the site and also the npm page doesnt link to it either

https://github.com/Kalabasa/htmz

atahanacar
0 replies
2h1m

It is right at the end of the first sentence.

azornathogron
1 replies
3h25m

This is a glorious demonstration of someone really understanding the platform.

I don't expect I would ever use it, but I think it's excellent.

simplify
0 replies
1h18m

Understanding or not, certain decisions like overriding the semantic meaning of a hash in a url doesn't seem to be working with the platform. A better version would be adding a target to a `data-` attribute.

It's a fun project overall, though.

andrewmcwatters
1 replies
1h38m

Except using a URL fragment refers to a “resource that is subordinate to another, primary resource” not a destination. They point out the URL abuse, so why do it?

Slot is also a part of the custom elements standard, but they say no custom elements.

Why use only web standards and then use them incorrectly?

chuckadams
0 replies
1h9m

Why use only web standards and then use them incorrectly?

Because it's a clever hack, not a standards proposal. Lighten up, Francis.

Alifatisk
1 replies
4h6m

Kind of impressive that the installation script was that small.

turnsout
0 replies
1h30m

That’s not the installation script, it’s the entire “framework!”

yellowapple
0 replies
1h28m

One downside of this approach is that it fills my browser history with a bunch of extra entries, which ain't ideal (especially for my Back button). I'd guess that's probably fixable as an htmz "extension"?

That aside, I love the concept.

woah
0 replies
1h7m

Waiting for htmz on rails, the 100k loc batteries included htmz framework to implement full featured UX patterns and make development delightful

ulrischa
0 replies
1h37m

Me so: What? I looked at the code and it is really hacky. But so great

sunshinerag
0 replies
38m

Hi,

No babel plugin? Npm module… sheesh /s

sublinear
0 replies
2h43m

This seems likely to have issues with most "Content-Security-Policy" rules because of the inline script in "onload" and the iframe. Makes it a non starter in real world production environments.

spankalee
0 replies
2h12m

I think there's a pretty strong argument at this point for this kind of replacing DOM with a response behavior being part of the platform.

I think the first step would be an element that lets you load external content into the page declaratively. There's a spec issue open for this: https://github.com/whatwg/html/issues/2791

And my custom element implementation of the idea: https://www.npmjs.com/package/html-include-element

Then HTML could support these elements being targets of links.

sodimel
0 replies
4h4m

Simple and powerful, as the vanilla web should be. Thank you for this (small) gem :)

qwertygnu
0 replies
1h48m

ha, I'm working on a dev-side version similar to this (mostly just for me, but hopefully publishable). I opted for an entirely pre-deplopyment build tool, where you just put

  <custom-tag custom-param="value"></custom-tag>
in your HTML, run the build and it outputs the filled in file somewhere else. I know its functionality is very similar to many web frameworks (e.g. React, handlebars) but it does one thing.

p4bl0
0 replies
4h1m

This is a neat hack, I like it :). Thanks for sharing.

lyxsus
0 replies
1h23m

This is incredible. I really want it to take off.

lelanthran
0 replies
1h9m

Jesus Christ, this is all at once simple, powerful and useful.

So little code, achieving so much!!!

jdp
0 replies
3h49m

Reminds me of pjax [1], except pjax works over XHR instead of an iframe and uses pushState by default to keep the back button working.

[1]: https://github.com/defunkt/jquery-pjax

jallasprit
0 replies
35m

It's quite good. I noticed that my back button had to be repeatedly pressed to go back to write this comment, after interacting with the examples a few times. I'm sure that's simple enough to fix.

germandiago
0 replies
1h13m

How it compares to htmx?

franky47
0 replies
1h38m

If anyone is wondering, `htmy` is available on NPM, and `htmx` there is not what you think.

fractaledmind
0 replies
1h29m

I cannot believe how simple and elegant this is. Using an iframe as a request/response proxy to enable targeted replacement is just

d0utone
0 replies
4m

Refreshed 10 times to see the neat animation on top!

d0utone
0 replies
3m

Refreshed 10 times to see the neat animation on top again!

chuckadams
0 replies
1h13m

It's not my style, and I'll stick with Vue SPAs thanks, but still... damn this is elegant.

atum47
0 replies
1h45m

I'll take a deeper look in the code later, but it seems useful.

If been using the window location hash to do some simple navigation on my SPA, but i use JS. (Just hide all sections and shows the one that matches the hash i.e.: #main

_ix
0 replies
54m

This looks neat! I've never really been in to web development, but I'm curious... is it possible to create a standalone .html file for a browser-delivered app? Like, not just PWA or SPA, but... a single HTML App?

If I had modest amount of data in JSON baked into html, what's the barrier to something interesting, say... implementing a minimal spreadsheet or maybe just a sortable/filterable table?