Files
unique/src/pages/feeds.astro
T
rzen ff4c6959a5 site: tag pages include finds; find-only tags get pages
Tag pages are now generated from the union of entry and find tags —
1,179 tags that existed only on finds (most tag links on find pages)
previously 404'd. Tagged finds render in a compact secondary "Finds"
list below the entry grid, keeping the editorial tier on top. Find-only
tag pages with fewer than 3 finds are noindexed until they fill out.
Tag feeds stay entries-only; the RSS pill and autodiscovery link only
render where a feed exists. Category pages unchanged (finds have no
category).

Claude-Session: https://claude.ai/code/session_01WZaczDJjL3xZ3u5spsN5AL
2026-07-12 19:05:46 -04:00

151 lines
3.9 KiB
Plaintext

---
import BaseLayout from '../layouts/BaseLayout.astro';
import { getFeedCategories, getFeedTags } from '../lib/feed';
import { buildOgImage, buildBreadcrumbs, absoluteUrl } from '../lib/seo';
const categories = await getFeedCategories();
const tags = await getFeedTags();
const description =
'Subscribe to Unique: RSS and JSON feeds for everything, plus per-category and per-tag feeds.';
const ogImage = buildOgImage(undefined, 'site', 'Feeds on Unique');
const collectionPage = {
'@context': 'https://schema.org',
'@type': 'CollectionPage',
'@id': absoluteUrl('/feeds/#collection'),
name: 'Feeds — Unique',
description,
url: absoluteUrl('/feeds/'),
inLanguage: 'en-US',
};
const breadcrumbs = buildBreadcrumbs([
{ name: 'Home', url: '/' },
{ name: 'Feeds', url: '/feeds/' },
]);
---
<BaseLayout
title="Feeds"
description={description}
subheader="Take Unique with you."
ogImage={ogImage}
jsonLd={[collectionPage, breadcrumbs]}
>
<h1>Feeds</h1>
<p>
Everything published here — reviews, bundles, posts — is available as a
feed. Paste any of these into your feed reader.
</p>
<h2>Everything</h2>
<ul class="feed-list">
<li>
<a href="/rss.xml">/rss.xml</a> — all entries, RSS 2.0
</li>
<li>
<a href="/feed.json">/feed.json</a> — all entries,
<a href="https://jsonfeed.org/">JSON Feed 1.1</a>
</li>
</ul>
<h2>By category</h2>
<p class="hint">Each category page also advertises its own feed for autodiscovery.</p>
<ul class="feed-list scopes">
{categories.map(({ name, count }) => (
<li>
<a href={`/categories/${name}/`}>{name}</a>
<span class="count">({count})</span>
<a class="rss" href={`/categories/${name}/rss.xml`}>RSS</a>
</li>
))}
</ul>
<h2>By tag</h2>
<ul class="feed-list scopes">
{tags.map(({ name, count }) => (
<li>
<a href={`/tags/${name}/`}>#{name}</a>
<span class="count">({count})</span>
<a class="rss" href={`/tags/${name}/rss.xml`}>RSS</a>
</li>
))}
</ul>
<h2>For robots</h2>
<p>Reading the site programmatically? You may also want:</p>
<ul class="feed-list">
<li>
<a href="/search.json">/search.json</a> — the full index of everything on
the site as JSON, including individual finds (which don't appear in the
feeds — they surface through bundles)
</li>
<li>
<a href="/llms.txt">/llms.txt</a> — a plain-text map of the site for
language models and other tools
</li>
<li>
<a href="/sitemap-index.xml">/sitemap-index.xml</a> — every page, for crawlers
</li>
<li>
Every page embeds schema.org JSON-LD (<code>Review</code>,
<code>Product</code>, <code>Article</code>, <code>CollectionPage</code>…)
</li>
</ul>
<style>
h2 {
margin-top: 2.25rem;
font-size: 1.15rem;
}
.hint {
margin: 0.25rem 0 0.75rem;
font-size: 0.85rem;
color: var(--muted);
font-style: italic;
}
.feed-list {
margin: 0.5rem 0 0;
padding-left: 1.25rem;
}
.feed-list li {
margin: 0.3rem 0;
}
.feed-list.scopes {
list-style: none;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.35rem 1.4rem;
}
.feed-list.scopes li {
margin: 0;
white-space: nowrap;
}
.count {
margin-left: 0.25rem;
font-size: 0.8rem;
color: var(--muted);
}
.rss {
margin-left: 0.45rem;
padding: 0.05rem 0.4rem;
font-family: ui-sans-serif, system-ui, sans-serif;
font-size: 0.66rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
background: var(--rule);
color: var(--muted);
border-radius: 999px;
vertical-align: middle;
}
.rss:hover {
color: var(--accent);
text-decoration: none;
}
</style>
</BaseLayout>