AI translation notice: This English version was translated from the original Chinese article with AI assistance. Some nuances may differ from the original.
TLDR:
Back in March, while I was building this site piece by piece, I got to the RSS subscription part and added a styling scheme to the XML file. I was quite pleased with it. Then, just two days later, the page that had been rendering just fine was suddenly down to nothing but the XML document tree again. Later I asked about it in Zhilu's blog community group chat, and Zhilu pointed me to Mayx's “XML Beautification After Google Killed XSLT”. After reading it, I rethought how RSS, Atom, and browser rendering relate to one another, and that is how the current version came to be.
Why Beautify RSS at All
Every blog should have a subscription entry point.
Blog posts usually live on a personal site. You can of course read a web page at your own pace, but if someone wants to follow what you publish over the long term, they have to open your site every so often. If the reader uses an RSS reader, though, new posts appear in their subscription list automatically, and there is no need to open the site every day just to check for updates.
Sounds great, does it not?
But for someone who is not familiar with feeds, opening one and seeing a bare XML file would probably leave them baffled. So I figured: since a feed is meant for people to look at, I might as well make it look like a page while I am at it.
And as for which of the two images below is the more intuitive one, that needs no explanation.
The First Version
This happened in early March, around the time the site first went live—the same stretch when I had just started adding subscription features. Looking back now, the Git history records it pretty clearly:
- February 28: added the feed dependency package and created the script generate-rss.js to automatically generate RSS, Atom, and JSON Feed files from the posts under the content/posts directory
- March 1: hooked up both RSS and Atom first, so posts could automatically produce feed files.
- Evening of March 1: added XSLT to the RSS feed for the first time.
- March 2: tried using
markdown-itto convert post content into HTML, and added cover images, summaries, and subscription links along the way. - Afternoon of March 2: unified the feeds on Atom (it felt like the easiest to implement and the most broadly compatible option, with JSON Feed as a possible follow-up (added on 2026.10.4)), and moved the files into the
/feeds/directory. - March 4: added a subscription page with cards, a background image, and a pop-up preview, so opening
/feeds/in a browser no longer gave you dry, bare XML.
My thinking at the time was the same as most blogs that style their feeds:
The script reads the posts under content/posts and generates an Atom file; the Atom file references atom.xsl at the top; after the browser receives the XML, XSLT transforms it into an HTML page with cover images, summaries, and dates.
The result was simple and effective, so I merged it into the site quickly.
I thought the whole thing was finally done.
I was pretty happy the first time I saw it working. Click the RSS button below, open the feed link, and instead of a dense forest of XML you got a page that looked a lot like the style of my blog.
And right about then, the plot twist I had coming arrived anyway.
The Styling Scheme Suddenly Stops Working
A few days later, I opened the feed link again, ready to admire my handiwork and see what else could be polished, only to find that the page I had built was gone.
All that was left in the browser was the bare XML file. At first I assumed it was my own fault—maybe while I kept updating the site's content I had accidentally touched the script, or maybe, being up late, I had carelessly changed something in the script and broken the styled page. Then I wondered whether vibe-coding certain pages had caused Vercel to get the Atom MIME type wrong.
Following my own experience and the possibilities the AI suggested, I checked the stylesheet path, the response headers, and the build output, and re-confirmed whether the XML file still had the xml-stylesheet instruction. Each piece looked right on its own, but put together, it just would not work. The styled page rendered in my local dev environment, but not in Chrome online.
After that I adjusted it many times (I even ran an ablation experiment), pushed several commits, and nothing worked 😭. That was when I decided to ask the veterans in the group chat.
Help from the Veterans
So I went to Zhilu's blog community group chat and asked. My description was simple: the styling on my RSS feed seems to have stopped working—do any of you know where the problem might be?
In less than five minutes, Zhilu dropped a link to Mayx's article: “XML Beautification After Google Killed XSLT”, saying that Mayx had just written something about exactly this and I should take a look.
That article answered my question outright: Chrome plans to deprecate XSLT. So the reason my styling suddenly stopped working was not me—it was that the browser no longer supported it after an update.
Mayx's post explains the specifics far better than I could, so there is no need for me to belabor it. I will quote it here:
From the Chrome deprecation document above, you can see that the person behind this is Mason Freed, who filed an Issue in the WHATWG. Because very few people use XSLT, and the libraries that implement it are old and prone to vulnerabilities, he proposed removing XSLT from the web standards. In that Issue, you can see that plenty of people object—after all, this feature is still very useful for bloggers who want to style their own feeds. To fight Google, someone even built a website: https://xslt.rip.
And although XSLT's share of users may not be high, the total number should still be fairly large. Beyond styling blog feeds with XSLT, some even use XSLT as a blog framework, and others pointed out that some government websites use XSLT too.
But Freed seems to have been prepared for this. He built a Polyfill library that lets XSLT work properly through WASM. To make the library easier for everyone to use, I went ahead and sent a PR to CDNJS, so it can be referenced from a CDN from now on. The catch is that using the library requires adding a snippet of JS to the feed. My blog's Atom feed uses the jekyll-feed plugin, where the format is all hard-coded, so I could not use it…
It is just that there is no way to stop Google now… and other browsers have said they will follow suit, so it seems the only thing we can do is adapt.
And that post did more than explain the cause—it also proposed two alternative routes: pure CSS, and mixing XHTML into the XML.
Pure CSS can arrange the tags into something nicer looking, but it cannot really manipulate the document content, and it is not easy to give posts proper hyperlinks; mixing in XHTML fills those gaps, but XML is still XML, its DOM behavior is not entirely the same as HTML's, and it also triggers warnings like Misplaced XHTML content in validators.
After reading it, I figured: if XSLT is going to lose support in the end and the tide cannot be turned, there is nothing I can do about it. So I might as well write my own generation script and produce standalone HTML pages myself.
How the Current Version Works
The site now uses Atom as its primary feed format, with the feed addresses under the /feeds/ directory. The generation script generate-rss.js handles a few things:
- Recursively read posts.
- Parse the language, slug, date, summary, and cover image.
- Generate Atom for each language.
- Also generate standalone static HTML pages, and copy the Atom, HTML, and XSL files into dist together.
This approach may look a little inelegant, but at least it separates browser preview from RSS subscription. Even if every browser drops XSLT support in the future, static HTML pages like /feeds/zh/ and /feeds/en/ will still be reachable, and RSS readers can still subscribe to the corresponding Atom XML. Of course, I did not delete the .xsl files entirely—I thought I would keep them around, since it was once an extremely efficient transformation method on the internet.
You can also see what the XSL styling looks like here.
A Few Reflections
This bug hunt left a deep impression on me, and I am grateful for the veterans' generous sharing. It also shows that when a new feature changes and the AI has no relevant experience from its training, it cannot quickly pinpoint the cause of the bug. Maybe this is also a bit of proof that blogs still have some value in the AI era: only if people keep sharing on the internet can AI get enough information, and only then can it better help more people.
At the same time, I regret the disappearance of XSLT as a technology. On https://xslt.rip, a site made by a blogger I follow, you can see that many people are still holding on, wanting to preserve the tech stack they are used to. But which way the wheel of history will turn, we can only wait and see.
- Author:Mark Xu
- Copyright:All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating otherwise.

