import { heroes } from './hero'; import type { OgImage } from '../components/SEO.astro'; export type OgFallback = 'reviews' | 'bundles' | 'posts' | 'site'; const SITE_URL = 'https://unique.rzen.dev'; const FALLBACK_PATHS: Record = { reviews: '/og/reviews.png', bundles: '/og/bundles.png', posts: '/og/posts.png', site: '/og/default.png', }; const FALLBACK_DIMS = { width: 1200, height: 630, type: 'image/png' }; export function buildOgImage( heroId: string | undefined, fallback: OgFallback, alt: string ): OgImage { const hero = heroId ? heroes[heroId] : undefined; if (hero?.kind === 'image') { const fmt = hero.src.format; const mime = fmt ? `image/${fmt === 'jpg' ? 'jpeg' : fmt}` : undefined; return { url: new URL(hero.src.src, SITE_URL).href, width: hero.src.width, height: hero.src.height, alt, type: mime, }; } return { url: new URL(FALLBACK_PATHS[fallback], SITE_URL).href, width: FALLBACK_DIMS.width, height: FALLBACK_DIMS.height, alt, type: FALLBACK_DIMS.type, }; } export function absoluteUrl(path: string): string { return new URL(path, SITE_URL).href; } export type Crumb = { name: string; url: string }; export function buildBreadcrumbs(crumbs: Crumb[]): Record { return { '@context': 'https://schema.org', '@type': 'BreadcrumbList', itemListElement: crumbs.map((c, i) => ({ '@type': 'ListItem', position: i + 1, name: c.name, item: absoluteUrl(c.url), })), }; } export type ListItem = { url: string; name: string }; export function buildItemList( items: ListItem[], name?: string ): Record { return { '@context': 'https://schema.org', '@type': 'ItemList', ...(name ? { name } : {}), numberOfItems: items.length, itemListElement: items.map((it, i) => ({ '@type': 'ListItem', position: i + 1, name: it.name, url: absoluteUrl(it.url), })), }; } export const PERSON_AUTHOR = { '@type': 'Person', name: 'rzen', url: `${SITE_URL}/about/`, }; export const ORGANIZATION = { '@context': 'https://schema.org', '@type': 'Organization', '@id': `${SITE_URL}/#org`, name: 'Unique', url: SITE_URL, logo: `${SITE_URL}/favicon.svg`, }; export const WEBSITE = { '@context': 'https://schema.org', '@type': 'WebSite', '@id': `${SITE_URL}/#site`, name: 'Unique', url: SITE_URL, description: 'A small log of delightful, unique things — products, apps, phenomena, oddities.', publisher: { '@id': `${SITE_URL}/#org` }, inLanguage: 'en-US', }; const SOFTWARE_CATEGORIES = new Set([ 'apps', 'app', 'software', 'macos-apps', 'macos', 'ios-apps', 'ios', 'tools', ]); export function reviewedItemType(category: string): 'SoftwareApplication' | 'Product' { return SOFTWARE_CATEGORIES.has(category.toLowerCase()) ? 'SoftwareApplication' : 'Product'; }