feat: migrate to Next.js 15 App Router with i18n and multi-page SEO
- Replace Vite+React SPA with Next.js 15, TypeScript, App Router - Static export (output: 'export'), deploy via npm run deploy - i18n routing: /ru/... and /en/... with generateStaticParams - New pages: /uslugi/ (catalog), /uslugi/[slug]/ (8 service pages), /faq/, /kontakty/ - SEO: generateMetadata on all pages, JSON-LD Service schema, hreflang alternates - ContactForm: 'use client', Turnstile + POST to /api/contact.php - Fonts: Manrope via next/font/google (CSS variable) - Remove: vite.config.js, entry-server.jsx, prerender scripts, LanguageContext Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
34
src/app/[lang]/layout.tsx
Normal file
34
src/app/[lang]/layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { LOCALES } from '@/lib/i18n'
|
||||
import Header from '@/components/layout/Header'
|
||||
import Footer from '@/components/layout/Footer'
|
||||
import FloatingContacts from '@/components/ui/FloatingContacts'
|
||||
import ScrollToTop from '@/components/ui/ScrollToTop'
|
||||
|
||||
export function generateStaticParams() {
|
||||
return LOCALES.map(lang => ({ lang }))
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: { default: 'Сисадмингрупп — IT-аутсорсинг в Пушкино', template: '%s | Сисадмингрупп' },
|
||||
description: 'IT-аутсорсинг, техническая поддержка, кибербезопасность для бизнеса в Пушкино и Московской области. Опыт 10+ лет, 150+ клиентов, SLA от 15 минут.',
|
||||
}
|
||||
|
||||
export default async function LangLayout({
|
||||
children,
|
||||
params,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
params: Promise<{ lang: string }>
|
||||
}) {
|
||||
const { lang } = await params
|
||||
return (
|
||||
<>
|
||||
<Header lang={lang} />
|
||||
<main>{children}</main>
|
||||
<Footer lang={lang} />
|
||||
<FloatingContacts />
|
||||
<ScrollToTop />
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user