--- /** * SEO.astro — Reusable
tags for OG, Twitter, canonical, robots. * * Place inside . All props are optional except title/description * (which the parent layout owns). Designed to be rendered once per page * via BaseLayout.astro. */ interface Props { title: string; description: string; /** Path-only or absolute URL. Defaults to /images/og/default-og.jpg */ ogImage?: string; /** Override canonical URL. Default: current pathname */ canonical?: string; /** og:type — "website" for pages, "article" for blog */ ogType?: 'website' | 'article' | 'product'; /** Article published time (ISO) — only used when ogType=article */ publishedTime?: string; /** Article author — only used when ogType=article */ author?: string; /** Indexing policy. Default: 'index, follow' */ robots?: string; /** Override site_name for og:site_name */ siteName?: string; /** Locale tag — default th_TH */ locale?: string; } const { title, description, ogImage = '/images/og/default-og.jpg', canonical, ogType = 'website', publishedTime, author, robots = 'index, follow', siteName = 'ดีล พลัส เทค', locale = 'th_TH', } = Astro.props; const siteUrl = Astro.site ?? new URL(Astro.url.origin); const origin = siteUrl.origin; // Build absolute URL for ogImage (handle both path-only and full URL inputs) const isAbsolute = /^https?:\/\//.test(ogImage); const fullOgImage = isAbsolute ? ogImage : new URL(ogImage, origin).toString(); // Canonical: explicit override OR current path const canonicalPath = canonical ?? Astro.url.pathname; const fullCanonical = new URL(canonicalPath, origin).toString(); --- {ogType === 'article' && publishedTime && ( )} {ogType === 'article' && author && ( )}