Design-Tokens aus docs/10-design-system.md als CSS-Variablen: Grundpalette, die sechs Klassifizierungsfarben, Eckenradius durchgehend 2 px, keine Schatten ausser dem Fokusring. Der Schwärzungsbalken mit dem einmaligen Durchwischen respektiert prefers-reduced-motion. Vier Tests halten die Tokens gegen das Dokument. IBM Plex selbst gehostet als woff2, latin und latin-ext getrennt über unicode-range, font-display: swap, immutable-Cache. Alle Oberflächentexte in lib/i18n/de.ts. Ein Test durchsucht app/ und components/ nach Umlauten im JSX und schlägt fehl, wenn dort deutscher Text steht. Er hat beim ersten Lauf gleich einen Verstoss gefunden. /api/health prüft Datenbank, Discord-Gateway und ClamAV. Die Gesamtbewertung fällt nur auf "down", wenn die Datenbank weg ist: die anderen Dienste haben eigene Healthchecks im Stack, und ein ausgefallener Virenscanner soll nicht den Web-Container als tot markieren. Strikte CSP mit Nonce, kein unsafe-inline für Skripte. Die erste Route liegt bei 100 kB JavaScript nach Kompression, Budget sind 120 kB.
49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import type { Metadata, Viewport } from 'next'
|
|
import { de } from '@/lib/i18n/de'
|
|
import './globals.css'
|
|
|
|
export const metadata: Metadata = {
|
|
title: { default: de.app.name, template: `%s · ${de.app.shortName}` },
|
|
description: de.app.description,
|
|
robots: { index: false, follow: false },
|
|
}
|
|
|
|
export const viewport: Viewport = {
|
|
themeColor: '#15181A',
|
|
width: 'device-width',
|
|
initialScale: 1,
|
|
}
|
|
|
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<html lang="de">
|
|
<head>
|
|
{/* Nur die beiden Schnitte vorladen, die auf jeder Seite vorkommen. */}
|
|
<link
|
|
rel="preload"
|
|
href="/fonts/ibm-plex-sans-latin-400-normal.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossOrigin="anonymous"
|
|
/>
|
|
<link
|
|
rel="preload"
|
|
href="/fonts/ibm-plex-mono-latin-400-normal.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossOrigin="anonymous"
|
|
/>
|
|
</head>
|
|
<body>
|
|
<a
|
|
href="#inhalt"
|
|
className="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:z-50 focus:border focus:border-line focus:bg-panel focus:px-3 focus:py-2"
|
|
>
|
|
{de.nav.skipToContent}
|
|
</a>
|
|
{children}
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|