Custom post content blocks (images/gallery/video/quote) + backend-driven SEO settings
RichText.tsx switched to Payload's official React renderer + custom JSXConverters (same call signature, LiveRichText/LivePostContent untouched) — needed to render the new Lexical Blocks the Payload repo's Posts.content just gained. Converters follow the existing CMS-image convention (relative + aspect-[...] + fill + object-cover); the video block resolves YouTube/Vimeo links to an iframe embed. New getSeoSettings() fetcher (same pattern as getKleinunternehmer()), app/layout.tsx now generateMetadata() reading it with the same fallback values it used to hardcode. Per-post SEO overrides (seoTitle/ seoDescription/seoImage) wired into the blog detail page's metadata, falling back to title/excerpt/thumbnail when empty. Also fixed while auditing every page's metadata: missing descriptions on 3 konto pages, a static title on the dynamic order-detail route, and missing OG images on /shop and /blog.
This commit is contained in:
+27
-17
@@ -4,7 +4,7 @@ import "./globals.css";
|
||||
import { Navbar } from "./components/Navbar";
|
||||
import { CartFlyProvider } from "./components/CartFly";
|
||||
import { CartSync } from "./components/CartSync";
|
||||
import { getProducts } from "./lib/payload";
|
||||
import { getProducts, getSeoSettings } from "./lib/payload";
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
@@ -30,22 +30,32 @@ const lora = Lora({
|
||||
weight: ["400", "600"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL("https://einfach-produktiv.mk360.de"),
|
||||
title: {
|
||||
default: "einfach produktiv. – Werkzeuge und Impulse für einen leichteren Alltag",
|
||||
template: "%s | einfach produktiv.",
|
||||
},
|
||||
description: "Werkzeuge, Impulse und ein Blog für mehr Klarheit im Alltag.",
|
||||
openGraph: {
|
||||
siteName: "einfach produktiv.",
|
||||
locale: "de_DE",
|
||||
type: "website",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
},
|
||||
};
|
||||
// Backend-driven since 2026-07-24 (CompanySettings' "SEO" tab) — the
|
||||
// literal strings below are only the fallback getSeoSettings() returns if
|
||||
// that field is empty or unreachable, kept identical to what used to be
|
||||
// hardcoded here so nothing changes until an admin actually fills in the
|
||||
// new fields.
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const seo = await getSeoSettings();
|
||||
return {
|
||||
metadataBase: new URL("https://einfach-produktiv.mk360.de"),
|
||||
title: {
|
||||
default: seo.defaultTitle ?? "einfach produktiv.",
|
||||
template: seo.titleTemplate ?? "%s | einfach produktiv.",
|
||||
},
|
||||
description: seo.defaultDescription ?? undefined,
|
||||
openGraph: {
|
||||
siteName: "einfach produktiv.",
|
||||
locale: "de_DE",
|
||||
type: "website",
|
||||
images: seo.defaultOgImage ? [{ url: seo.defaultOgImage }] : undefined,
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
images: seo.defaultOgImage ? [seo.defaultOgImage] : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
|
||||
Reference in New Issue
Block a user