login register comlated

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-04-01 18:26:25 +05:00
parent 9414ce0c8a
commit 7b76901f5f
23 changed files with 576 additions and 102 deletions

137
src/shared/lib/metadata.ts Normal file
View File

@@ -0,0 +1,137 @@
import type { Metadata } from 'next';
import { SEO_DATA, type SupportedLocale } from '../config/seo.config';
// ─── Site-wide constants ───────────────────────────────────────────────────────
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://antiplagiat.uz';
const OG_IMAGE_URL = `${SITE_URL}/og-image.png`; // 1200×630 px recommended
const TWITTER_HANDLE = '@antiplagiatuz'; // update or remove if unused
// ─── Root layout metadata (called in app/[locale]/layout.tsx) ─────────────────
export function generateRootMetadata(locale: string): Metadata {
const seo = SEO_DATA[locale as SupportedLocale] ?? SEO_DATA.ru;
// Build alternate-language links for <head>
const languages: Record<string, string> = {
uz: `${SITE_URL}/uz`,
ru: `${SITE_URL}/ru`,
en: `${SITE_URL}/en`,
'x-default': `${SITE_URL}/ru`,
};
return {
// ── Basic ──────────────────────────────────────────────────────────────────
metadataBase: new URL(SITE_URL),
title: {
default: seo.title,
template: seo.titleTemplate,
},
description: seo.description,
keywords: seo.keywords,
authors: [{ name: seo.siteName, url: SITE_URL }],
creator: seo.siteName,
publisher: seo.siteName,
applicationName: seo.siteName,
generator: 'Next.js',
// ── Canonical & alternates ─────────────────────────────────────────────────
alternates: {
canonical: `${SITE_URL}/${locale}`,
languages,
},
// ── Robots ────────────────────────────────────────────────────────────────
robots: {
index: true,
follow: true,
nocache: false,
googleBot: {
index: true,
follow: true,
noimageindex: false,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
// ── Open Graph ────────────────────────────────────────────────────────────
openGraph: {
type: 'website',
locale: ogLocale(locale),
alternateLocale: ogAlternates(locale),
url: `${SITE_URL}/${locale}`,
siteName: seo.siteName,
title: seo.ogTitle,
description: seo.ogDescription,
images: [
{
url: OG_IMAGE_URL,
width: 1200,
height: 630,
alt: seo.ogTitle,
type: 'image/png',
},
],
},
// ── Twitter / X ───────────────────────────────────────────────────────────
twitter: {
card: 'summary_large_image',
site: TWITTER_HANDLE,
creator: TWITTER_HANDLE,
title: seo.ogTitle,
description: seo.ogDescription,
images: [OG_IMAGE_URL],
},
// ── Icons ─────────────────────────────────────────────────────────────────
icons: {
icon: [
{ url: '/favicon.ico' },
{ url: '/icons/icon-16.png', sizes: '16x16', type: 'image/png' },
{ url: '/icons/icon-32.png', sizes: '32x32', type: 'image/png' },
{ url: '/icons/icon-192.png', sizes: '192x192', type: 'image/png' },
],
apple: [
{
url: '/icons/apple-touch-icon.png',
sizes: '180x180',
type: 'image/png',
},
],
shortcut: '/favicon.ico',
},
// ── Web app manifest ──────────────────────────────────────────────────────
manifest: '/manifest.webmanifest',
// ── Verification (add your Search Console token) ──────────────────────────
verification: {
google: process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION ?? '',
yandex: process.env.NEXT_PUBLIC_YANDEX_VERIFICATION ?? '',
},
// ── Extra meta ────────────────────────────────────────────────────────────
category: 'education',
};
}
// ─── Helpers ──────────────────────────────────────────────────────────────────
/** Maps locale code to Open Graph locale string */
function ogLocale(locale: string): string {
const map: Record<string, string> = {
uz: 'uz_UZ',
ru: 'ru_RU',
en: 'en_US',
};
return map[locale] ?? 'ru_RU';
}
/** Returns the other two OG locales for alternateLocale */
function ogAlternates(currentLocale: string): string[] {
const all = ['uz_UZ', 'ru_RU', 'en_US'];
return all.filter((l) => l !== ogLocale(currentLocale));
}