Feeds: JSON Feed 1.1 at /feed.json, per-category and per-tag RSS at /categories/<name>/rss.xml and /tags/<name>/rss.xml alongside the main /rss.xml — all from a shared src/lib/feed.ts item source. Category/tag pages advertise their scoped feed via autodiscovery; new /feeds/ directory page (footer-linked) lists every feed with counts; RSS feeds gain an atom:link self reference and a feed.xsl stylesheet so they render readably in browsers. Programmatic readers: build-generated /llms.txt (site map with every review/bundle/post), SearchAction on the WebSite JSON-LD wired to /search/?q=, and a "For robots" section on /feeds/ documenting search.json, llms.txt, the sitemap, and JSON-LD coverage. Claude-Session: https://claude.ai/code/session_01WZaczDJjL3xZ3u5spsN5AL
80 lines
3.0 KiB
XML
80 lines
3.0 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
Browser-facing rendering for the site's RSS feeds. Feed readers ignore
|
|
this entirely; it only makes /rss.xml (and the per-category/per-tag
|
|
feeds) human-friendly when opened in a browser.
|
|
-->
|
|
<xsl:stylesheet version="1.0"
|
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:atom="http://www.w3.org/2005/Atom">
|
|
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
|
|
<xsl:template match="/rss/channel">
|
|
<html lang="en">
|
|
<head>
|
|
<title><xsl:value-of select="title"/> — feed</title>
|
|
<meta charset="UTF-8"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
<style>
|
|
body {
|
|
max-width: 42rem;
|
|
margin: 0 auto;
|
|
padding: 2rem 1.25rem;
|
|
background: #f4f0ec;
|
|
color: #1a1a1a;
|
|
font-family: ui-serif, Georgia, 'Iowan Old Style', serif;
|
|
font-size: 18px;
|
|
line-height: 1.55;
|
|
}
|
|
a { color: #b34700; text-decoration: none; }
|
|
a:hover { text-decoration: underline; }
|
|
.notice {
|
|
padding: 0.75rem 1rem;
|
|
background: #ebe6df;
|
|
border-radius: 6px;
|
|
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
font-size: 0.85rem;
|
|
color: #6b6b6b;
|
|
}
|
|
.notice code {
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
font-size: 0.9em;
|
|
}
|
|
h1 { font-family: ui-sans-serif, system-ui, sans-serif; letter-spacing: -0.015em; margin: 1.5rem 0 0.25rem; }
|
|
.tagline { margin: 0 0 2rem; font-style: italic; color: #6b6b6b; }
|
|
.item { margin: 0 0 1.5rem; }
|
|
.item h2 { margin: 0; font-size: 1.1rem; font-family: ui-sans-serif, system-ui, sans-serif; letter-spacing: -0.015em; }
|
|
.item p { margin: 0.2rem 0 0; }
|
|
.item .date {
|
|
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
font-size: 0.72rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: #6b6b6b;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<p class="notice">
|
|
This is an <strong>RSS feed</strong>. Copy this page's address into
|
|
your feed reader to subscribe. All feeds are listed at
|
|
<a href="/feeds/">/feeds/</a>.
|
|
</p>
|
|
<h1><xsl:value-of select="title"/></h1>
|
|
<p class="tagline"><xsl:value-of select="description"/></p>
|
|
<xsl:for-each select="item">
|
|
<div class="item">
|
|
<h2>
|
|
<a>
|
|
<xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute>
|
|
<xsl:value-of select="title"/>
|
|
</a>
|
|
</h2>
|
|
<p class="date"><xsl:value-of select="pubDate"/></p>
|
|
<p><xsl:value-of select="description"/></p>
|
|
</div>
|
|
</xsl:for-each>
|
|
</body>
|
|
</html>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|