feat: update locale layout with Inter font, ThemeProvider, SEO metadata, JSON-LD, Header, and footer

This commit is contained in:
2026-08-11 09:00:01 +02:00
parent 6e7ee816ad
commit efe6515fc9
+62 -8
View File
@@ -1,9 +1,14 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { NextIntlClientProvider } from 'next-intl'
import { getTranslations, getMessages } from 'next-intl/server'
import { notFound } from 'next/navigation'
import { ThemeProvider } from 'next-themes'
import { routing } from '@/i18n/routing'
import { LanguageSwitcher } from '@/components/LanguageSwitcher'
import { Header } from '@/components/Header'
import '../globals.css'
const inter = Inter({ subsets: ['latin', 'latin-ext'] })
export async function generateMetadata({
params,
@@ -12,7 +17,26 @@ export async function generateMetadata({
}): Promise<Metadata> {
const { locale } = await params
const t = await getTranslations({ locale, namespace: 'meta' })
return { title: t('title') }
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? ''
return {
title: t('title'),
description: t('description'),
robots: { index: true, follow: true },
openGraph: {
title: t('title'),
description: t('description'),
url: `${baseUrl}/${locale}`,
siteName: 'Ombrora',
locale,
},
alternates: {
canonical: `${baseUrl}/${locale}`,
languages: Object.fromEntries(
routing.locales.map((l) => [l, `/${l}`])
),
},
}
}
export default async function LocaleLayout({
@@ -29,14 +53,44 @@ export default async function LocaleLayout({
}
const messages = await getMessages()
const t = await getTranslations({ locale, namespace: 'footer' })
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? ''
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'WebApplication',
name: 'Ombrora',
url: baseUrl,
description: 'Free, fast, private video downloader.',
applicationCategory: 'MultimediaApplication',
operatingSystem: 'Web',
offers: {
'@type': 'Offer',
price: '0',
priceCurrency: 'EUR',
},
}
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
<LanguageSwitcher />
{children}
</NextIntlClientProvider>
<html lang={locale} suppressHydrationWarning>
<head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</head>
<body className={`${inter.className} bg-white dark:bg-slate-950 text-gray-900 dark:text-gray-50 antialiased min-h-screen flex flex-col`}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<NextIntlClientProvider messages={messages}>
<Header />
<div className="flex-1">
{children}
</div>
<footer className="border-t border-gray-100 dark:border-slate-800 py-6 text-center text-sm text-gray-400 dark:text-slate-500">
{t('copyright')}
</footer>
</NextIntlClientProvider>
</ThemeProvider>
</body>
</html>
)