SITE_TITLE per Docker-Variable, Favicon im Admin-Bereich austauschbar

- SITE_TITLE (Default "Canteen Menu") steuert Browser-Tab-Titel und
  H1-Fallback ohne Logo
- Favicon-Upload analog zum Logo über den Design-Bereich (Storage-
  Bucket branding); generateMetadata setzt icons.icon jetzt immer
  explizit, da Next.js sonst app/favicon.ico zusätzlich einbindet –
  die Datei liegt daher als expliziter Fallback unter public/
This commit is contained in:
2026-07-18 00:46:41 +02:00
parent 72459d8da5
commit 39181be3fb
5 changed files with 105 additions and 27 deletions
+19 -6
View File
@@ -2,10 +2,10 @@ import type { Metadata } from "next";
import { Geist } from "next/font/google";
import "./globals.css";
import { createClient } from "@/lib/supabase/server";
import { COLOR_VARS, DEFAULT_COLORS } from "@/lib/types";
import { COLOR_VARS, DEFAULT_COLORS, faviconUrl, SITE_TITLE } from "@/lib/types";
import packageJson from "@/package.json";
// Farben/Logo sollen Änderungen sofort widerspiegeln.
// Farben/Logo/Favicon sollen Änderungen sofort widerspiegeln.
export const dynamic = "force-dynamic";
const geistSans = Geist({
@@ -13,10 +13,23 @@ const geistSans = Geist({
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Canteen Menu",
description: "Speisekarte der Betriebskantine",
};
export async function generateMetadata(): Promise<Metadata> {
const supabase = await createClient();
const { data: settings } = await supabase
.from("settings")
.select("favicon_path")
.eq("id", 1)
.maybeSingle();
return {
title: SITE_TITLE,
description: "Speisekarte der Betriebskantine",
// Immer explizit setzen: app/favicon.ico würde sonst zusätzlich zu
// einem eigenen Favicon eingebunden (Next.js kombiniert Datei-
// Konvention und Metadata statt sie zu ersetzen).
icons: { icon: faviconUrl(settings?.favicon_path) ?? "/favicon.ico" },
};
}
export default async function RootLayout({
children,