--- import smartypants from 'smartypants'; type SEOMetadata = { name?: string; title: string; description: string; image?: { src: string; alt: string }; canonicalURL?: URL | null; locale?: string; }; type OpenGraph = Partial & { type?: string; }; type Twitter = Partial & { handle?: string; card?: 'summary' | 'summary_large_image'; }; export type Props = SEOMetadata & { og?: OpenGraph; twitter?: Twitter; }; const { name, description, image, locale = 'en', canonicalURL = new URL(Astro.url.pathname, Astro.site), og: _og = {}, twitter: _twitter = {}, } = Astro.props; const title = [Astro.props.title, name].filter(Boolean).join(' | '); const og: OpenGraph = { name, title, description, canonicalURL, image, locale, type: 'website', ..._og }; const twitter: Twitter = { name, title, description, canonicalURL, image, locale, card: 'summary_large_image', ..._twitter }; const ensureSlash = (url: string | URL) => `${url.toString().replace(/\/$/, '')}/`; --- <!-- Page Metadata --> <meta name="generator" content={Astro.generator} /> {canonicalURL && <link rel="canonical" href={ensureSlash(canonicalURL)} />} <title>{title} {og.canonicalURL && } { og.image && ( <> ) } {twitter.card && } {twitter.handle && } { twitter.image && ( <> ) }