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:
+41
-12
@@ -2,6 +2,12 @@
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import sourcesData from '../../sources.json';
|
||||
import { getAllFinds } from '../lib/find-items';
|
||||
import {
|
||||
buildOgImage,
|
||||
buildBreadcrumbs,
|
||||
buildItemList,
|
||||
absoluteUrl,
|
||||
} from '../lib/seo';
|
||||
|
||||
type Source = {
|
||||
name: string;
|
||||
@@ -40,14 +46,43 @@ for (const f of allFinds) {
|
||||
arr.push(f);
|
||||
findsBySource.set(f.data.source, arr);
|
||||
}
|
||||
|
||||
const lastUpdated = allFinds.sort(
|
||||
(a, b) => b.data.date.valueOf() - a.data.date.valueOf()
|
||||
)[0]?.data.date;
|
||||
|
||||
const description = `The ${sources.length} feeds, shops, and forums Unique draws daily picks from.`;
|
||||
const ogImage = buildOgImage(undefined, 'site', 'Unique sources catalog');
|
||||
|
||||
const itemList = buildItemList(
|
||||
sources.map((s) => ({ url: s.url, name: s.name })),
|
||||
'Sources used by Unique'
|
||||
);
|
||||
|
||||
const collectionPage: Record<string, unknown> = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'CollectionPage',
|
||||
'@id': absoluteUrl('/sources/#collection'),
|
||||
name: 'Sources — Unique',
|
||||
description,
|
||||
url: absoluteUrl('/sources/'),
|
||||
inLanguage: 'en-US',
|
||||
};
|
||||
|
||||
const breadcrumbs = buildBreadcrumbs([
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Sources', url: '/sources/' },
|
||||
]);
|
||||
---
|
||||
|
||||
<BaseLayout title="Sources" wide>
|
||||
<div class="intro">
|
||||
<h1>Sources</h1>
|
||||
<p>Where the daily picks come from. {sources.length} feeds, shops, and forums.</p>
|
||||
</div>
|
||||
|
||||
<BaseLayout
|
||||
title="Sources"
|
||||
description={description}
|
||||
subheader={`Where the daily picks come from. ${sources.length} feeds, shops, and forums.`}
|
||||
lastUpdated={lastUpdated}
|
||||
ogImage={ogImage}
|
||||
jsonLd={[collectionPage, itemList, breadcrumbs]}
|
||||
>
|
||||
<ul class="grid">
|
||||
{
|
||||
sources.map((source) => {
|
||||
@@ -93,12 +128,6 @@ for (const f of allFinds) {
|
||||
<p class="back"><a href="/">← back</a></p>
|
||||
|
||||
<style>
|
||||
.intro {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.intro h1 { margin: 0 0 0.25rem; font-size: 1.85rem; }
|
||||
.intro p { margin: 0; color: var(--muted); }
|
||||
|
||||
.grid {
|
||||
column-count: 3;
|
||||
column-gap: 1rem;
|
||||
|
||||
Reference in New Issue
Block a user