7 ms·
Show HN: JavaScript-free (X)HTML Includes
(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 https://news.ycombinator.com/item?id=44952185
See also: grug-brain XSLT https://news.ycombinator.com/item?id=44393817 https://news.ycombinator.com/item?id=44393817
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- shakna 1y agoAs of the next version of Chrome, XSLT will be gated behind a flag. Google have also asked for it to be removed from the standard [0]. [0] https://github.com/WHATWG/html/issues/11523 https://github.com/WHATWG/html/issues/11523
- kome 1y agoso it's time to use XSLT more
- notpushkin 1y agoYeah, I think that was what prompted this submission. All this has also reignited my idea for a compile-to-XSLT templating language, too – maybe I’ll get to it finally this time; definitely if XSLT 3.0 gets into web standards: https://github.com/whatwg/html/issues/11578 https://github.com/whatwg/html/issues/11578, https://news.ycombinator.com/item?id=44987552 https://news.ycombinator.com/item?id=44987552 Also, I’ve put together a simple XSLT playgroung a while ago! https://xsltbin.ale.sh/ https://xsltbin.ale.sh/
- Evidlo 1y agoI was thinking it would be possible to compile a subset of Jinja2 (or your favorite equivalent) into XSL: https://chatgpt.com/share/68a95439-ad54-800a-919f-23caecce4351 https://chatgpt.com/share/68a95439-ad54-800a-919f-23caecce43... Thanks for the playground! I'll check it out.
- bokchoi 1y agoI haven't tried it yet, but I came across this alternate syntax for XSLT which is much more friendly: https://github.com/Juniper/libslax/wiki/Intro https://github.com/Juniper/libslax/wiki/Intro
- SnuffBox 1y agoI find it bizarre that Google can just ask for a feature to be removed from standard and nobody bats an eye.
- notpushkin 1y agoIf I understand correctly, Mozilla and Apple don’t really want to support it either. And the reason for that is, the spec is still at XSLT 1.0, which is super old, and current implementations are effectively abandonware. Catch-22?
- ekianjo 1y agoThe spec is at XLST 3 right now.
- abraham 1y agoBrowsers only implement XSLT 1 https://meyerweb.com/eric/thoughts/2025/08/22/no-google-did-not-unilaterally-decide-to-kill-xslt/ https://meyerweb.com/eric/thoughts/2025/08/22/no-google-did-...
- ekianjo 1y agoWe were talking about the spec, not the implementation.
- JW_00000 1y agoWhen notpushkin said "the spec is still at XSLT 1.0", I think "the spec" is referring to the WHATWG HTML Living Standard spec, which only refers to XSLT 1.0. (It wouldn't make sense to say "the XSLT spec is at XSLT 1.0".)
- notpushkin 1y agoExactly. Thanks!
- 1y ago
- simpaticoder 1y agoIt's kind of too bad XSLT didn't take off. It is quite complex, until you compare it to the complexity of what now solves this problem (e.g. a build step with React and webpack and javascript absolutely required on the client-side). As the OP ably demonstrates, XSLT provides a declarative, non-javascript, non-build way to solve the basic HTML component problem. Perhaps a devastating 0-day in V8 will make us really, really want an alternative to the current best practice.
- shakna 1y agoWhilst I can't be certain, I've been hearing that part of Google's want to move away from XSLT is two-fold - and relates to the idea of the security problem. Partly, there's increasing attacks against XML. And also, libxml2 has said "no" to security embargoes altogether. [0] They might well consider there to be 0-days waiting in XSLT. [0] https://news.ycombinator.com/item?id=44381093 https://news.ycombinator.com/item?id=44381093
- AgentME 1y agoReact supports rendering to HTML ahead of time (SSR) which doesn't need any client-side javascript, and this is a prominent feature of most frameworks using React. This feature of React was one of its major innovations over many other front-end frameworks of the time.
- degamad 1y ago> React supports rendering to HTML ahead of time (SSR)... So does XSLT?
- throwaway290 1y agoLiterally not one person said XSLT can't do it. But in case you missed it somebody did said React can't do it and so XSLT is better. > build step with React and webpack and javascript absolutely required on the client-side This was a false statement. both XSLT and React can be used for this except React can additionally do a bunch of other stuff that does use JS and that XSLT can't do.
- chrismorgan 1y ago> As of the next version of Chrome, XSLT will be gated behind a flag. Citation? That would greatly surprise me in its abruptness and severity (they only just started talking about it this month, and acknowledge it’s particularly risky for enterprise) and https://chromestatus.com/feature/4709671889534976 https://chromestatus.com/feature/4709671889534976 gives no such indication.
- shakna 1y agoThe meeting referenced there, from March not last month, also gives no indication that they'd go ahead and make any moves - "stick a pin in it". But they did anyway. [0] panos: next item, removing XSLT. There are usage numbers. stephen: I have concerns. I kept this up to date historically for Chromium, and I don't trust the use counters based on my experience. Total usage might be higher. dan: even if the data were accurate, not enough zeros for the usage to be low enough. mason: is XSLT supported officially? simon: supported mason: maybe we could just mark it deprecated in the spec, to make the statement that we're not actively working on it. brian: we could do that on MDN too. This would be the first time we have something baseline widely available that we've marked as removed. dan: maybe we could offer helpful pointers to alternatives that are better, and why they're better. panos: maybe a question for olli. But I like brian's suggestion to mark it in all the places. dan: it won't go far unless developers know what to use instead. brian: talk about it in those terms also. Would anyone want to come on the podcast and talk about it? I'm guessing people will have objections. emilio: we have a history of security bugs, etc. stephen: yeah that was a big deal mason: yeah we get bugs about it and have to basically ignore them, which sucks brian: people do use it and some like it panos: put a pin in it, and talk with olli next time? panos: next thing is file upload control rendering [0] https://github.com/whatwg/html/issues/11146#issuecomment-2759059949 https://github.com/whatwg/html/issues/11146#issuecomment-275...
- magicalist 1y ago> But they did anyway. Did what? The GP asked for a citation for XSLT support going behind a flag in the next version of Chrome, but you forgot to add that. As best as I can tell, the GP is right and you're confused.
- basscomm 1y agoLooks promising! 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 https://github.com/zmodemorg/wyrm.org
- raggi 1y agoI used to do this in the 2000's era, there was a lot to love about it. At the time though the IE engines were far more complete and less buggy than others with various XML features.
- b_e_n_t_o_n 1y agoThis works client side right? So when a user navigates to this page, it recursively fetches content from the server? And if you have nested includes it would waterfall? 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?
- bawolff 1y agoLooking at the xslt stylesheet , it doesn't look like there are nested includes, its just one stylesheet which doesn't include anything else. So its not that different in terms of requests than how css would work.
- magicalist 1y ago> Looking at the xslt stylesheet , it doesn't look like there are nested includes, its just one stylesheet which doesn't include anything else At least the browser has to load template.xsl before it can know it has to load the css file though, right? And this is just a simple demo page.
- b_e_n_t_o_n 1y agoIt's making three round trips. The first is to get the original xml file, then it's to load the second xml file, then it's to load the stylesheet. Now you can imagine with a real site, you will have many includes per page, each one perhaps using includes of it's own. You end up with a really bad waterfall where it can take a long time for a page to load because it's going back to the server constantly, whereas if you did it on the server it would be a single round trip. Early SPA's did this, they would load a shell and then begin fetching from the client. Some still do but we know better than to do this for things that aren't web apps.
- Mikhail_Edoshin 1y ago
- xnx 1y agoWhy didn't HTML imports stick around? https://web.dev/articles/imports https://web.dev/articles/imports
- lloydatkinson 1y agoThe moronic Web Component cabal got their hands on it and trashed it by forcing it to rely on JavaScript, thus ensuring it would never get support.
- abraham 1y agoFor a long time web components generally built on four standards: - Custom HTML elements - Shadow DOM - HTML imports - HTML templates https://korban.net/posts/elm/2018-09-17-introduction-custom-elements-shadow-dom/ https://korban.net/posts/elm/2018-09-17-introduction-custom-... Eventually it became clear some browsers were not going to implement and the design of HTML imports was better handled be ES modules. https://webmasters.stackexchange.com/questions/127482/on-what-specific-grounds-were-html-imports-rejected-deprecated-and-removed https://webmasters.stackexchange.com/questions/127482/on-wha...
- bapak 1y agoFound this, it should answer your complaints: > HTML Imports were redundant, since you need JavaScript to bring them alive anyways
- thayne 1y agoExactly. I think the problem wasn't that browsers (specifically Firefox and Safari) were opposed to the idea of html includes in general, but they didn't like the specific proposal, in large part because it still required javascript, and added a lot of complexity for little to no benefit. I think rejecting that proposal was the right thing to do. What disappoints me is that there hasn't been a more declaritive, simpler proposal that has gotten anywhere.
- xnx 1y ago
- RebeccaTheDev 1y agoThree jobs ago I worked for a company that did e-learning systems for industrial clients. This was roughly 2004. One of the company owner's many ideas was a technical documentation system based on XML and XSLT. The "idea" being that technical writers or SMEs would rather write XML than, you know, use a word processor. Unsurprisingly the idea did not take off, but I did find the XML/XSLT combination to be very interesting.
- the_other 1y agoBetween 2000 and 2003 I worked for a company that produced corporate training materials (initially on CDROM, later as learning-management-system units). We had a system which allowed the content authors to write in structured Word files. VBA would create XML of the Word files, and XSLT would create the HTML. I mostly worked in the XSLT and JS/CSS layers, not on the XML generation layer. It was my first job out of uni and I found XSLT fascinating and slightly psychedelic.
- Telemakhos 1y agoIs this DITA? I always wondered who actually used that. XSLT is also big in the TEI community in digital humanities. TEI gives a structured markup for reproducing printed volumes, which is important when you are dealing with variants of the same text, like revised editions of a text. XSLT lets you turn your TEI file into a web page for humans to read.
- prettyman 1y ago[dead]
- OCTAGRAM 1y agoThe most advanced usage of XSLT I've seen was in YBlog2, YML and YSLT, an alternative syntax for XML and XSLT. And IIUC they did not rely on browser-side although that may be still possible.
- bawolff 1y agoSince this seems to be about the recent proposal to remove xslt, i'd point out you can do the same thing with CSS https://bawolff.net/css-website/index.xml 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.
- 8organicbits 1y ago> there is a lot that xslt can do that css cannot This latter part is why I've reached for XSLT in the past. Most recently was to convert an RSS feed into a styled page with instructions at the top. Templates and xpath can really transform a document.
- Evidlo 1y agoThanks for the CSS example. By the way, the advanced/ folder has a slightly more complicated example that demonstrates template inheritance and "slots".
- bawolff 1y agoYeah, i saw. Unfortunately the advanced example wouldn't be doable in CSS. I suppose i'm being a bit intellectually dishonest to not explicitly point that out.
- Pxtl 1y ago> i'd point out you can do the same thing with CSS Cool when are they removing CSS from the standard?
- egeozcan 1y agoThis is really, definitely cool, but it's important to remember that content added via CSS is purely decorative. It can't be interacted with, which is a major issue for assistive technologies like screen readers.
- mgr86 1y agoA small comment for anyone new to xslt. The author references a wildcard rule in the comments [0]. While that is true, they are calling an identity transformation [1]. Identity transformations are very common in xslt. [0] https://github.com/Evidlo/xsl-website/blob/0dda1d82ce1eb01b725566f9672043674d25328a/template.xsl#L27-L34 https://github.com/Evidlo/xsl-website/blob/0dda1d82ce1eb01b7... [1] https://en.wikipedia.org/wiki/Identity_transform https://en.wikipedia.org/wiki/Identity_transform
- ulrischa 1y agoTo overcome the two problems here (client side loading the template and ending browser support) you could throw in php in the mix and have a wonderful solution for templating with bullet proof standards: // XML $xml_doc = new DOMDocument(); $xml_doc->load("file1.xml"); // 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 https://www.php.net/manual/en/class.xsltprocessor.php
- Telemakhos 1y agoWhat you're describing is basically Symphony, the CMS built around XSLT with some PHP and MySQL to glue things together: https://github.com/symphonycms/symphonycms https://github.com/symphonycms/symphonycms I don't think it's been updated since 2019. XSL was really powerful, but it had a steep learning curve, and I think server-side PHP and client-side JS were just more intuitive.
- ulrischa 1y agoCool project. Sadly it seems to be unmaintained
- tannhaeuser 1y agoThis is how the simplest variant of SGML (or XML) entities have worked since 1986: <!doctype html [ <!entity e system "e.html"> ]> <html> <title>Hello, world!</title> <p>The content of e is: &e;</p> </html> HTML was envisioned as an SGML vocabulary from day one. That SGML's document composition and other facilities were used only at authoring time and not directly supported by browsers was merely due to the very early stage of the first browser software ([1]) which directly mentions SGML even, just as HTML specs have presented HTML as a language for authoring and not just delivery since at least version 4. 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 https://info.cern.ch/hypertext/WWW/MarkUp/MarkUp.html
- myfonj 1y agoI wish external entities were enabled in browsers (*), and not entirely disabled, like they are now. In the OP scenario, it would provide possibility to have header/footer/stylesheet content in separate files and get system working that does not rely on absolute path of the CSS. (*) Naturally, just with few minimal directory traversal precautions; basically anything like "no ../" and even restriction like "referenced resource filename must begin with referencing XSL filename" would be fine for me.
- DonHopkins 1y agoXULRunner (Firefox, Thunderbird, Songbird, Miro, Joost, TomTom Home, etc) abused XML external entities in language specific DTDs for internationalization / localization. https://www-archive.mozilla.org/projects/intl/iuc15/paper/iuc15xul.doc https://www-archive.mozilla.org/projects/intl/iuc15/paper/iu... https://en.wikipedia.org/wiki/XULRunner https://en.wikipedia.org/wiki/XULRunner
- the_mitsuhiko 1y ago> This is how the simplest variant of SGML (or XML) entities have worked since 1986: In theory. In practice not a single browser had an actual SGML parser and that was never supported.
- msylvest 1y agoI remember admiring the intent of XSLT when it was born. And how difficult it turned out to be to write; using XML framing makes it terse/verbose/arcane, eg. when compared to the compactness of regex/subs. 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)?
- reacweb 1y agoI have 1 "big" xsl file in a project I maintain. I have fixed an issue this year. I have tried to use chatgpt prompt. The scope was perfect: I had the buggy xsl, the buggy result, the expected result and a clear explanation. It generated syntactically correct code (almost) that did not work because chatgpt does not understand. This was not a complete loss: a good refresher of the syntax, but I had to do the thinking fully alone and found alone how to use "node-set". My previous change in this file was in 2017 when I replaced xalan by the xslt processor built in java. I was very surprised I had to make the following changes: -<xsl:if test="string(serverName)=$sName"> +<xsl:if test="string(serverName)=string($sName)"> -<xsl:for-each select="attributeList/attribute[self::attribute!='']"> +<xsl:for-each select="attributeList/attribute[text()!='']"> -<xsl:if test="preceding-sibling::Connection[featureType='Receptacle'][position() = 1]/@Name!=@Name or not(preceding-sibling::Connection[featureType='Receptacle'][position() = 1]/node()) "> +<xsl:if test="preceding-sibling::Connection[position() = 1]/@Name!=@Name or position()=1"> These incompatibility issues with something I considered to be standard greatly damaged my opinion on xslt.
- vgr-land 1y agohttps://news.ycombinator.com/item?id=45006098 https://news.ycombinator.com/item?id=45006098 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
- postepowanieadm 1y agoCan we have xml/xhtml back? It makes perfect sense in the age of LLMs.
- cranberryturkey 1y agoI'm bummed that w3c dropped xslt
- em-bee 1y agothis is exactly how i built my site with help of a fellow HNer: https://news.ycombinator.com/item?id=44966886 https://news.ycombinator.com/item?id=44966886
- mjaniczek 1y agoReminds me of Symphony CMS, which is XSLT based. Cool concept but not entirely practical in my experience.
- ulrischa 1y agoCool project. Sadly it seems to be unmaintained
- DonHopkins 1y agoWhat's the whole point of bending over backwards to be "JavaScript-free" when the chosen alternative is using something as half-assedly hamstrung and counterintuitively crippled and mind-bogglingly rube-goldbergesque as XSLT, that tries to be all things to all people, thus satisfying no-one? 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/ 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.
- Kuyawa 1y ago20 years ago I saw the greatness of xml and xslt as I was coming from the painful inferno of an EDI shop. There is nothing more beautiful than sending plain data to a client and being able to see the whole document without any extra bloating, that's what XSLT was intended for: <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="/invoice.xsl"?> <invoice> <date>2025-08-23</date> <customer> <name>John Doe</name> <address> <line>123 Sunny Boulevard</line> <city>Miami</city> <state>FL</state> <zip>33133</zip> </address> </customer> <items> <item> <code>123456</code> <description>Some Apple gadget</description> <quantity>1</quantity> <price>1234.56</price> <total>1234.56</total> </item> <item>more items...</item> </items> </invoice> That piece of data would be sent to millions of customers and they could open it and the XML was transformed in an invoice perfectly formatted for human consumption. Both flesh and silicon were living happy in perfect harmony. 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)
- Kuyawa 1y agoIf we extrapolate it all to JSON, all we need to do is add two lines to the data file to reference the JSLT source and then use any templating system as default (ejs, mustache, handlebars) to do the transformation in the browser { "JSLT": "1.0", "style": "/invoice.jsl", "data": { "invoice":{ "date": "2025-08-23", "customer": { "name": "John Doe", "address": { "line": "123 Sunny Boulevard", "city": "Miami", "state": "FL", "zip": "33133", }, }, "items": [ { "code": "123456", "description": "Some Apple gadget", "quantity": "1", "price": "1234.56", "total": "1234.56", }, { "code": "123457", "description": "Another Apple gadget", "quantity": "1", "price": "1234.57", "total": "1234.57", } ] } } } Then the JSLT file: <html> <body> <h2>Invoice</h2> <p><label>Date</label> <span><%=data.invoice.date%></span></p> <div> <h3>Customer</h3> <p><%=data.invoice.customer.name%></p> <p> <%=data.invoice.customer.address.line%> <%=data.invoice.customer.address.city%> <%=data.invoice.customer.address.state%> <%=data.invoice.customer.address.zip%> </p> </div> <table> <tr> <th>Code</th> <th>Description</th> <th>Quantity</th> <th>Price</th> <th>Total</th> </tr> <% for(item of invoice.items) { %> <tr> <td><%=item.code%></td> <td><%=item.description%></td> <td><%=item.quantity%></td> <td><%=item.price%></td> <td><%=item.total%></td> </tr> <% } %> </table> </body> </html> Then we could get rid of XSLT