Fundament: Branding Craftvia

- Farb-Tokens laut Brandbook §11.4 (Lotsenblau, Signalorange, Graphit, Hafengrau,
  Stahlgrau, Zink, Funktionsfarben) in globals.css + src/lib/brand.ts; helles Theme
- Inline-SVG-Logo src/components/brand/craftvia-logo.tsx (horizontal/signet,
  color/mono/reversed, App-Icon-Kachel, optionale Tagline); Certvia-/GEFIM-Logos entfernt
- Favicon/PWA-Icons aus dem Signet erzeugt (scripts/generate-brand-icons.ts),
  site.webmanifest (Craftvia, theme_color #082E5B)
- Inter selbst gehostet (next/font/local, lokale OFL-Datei), Open Sans/Poppins entfernt
- Metadaten, WebAuthn-RP-Name, Mail-/Dokument-CD auf Craftvia umgestellt
- docs/craftvia/BRANDING.md ersetzt docs/BRANDING-CERTVIA.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 11:39:52 +02:00
co-authored by Claude Opus 5
parent 8491c7f173
commit 9ec7fa5356
62 changed files with 549 additions and 1070 deletions
+12 -40
View File
@@ -5,30 +5,13 @@ import { getLocale } from "next-intl/server";
import { BRAND, BRAND_ASSETS, BRAND_COLORS } from "@/lib/brand";
import "./globals.css";
// Selbst gehostet über next/font/local (committete woff2 in ./fonts) — kein
// Google-Fonts-Fetch zur Build- oder Laufzeit. DSGVO-konform und macht den
// Produktiv-Build reproduzierbar/offline (next/font/google lud die Schriften
// sonst zur Build-Zeit von Google, was flakig fehlschlagen kann).
const openSans = localFont({
variable: "--font-open-sans",
// Inter (Brandbook §11.5), selbst gehostet über next/font/local — kein Google-Fonts-Fetch
// zur Build- oder Laufzeit (DSGVO, reproduzierbarer Offline-Build). Variable Font
// (Gewichte 100–900 in einer Datei). TODO(brand): auf woff2-Subsets umstellen (kleiner).
const inter = localFont({
variable: "--font-inter",
display: "swap",
src: [
{ path: "./fonts/open-sans-300.woff2", weight: "300", style: "normal" },
{ path: "./fonts/open-sans-400.woff2", weight: "400", style: "normal" },
{ path: "./fonts/open-sans-600.woff2", weight: "600", style: "normal" },
{ path: "./fonts/open-sans-700.woff2", weight: "700", style: "normal" },
],
});
const poppins = localFont({
variable: "--font-poppins",
display: "swap",
src: [
{ path: "./fonts/poppins-300.woff2", weight: "300", style: "normal" },
{ path: "./fonts/poppins-500.woff2", weight: "500", style: "normal" },
{ path: "./fonts/poppins-600.woff2", weight: "600", style: "normal" },
{ path: "./fonts/poppins-700.woff2", weight: "700", style: "normal" },
],
src: [{ path: "./fonts/inter-variable.ttf", weight: "100 900", style: "normal" }],
});
export const metadata: Metadata = {
@@ -37,35 +20,27 @@ export const metadata: Metadata = {
description: BRAND.description,
applicationName: BRAND.name,
manifest: "/site.webmanifest",
// Alle Icons aus dem Certvia-Asset-Bundle (public/favicon + public/assets/logo).
// Icons aus dem Craftvia-Signet erzeugt (scripts/generate-brand-icons.ts).
icons: {
icon: [
{ url: "/favicon.ico", sizes: "any" },
{ url: BRAND_ASSETS.favicon, type: "image/svg+xml" },
{ url: "/favicon/icon-16.png", type: "image/png", sizes: "16x16" },
{ url: "/favicon/icon-32.png", type: "image/png", sizes: "32x32" },
],
apple: [{ url: "/favicon/apple-touch-icon-180.png", sizes: "180x180" }],
apple: [{ url: BRAND_ASSETS.appleTouchIcon, sizes: "180x180" }],
},
appleWebApp: { capable: true, title: BRAND.name, statusBarStyle: "black-translucent" },
appleWebApp: { capable: true, title: BRAND.name, statusBarStyle: "default" },
openGraph: {
type: "website",
siteName: BRAND.name,
title: `${BRAND.name} — ${BRAND.tagline}`,
description: BRAND.description,
images: [{ url: "/assets/logo/certvia-lockup-positiv-1024.png", width: 1024, height: 259 }],
},
twitter: {
card: "summary_large_image",
title: `${BRAND.name} — ${BRAND.tagline}`,
description: BRAND.description,
images: ["/assets/logo/certvia-lockup-positiv-1024.png"],
images: [{ url: BRAND_ASSETS.ogImage, width: 512, height: 512 }],
},
};
export const viewport: Viewport = {
// Marken-Violett (wie auf der Certvia-Website), nicht die UI-Primärfarbe.
themeColor: BRAND_COLORS.violet,
themeColor: BRAND_COLORS.lotsenblau,
};
export default async function RootLayout({
@@ -76,10 +51,7 @@ export default async function RootLayout({
const locale = await getLocale();
return (
<html
lang={locale}
className={`${openSans.variable} ${poppins.variable} h-full antialiased`}
>
<html lang={locale} className={`${inter.variable} h-full antialiased`}>
<body className="min-h-full flex flex-col bg-background text-foreground">
<NextIntlClientProvider>{children}</NextIntlClientProvider>
</body>