fix(seo): canonical URL, og:locale:alternate, JSON-LD languages, sitemap x-default
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,10 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params
|
||||
const t = await getTranslations({ locale, namespace: 'meta' })
|
||||
|
||||
const ogLocaleMap: Record<string, string> = { en: 'en_US', fr: 'fr_FR', it: 'it_IT', es: 'es_ES' }
|
||||
const currentOgLocale = ogLocaleMap[locale] ?? 'en_US'
|
||||
const otherOgLocales = Object.values(ogLocaleMap).filter((l) => l !== currentOgLocale)
|
||||
|
||||
return {
|
||||
metadataBase: new URL(BASE_URL),
|
||||
title: {
|
||||
@@ -31,9 +35,12 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
openGraph: {
|
||||
type: 'website',
|
||||
siteName: t('siteName'),
|
||||
locale: ({ en: 'en_US', fr: 'fr_FR', it: 'it_IT', es: 'es_ES' } as Record<string, string>)[locale] ?? 'en_US',
|
||||
locale: currentOgLocale,
|
||||
images: [{ url: '/images/og-default.png', width: 1200, height: 630 }],
|
||||
},
|
||||
other: {
|
||||
'og:locale:alternate': otherOgLocales,
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
},
|
||||
@@ -41,16 +48,6 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
alternates: {
|
||||
canonical: BASE_URL,
|
||||
languages: {
|
||||
'en': BASE_URL,
|
||||
'fr': `${BASE_URL}/fr`,
|
||||
'it': `${BASE_URL}/it`,
|
||||
'es': `${BASE_URL}/es`,
|
||||
'x-default': BASE_URL,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +72,12 @@ const organizationJsonLd = {
|
||||
email: 'hello@letsbe.biz',
|
||||
contactType: 'customer service',
|
||||
},
|
||||
availableLanguage: [
|
||||
{ '@type': 'Language', name: 'English', alternateName: 'en' },
|
||||
{ '@type': 'Language', name: 'French', alternateName: 'fr' },
|
||||
{ '@type': 'Language', name: 'Italian', alternateName: 'it' },
|
||||
{ '@type': 'Language', name: 'Spanish', alternateName: 'es' },
|
||||
],
|
||||
}
|
||||
|
||||
export default async function LocaleLayout({ children, params }: Props) {
|
||||
|
||||
@@ -38,16 +38,17 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
}
|
||||
}
|
||||
|
||||
const websiteJsonLd = {
|
||||
export default async function HomePage({ params }: Props) {
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
|
||||
const websiteJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
name: 'LetsBe.',
|
||||
url: BASE_URL,
|
||||
}
|
||||
|
||||
export default async function HomePage({ params }: Props) {
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
inLanguage: locale,
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
|
||||
@@ -19,6 +19,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
fr: `${BASE_URL}/fr${route}`,
|
||||
it: `${BASE_URL}/it${route}`,
|
||||
es: `${BASE_URL}/es${route}`,
|
||||
'x-default': `${BASE_URL}${route}`,
|
||||
},
|
||||
},
|
||||
}))
|
||||
@@ -34,6 +35,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
fr: `${BASE_URL}/fr/work/${slug}`,
|
||||
it: `${BASE_URL}/it/work/${slug}`,
|
||||
es: `${BASE_URL}/es/work/${slug}`,
|
||||
'x-default': `${BASE_URL}/work/${slug}`,
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user