--- import BaseLayout from '../layouts/BaseLayout.astro'; import Masonry from '../components/Masonry.astro'; import sourcesData from '../../sources.json'; import { getAllFinds } from '../lib/find-items'; import { sourceSlug } from '../lib/sources'; import { buildOgImage, buildBreadcrumbs, buildItemList, absoluteUrl, } from '../lib/seo'; type Source = { name: string; url: string; type: string; topics: string[]; cadence: string; notes: string; }; const topicLabels: Record = { 'macos-apps': 'macOS apps', 'apple-tips': 'apple tips', 'tools': 'tools', 'gifts': 'gifts', 'clothing': 'clothing', 'travel': 'travel', 'quotes': 'quotes', 'dad-jokes': 'dad jokes', 'general-delight': 'general delight', }; function host(url: string) { try { return new URL(url).hostname.replace(/^www\./, ''); } catch { return url; } } const allFinds = await getAllFinds(); const findsBySource = new Map(); for (const f of allFinds) { const arr = findsBySource.get(f.data.source) ?? []; arr.push(f); findsBySource.set(f.data.source, arr); } for (const arr of findsBySource.values()) { arr.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); } const sources: Source[] = [...sourcesData.sources].sort((a, b) => { const af = findsBySource.get(a.name) ?? []; const bf = findsBySource.get(b.name) ?? []; const aLatest = af[0]?.data.date.valueOf() ?? -Infinity; const bLatest = bf[0]?.data.date.valueOf() ?? -Infinity; if (aLatest !== bLatest) return bLatest - aLatest; if (af.length !== bf.length) return bf.length - af.length; return a.name.localeCompare(b.name); }); const lastUpdated = findsBySource.size ? new Date( Math.max( ...[...findsBySource.values()].map((arr) => arr[0].data.date.valueOf()) ) ) : undefined; 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 = { '@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/' }, ]); --- { sources.map((source) => { const recent = (findsBySource.get(source.name) ?? []).slice(0, 5); return ( ); }) }

โ† back