Add SeoHead component with canonical, hreflang, OG, Twitter, and JSON-LD
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import type { Language } from "@/i18n/resolver";
|
||||
import { JsonLdRenderer } from "@/shared/seo/json-ld.js";
|
||||
import type { Thing } from "schema-dts";
|
||||
|
||||
export interface SeoHeadProps {
|
||||
title: string;
|
||||
description: string;
|
||||
canonical: string;
|
||||
hreflang: Array<{ lang: Language | "x-default"; href: string }>;
|
||||
og: {
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
image: string;
|
||||
type: "website" | "article";
|
||||
locale: string;
|
||||
siteName: string;
|
||||
};
|
||||
twitter?: {
|
||||
card: "summary" | "summary_large_image";
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
};
|
||||
jsonLd?: Thing | Thing[];
|
||||
noindex?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the full SEO <head> fragment: title, meta description, canonical,
|
||||
* hreflang alternates, Open Graph tags, Twitter Card tags, and JSON-LD.
|
||||
*/
|
||||
export function SeoHead({
|
||||
title,
|
||||
description,
|
||||
canonical,
|
||||
hreflang,
|
||||
og,
|
||||
twitter,
|
||||
jsonLd,
|
||||
noindex,
|
||||
}: SeoHeadProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="canonical" href={canonical} />
|
||||
{noindex && <meta name="robots" content="noindex,nofollow" />}
|
||||
|
||||
{/* Hreflang alternates */}
|
||||
{hreflang.map((entry) => (
|
||||
<link
|
||||
key={entry.lang}
|
||||
rel="alternate"
|
||||
hrefLang={entry.lang}
|
||||
href={entry.href}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Open Graph */}
|
||||
<meta property="og:title" content={og.title} />
|
||||
<meta property="og:description" content={og.description} />
|
||||
<meta property="og:url" content={og.url} />
|
||||
<meta property="og:image" content={og.image} />
|
||||
<meta property="og:type" content={og.type} />
|
||||
<meta property="og:locale" content={og.locale} />
|
||||
<meta property="og:site_name" content={og.siteName} />
|
||||
|
||||
{/* Twitter Card */}
|
||||
{twitter && (
|
||||
<>
|
||||
<meta name="twitter:card" content={twitter.card} />
|
||||
{twitter.title && <meta name="twitter:title" content={twitter.title} />}
|
||||
{twitter.description && <meta name="twitter:description" content={twitter.description} />}
|
||||
{twitter.image && <meta name="twitter:image" content={twitter.image} />}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* JSON-LD */}
|
||||
{jsonLd && <JsonLdRenderer data={jsonLd} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user