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:
Marco
2026-07-24 21:10:33 +00:00
parent b1b1aa2037
commit 797d9d42fe
13 changed files with 4249 additions and 184 deletions
+18 -5
View File
@@ -19,16 +19,29 @@ export async function generateMetadata({
const post = await getPostBySlug(slug);
if (!post) return { title: "Beitrag nicht gefunden" };
// Each falls back to the normal field when its SEO override (Posts.ts's
// "SEO" collapsible group) is empty — filling those in is optional, a
// post already has sensible metadata without them.
const title = post.seoTitle || post.title;
const description = post.seoDescription || post.excerpt;
const image = post.seoImage || post.thumbnail;
return {
title: post.title,
description: post.excerpt,
title,
description,
alternates: { canonical: `/blog/${post.slug}` },
openGraph: {
title: `${post.title} | einfach produktiv.`,
description: post.excerpt,
title: `${title} | einfach produktiv.`,
description,
url: `/blog/${post.slug}`,
type: "article",
images: post.thumbnail ? [{ url: post.thumbnail }] : undefined,
images: image ? [{ url: image }] : undefined,
},
twitter: {
card: "summary_large_image",
title,
description,
images: image ? [image] : undefined,
},
};
}