site: ui/ux refresh, seo pass, find/lists indexes, 25 new finds

- newspaper-style masthead (stats | "Unique" | About/Blog) on every page
  with per-page italic subheader + last-updated date on listing pages;
  sitewide 42rem reading width
- pinterest home (hero + masonry, "load more"); old list view at /index3/
- new pages: /about, /blog, /legal, /find/, /finds/, custom 404
- footer collection links now clickable; "founded" stat replaces "updated"
  in the masthead
- centralised SEO component with per-page json-ld (Review, BlogPosting,
  Product, Article, CollectionPage, ItemList, BreadcrumbList, etc.);
  @astrojs/sitemap + @astrojs/rss; robots.txt; promoted finds canonical
  to their review
- memoize getSiteStats() so the masthead/footer counts don't multiply
  per-page build cost
- 25 new daily-finds captures
This commit is contained in:
2026-05-03 16:58:23 -04:00
parent c184f3f50a
commit c8095d2766
54 changed files with 2337 additions and 95 deletions
+79 -2
View File
@@ -4,6 +4,12 @@ import BaseLayout from '../../layouts/BaseLayout.astro';
import SourceBadge from '../../components/SourceBadge.astro';
import Backlinks from '../../components/Backlinks.astro';
import { findsReferencing } from '../../lib/backlinks';
import {
resolveExternalLink,
AFFILIATE_REL,
AFFILIATE_DISCLOSURE,
} from '../../lib/affiliate';
import { buildOgImage, buildBreadcrumbs, absoluteUrl } from '../../lib/seo';
export async function getStaticPaths() {
const items = await getCollection('find');
@@ -25,11 +31,53 @@ const fmt = new Intl.DateTimeFormat('en-US', {
const linkLabel =
item.data.linkText ?? new URL(item.data.link).hostname.replace(/^www\./, '');
const external = resolveExternalLink(item.data.link);
const description =
item.data.description ?? item.data.subtitle ?? `A find: ${item.data.name}.`;
const canonicalOverride = item.data.promotedTo
? absoluteUrl(`/reviews/${item.data.promotedTo}/`)
: undefined;
const ogImage = buildOgImage(
item.data.promotedTo,
'finds',
`${item.data.name} preview image`
);
const productSchema: Record<string, unknown> = {
'@context': 'https://schema.org',
'@type': 'Product',
'@id': absoluteUrl(`/find/${item.id}/#product`),
name: item.data.name,
description,
url: absoluteUrl(`/find/${item.id}/`),
image: ogImage.url,
offers: {
'@type': 'Offer',
url: item.data.link,
availability: 'https://schema.org/InStock',
},
};
const breadcrumbs = buildBreadcrumbs([
{ name: 'Home', url: '/' },
{ name: 'Sources', url: '/sources/' },
{ name: item.data.name, url: `/find/${item.id}/` },
]);
---
<BaseLayout
title={item.data.name}
description={item.data.description ?? item.data.subtitle ?? item.data.name}
description={description}
ogType="article"
ogImage={ogImage}
canonicalOverride={canonicalOverride}
publishedTime={item.data.date}
articleTags={item.data.tags}
jsonLd={[productSchema, breadcrumbs]}
>
<article>
<p class="source-line"><SourceBadge source={item.data.source} /></p>
@@ -49,11 +97,20 @@ const linkLabel =
</div>
<p class="external">
<a href={item.data.link} target="_blank" rel="noopener noreferrer">
<a
href={external.href}
target="_blank"
rel={external.isAffiliate ? AFFILIATE_REL : 'noopener noreferrer'}
>
{linkLabel} ↗
</a>
{external.isAffiliate && <span class="aff-badge">Affiliate</span>}
</p>
{external.isAffiliate && (
<p class="aff-disclosure">{AFFILIATE_DISCLOSURE}</p>
)}
{
item.data.promotedTo && (
<p class="promoted">
@@ -112,6 +169,26 @@ const linkLabel =
font-size: 0.95rem;
}
.external a:hover { text-decoration: none; opacity: 0.9; }
.aff-badge {
display: inline-block;
margin-left: 0.6rem;
padding: 0.15rem 0.5rem;
font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--muted);
background: var(--rule);
border-radius: 999px;
vertical-align: middle;
}
.aff-disclosure {
margin: 0.6rem 0 0;
font-size: 0.78rem;
color: var(--muted);
font-style: italic;
}
.promoted {
margin: 1.5rem 0 0;
padding: 0.85rem 1rem;