Files
klz-cables.com/app/[locale]/layout.tsx
Marc Mintel df2dd23206
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 1m53s
Build & Deploy / 🏗️ Build (push) Successful in 7m44s
Build & Deploy / 🚀 Deploy (push) Successful in 33s
Build & Deploy / 🧪 Smoke Test (push) Successful in 59s
Build & Deploy / ⚡ Lighthouse (push) Successful in 3m14s
Build & Deploy / 🔔 Notify (push) Successful in 1s
feat: optimize performance and SEO, integrate Lighthouse CI
- Integrated imgproxy for centralized image optimization
- Implemented Lighthouse CI in Gitea pipeline with native Chromium
- Reached 100/100 SEO score by fixing canonicals, hreflang, and link text
- Optimized LCP by forcing Hero component visibility until hydration
- Decoupled analytics into an async shell to reduce TTI
2026-02-18 10:01:00 +01:00

134 lines
4.4 KiB
TypeScript

import Footer from '@/components/Footer';
import Header from '@/components/Header';
import JsonLd from '@/components/JsonLd';
import SkipLink from '@/components/SkipLink';
import CMSConnectivityNotice from '@/components/CMSConnectivityNotice';
import { RecordModeProvider } from '@/components/record-mode/RecordModeContext';
import { RecordModeVisuals } from '@/components/record-mode/RecordModeVisuals';
import { ToolCoordinator } from '@/components/record-mode/ToolCoordinator';
import AnalyticsShell from '@/components/analytics/AnalyticsShell';
import { Metadata, Viewport } from 'next';
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
import dynamic from 'next/dynamic';
import { Suspense } from 'react';
import '../../styles/globals.css';
import { SITE_URL } from '@/lib/schema';
import { config } from '@/lib/config';
import { setRequestLocale } from 'next-intl/server';
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
export const metadata: Metadata = {
metadataBase: new URL(SITE_URL),
alternates: {
canonical: '/',
languages: {
de: '/de',
en: '/en',
},
},
icons: {
icon: [
{ url: '/favicon.ico', sizes: 'any' },
{ url: '/logo-blue.svg', type: 'image/svg+xml' },
],
apple: [{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' }],
},
};
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 1,
userScalable: false,
viewportFit: 'cover',
themeColor: '#001a4d',
};
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 = {};
try {
messages = await getMessages();
} catch (error) {
console.error(`Failed to load messages for locale '${safeLocale}':`, error);
messages = {};
}
const { getServerAppServices } = await import('@/lib/services/create-services.server');
const serverServices = getServerAppServices();
try {
const { headers } = await import('next/headers');
const requestHeaders = await headers();
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,
});
}
serverServices.analytics.trackPageview();
} 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 recordModeEnabled = process.env.NEXT_PUBLIC_RECORD_MODE_ENABLED === 'true';
const feedbackEnabled = process.env.NEXT_PUBLIC_FEEDBACK_ENABLED === 'true';
return (
<html lang={safeLocale} className={`scroll-smooth overflow-x-hidden ${inter.variable}`}>
<head></head>
<body className="flex flex-col min-h-screen font-sans selection:bg-accent selection:text-primary-dark antialiased overflow-x-hidden">
<NextIntlClientProvider messages={messages} locale={safeLocale}>
<RecordModeProvider isEnabled={recordModeEnabled}>
<RecordModeVisuals>
<SkipLink />
<JsonLd />
<Header />
<main
id="main-content"
className="flex-grow animate-fade-in overflow-visible"
tabIndex={-1}
>
{children}
</main>
<Footer />
</RecordModeVisuals>
<CMSConnectivityNotice />
<AnalyticsShell />
<ToolCoordinator feedbackEnabled={feedbackEnabled} />
</RecordModeProvider>
</NextIntlClientProvider>
</body>
</html>
);
}