import { Footer } from '@/components/layout/Footer'; import { Header } from '@/components/layout/Header'; import JsonLd from '@/components/JsonLd'; import SkipLink from '@/components/SkipLink'; import CMSConnectivityNotice from '@/components/CMSConnectivityNotice'; import AnalyticsShell from '@/components/analytics/AnalyticsShell'; import { Metadata, Viewport } from 'next'; import { NextIntlClientProvider } from 'next-intl'; import { getMessages } from 'next-intl/server'; import '../../styles/globals.css'; import { SITE_URL } from '@/lib/schema'; import FeedbackClientWrapper from '@/components/FeedbackClientWrapper'; import { setRequestLocale } from 'next-intl/server'; import { Inter } from 'next/font/google'; import { getPayload } from 'payload'; import configPromise from '@payload-config'; const inter = Inter({ subsets: ['latin'], display: 'swap', variable: '--font-inter', }); export async function generateMetadata(props: { params: Promise<{ locale: string }>; }): Promise { const params = await props.params; const { locale } = params; const baseUrl = process.env.CI ? 'http://etib.localhost' : SITE_URL; return { title: { template: '%s | E-TIB', default: 'E-TIB | Die Experten für Kabeltiefbau', }, description: 'Ihr Partner für Kabelleitungstiefbau, Horizontalspülbohrungen, Planung und Vermessung in Guben und überregional.', metadataBase: new URL(baseUrl), manifest: '/manifest.webmanifest', alternates: { canonical: `${baseUrl}/${locale}`, languages: { de: `${baseUrl}/de`, en: `${baseUrl}/en`, }, }, icons: { icon: [ { url: '/favicon.ico', sizes: 'any' }, { url: '/assets/logo.png', type: 'image/png' }, ], apple: [{ url: '/assets/logo.png', sizes: '180x180', type: 'image/png' }], }, }; } export const viewport: Viewport = { width: 'device-width', initialScale: 1, maximumScale: 5, userScalable: true, viewportFit: 'cover', themeColor: '#117c61', }; import AutoBrochureModal from '@/components/AutoBrochureModal'; export default async function Layout(props: { children: React.ReactNode; params: Promise<{ locale: string }>; }) { const params = await props.params; const { locale } = params; const { children } = props; const supportedLocales = ['en', 'de']; const localeStr = (typeof locale === 'string' ? locale : '').trim(); const safeLocale = supportedLocales.includes(localeStr) ? localeStr : 'en'; setRequestLocale(safeLocale); let messages: Record = {}; try { messages = await getMessages(); } catch { messages = {}; } // Fetch navigation and company info from Payload Global Settings const payload = await getPayload({ config: configPromise }); const settings = await payload.findGlobal({ slug: 'settings', locale: safeLocale as any, }).catch(() => null); const navLinks = (settings?.mainNav && settings.mainNav.length > 0) ? settings.mainNav.map((n) => ({ label: n.label, url: n.url, })) : [ { label: 'Kompetenzen', url: `/${safeLocale}/kompetenzen` }, { label: 'Über uns', url: `/${safeLocale}/ueber-uns` }, { label: 'Karriere & Messen', url: `/${safeLocale}/karriere` } ]; const companyInfo = { contactEmail: settings?.contactEmail || 'info@e-tib.com', contactPhone: settings?.contactPhone || '+49 15207230518', address: settings?.address || 'Gewerbestraße 22\\n03172 Guben' }; // Pick only the namespaces required by client components to reduce the hydration payload size const clientKeys = [ 'Footer', 'Navigation', 'Contact', 'Products', 'Team', 'Home', 'Error', 'StandardPage', 'Brochure', ]; const clientMessages: Record = {}; for (const key of clientKeys) { if (messages[key]) { clientMessages[key] = messages[key]; } } const { getServerAppServices } = await import('@/lib/services/create-services.server'); const serverServices = getServerAppServices(); try { const { headers } = await import('next/headers'); const requestHeaders = await headers(); // Disable analytics in CI to prevent console noise/score penalties if (process.env.NEXT_PUBLIC_CI === 'true') { // Skip setting server context for analytics in CI } else if ('setServerContext' in serverServices.analytics) { (serverServices.analytics as any).setServerContext({ userAgent: requestHeaders.get('user-agent') || undefined, language: requestHeaders.get('accept-language')?.split(',')[0] || undefined, referrer: requestHeaders.get('referer') || undefined, ip: requestHeaders.get('x-forwarded-for')?.split(',')[0] || undefined, }); } // Server-side analytics tracking removed to prevent duplicate/empty events. // Client-side AnalyticsProvider handles all pageviews. } catch { if (process.env.NODE_ENV !== 'production' || !process.env.CI) { console.warn( '[Layout] Static generation detected or headers unavailable, skipping server-side analytics context', ); } } // Read directly from process.env — bypasses all abstraction to guarantee correctness const feedbackEnabled = process.env.NEXT_PUBLIC_FEEDBACK_ENABLED === 'true'; return (
{children}