Show HN: JavaScript-free (X)HTML Includes (github.com)
(spoiler: its XSLT)
I've been working on a little demo for how to avoid copy-pasting header/footer boilerplate on a simple static webpage. My goal is to approximate the experience of Jekyll/Hugo but eliminate the need for a build step before publishing. This demo shows how to get basic templating features with XSL so you could write a blog post which looks like
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="/template.xsl"?>
<page>
<title>My Article</title>
<content>
some content
<ul>
<li>hello</li>
<li>hello</li>
</ul>
</content>
</page>
Some properties which set this approach apart from other methods: - no build step (no need to setup Jekyll on the client or configure Github/Gitlab actions)
- works on any webserver (e.g. as opposed to server-side includes, actions)
- normal looking URLs (e.g. `example.com/foobar` as opposed to `example.com/#page=foobar`)
There's been some talk about removing XSLT support from the HTML spec [0], so I figured I would show this proof of concept while it still works.[0]: https://news.ycombinator.com/item?id=44952185
See also: grug-brain XSLT https://news.ycombinator.com/item?id=44393817
24 comments
[ 3.4 ms ] story [ 51.8 ms ] threadGoogle have also asked for it to be removed from the standard [0].
[0] https://github.com/WHATWG/html/issues/11523
This looks like as good a place as any to show the XML/XSLT code that I've been tinkering with for the last couple of years: https://github.com/zmodemorg/wyrm.org
Even single page app frameworks have mostly solved this by doing the rendering on the server instead of making multiple round trips from the client. This feels like the no-JavaScript version of Spinnergeddon.
Does the browser wait for all the includes to resolve before showing the page or does it flicker in?
Unsurprisingly the idea did not take off, but I did find the XML/XSLT combination to be very interesting.
https://bawolff.net/css-website/index.xml is Evidlo's example but using a css stylesheet instead of xslt. I changed some of the text to explain what i was doing, but otherwise the XML is unchanged with one exception. Unfortunately you do have to put the <a> tags in the xhtml namespace to make them clickable. Other than that no changes to the xml.
Obviously there is a lot that xslt can do that css cannot, but when it comes to just display, CSS is an option here.
[0] https://github.com/Evidlo/xsl-website/blob/0dda1d82ce1eb01b7... [1] https://en.wikipedia.org/wiki/Identity_transform
// XSL $xsl_doc = new DOMDocument(); $xsl_doc->load("file.xsl");
// Proc $proc = new XSLTProcessor(); $proc->importStylesheet($xsl_doc); $newdom = $proc->transformToDoc($xml_doc);
// Output print $newdom->saveXML();
XSLT lacks functionality? No problem, use php functions in xslt: https://www.php.net/manual/en/class.xsltprocessor.php
There really never had been a need or call for browser devs to come up with idiosyncratic and overcomplicated solutions relying on JavaScript for such a simple and uncontroversial facility as a text macro which was part of every document/markup language in existance since the 1960s.
[1]: https://info.cern.ch/hypertext/WWW/MarkUp/MarkUp.html
It is 2025 and now we've got LLMs to write our code - that may actually be a strong argument in favor of keeping XSL(T): It is a useful browser mechanism and LLMs makes it easier to harvest.
Does anybody have experience with LLM-generated XSL(T)?
I used LLM (gpt o4-mini) for developing a blog template. Overall it did a good job especially with logic loops
Otherwise xml messes up its outputs sometimes
I had to reset my context window frequently
It would do a bad job troubleshooting large sections of code
My impression of XSLT's design is that there were partisan representatives from every popular programming language paradigm on the XSLT standard committee, and each one of them was able to get just enough to showcase what was special about their own paradigm into the standard, while strategically sabotaging all the other competing paradigms to undermine and beclown each other, but not enough for practical coherency, or lord forbid neatly dovetailing together into a synergistic design.
When the Lisp faction evals and applies their functional paradigm, the BASIC faction runs to goto their imperative paradigm, and the Prolog faction is horny and unified that its logical paradigm makes the cut, the result is dysfunctional emparitive illogical programming.
Jeff Atwood points out that "Martin Fowler hates XSLT too":
https://blog.codinghorror.com/martin-fowler-hates-xslt-too/
I have no problem with XML. It’s a fine way to store hierarchical data in a relatively simple, mostly human-readable format. But I’ve always disliked its companion technology, XSLT. While useful in theory – “using a simple XSLT transform, XML can be converted into anything!”– in practice, it takes painful contortions to do anything practical. Evidently I’m not alone; Martin Fowler hates XSLT too:
>All of this site is written in simple XML documents and transformed to HTML. I find this works really well, and means I never have to worry about dealing with HTML formats. (Not that fancy layout is my style, as you can tell.) I’ve even written a whole book that way.
>For most of this time I’ve used XSLT as my transformation language. I’ve got pretty good with slinging XSLT around and getting it to do what I want.
>But no more.
>When I wrote the software for this Bliki (on a long flight) I did it in Ruby. Prior to that I used Ruby to do a new version of my home page. My conclusion from this exercise was that using Ruby for XML transforms was much easier than using XSLT.
I’ve had almost the same exact argument with a few developers I used to work with. After working through a bit of the XSLT necessary to accomplish something, I concluded that it was easier and simpler to use procedural code to do the same thing. Not always, of course, but most of the time. As Fowler points out, this does beg the question: what good is XSLT?
I think this may raise some real questions about XSLT. There’s still much I like about the power of XSLT, but I hate the syntax and the walls you keep running into. I’m not going to convert my whole site over to Ruby tomorrow – most of the XSLT works fine - but I can certainly see my way to doing that at some point in the future. But the bigger question is whether you’re better off with scripting language for this kind of task than XSLT.
Maybe the idea of XSLT transforming XML into “anything” is fundamentally unrealistic – just more Write Once, Run Anywhere snake oil.
The reason XSLT is this way may be similar to why SQL is this way. SQL is declarative primarily because it isolates the user from concurrency. It would be much easier to write a procedure to fetch the data the way you want, but to write a concurrent procedure that does this safely and nicely among other such procedures would be much harder. XSLT was meant to be used with XML documents of unknown quality, so the logic of what is going on should be traceable. And XSLT did this rather well, given the constraints.
Upd: The constraints, as I see them, were that: the code will be written mostly by non-professionals (there were no professionals yet) so it should not be easy for them to get into an endless loop or otherwise shoot themselves in the foot. CSS faced similar constraints and was always rather awkward; nowadays it is also too complex and is only a formatting engine, not a transformation engine.
E.g. if XSLT was the main engine of the web CSS stylesheets would be unnecessary. The attributes could be placed on the elements themselves as this happens in XSL-FO. This would remove a major source of complexity; look at Tailwind, how popular it is, and why? Exactly because it removes an indirection step and instead of providing an external formatting rule merely formats an element directly.
Then it came SOAP and all the corporate suits and messed it all up into an extra complicated bloatness of anguish and suffering, but XML/XSLT were beautiful on their own (for data transformation, not web pages)