feat: redesign CMS and unify German admin UI

This commit is contained in:
2026-09-17 16:51:24 +02:00
parent a2b3e99174
commit 7ec0c51ff5
129 changed files with 952 additions and 550 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Minimal builders for Lexical's SerializedEditorState JSON — just enough to
* Minimal builders for Lexical's SerializedEditorState JSON - just enough to
* seed richText fields from plain paragraph/heading strings (see lib/texte.ts).
* Shape verified against node_modules/lexical's Serialized*Node types.
*/
+11 -11
View File
@@ -1,11 +1,11 @@
/**
* Seeds the CMS with the original ANOUMA content (the 7 offers from
* texte.txt, plus starting text for every editable page). Safe to re-run —
* texte.txt, plus starting text for every editable page). Safe to re-run -
* offers are matched and updated by slug, globals are simply overwritten.
*
* Usage: npm run seed (requires DATABASE_URI + PAYLOAD_SECRET in .env)
*
* Deliberately does NOT create a Users document — the first admin account is
* Deliberately does NOT create a Users document - the first admin account is
* created through Payload's own "create first user" screen at /admin, so no
* password is ever hardcoded here.
*/
@@ -94,7 +94,7 @@ async function seedOffers(payload: Awaited<ReturnType<typeof getPayload>>) {
description: lexicalFromParagraphs(mamaBabySingkreis.paragraphs),
},
{
// A private, bookable single-session offer — not listed in the menu
// A private, bookable single-session offer - not listed in the menu
// or on /angebote (see `visibility`), reachable only via its direct
// link or a booking Anna creates herself. Content reuses the
// "Individuelle Begleitung" section of Prozessbegleitung, which is
@@ -108,7 +108,7 @@ async function seedOffers(payload: Awaited<ReturnType<typeof getPayload>>) {
bookable: true,
price: "auf Anfrage",
durationMinutes: 60,
shortDescription: "Persönliche Einzelbegleitung – vor Ort oder online.",
shortDescription: "Persönliche Einzelbegleitung - vor Ort oder online.",
description: lexicalFromParagraphs(prozessbegleitung.sections[0].paragraphs),
},
];
@@ -151,13 +151,13 @@ async function seedGlobals(payload: Awaited<ReturnType<typeof getPayload>>) {
},
{
title: "Verbindung",
quote: "Räume für Verbindung – mit uns selbst, miteinander und mit der Natur.",
quote: "Räume für Verbindung - mit uns selbst, miteinander und mit der Natur.",
},
{ title: "Natur", quote: "Wir sind nicht nur in der Natur – wir sind ein Teil von ihr." },
{ title: "Natur", quote: "Wir sind nicht nur in der Natur - wir sind ein Teil von ihr." },
],
ctaTitle: "Kennenlernen & Termine vereinbaren",
ctaLead:
"Ich freue mich, von dir zu hören – schreib mir oder buche direkt ein unverbindliches Kennenlerngespräch.",
"Ich freue mich, von dir zu hören - schreib mir oder buche direkt ein unverbindliches Kennenlerngespräch.",
},
});
console.log(" ↺ Global „Startseite“ gesetzt");
@@ -179,7 +179,7 @@ async function seedGlobals(payload: Awaited<ReturnType<typeof getPayload>>) {
slug: "angebote-intro",
data: {
title: "Angebote",
lead: "Jeder Raum ist anders – und darf so genau das sein, was gerade gebraucht wird. Ein Überblick über meine Begleitung für Erwachsene, Kinder und Gemeinschaft.",
lead: "Jeder Raum ist anders - und darf so genau das sein, was gerade gebraucht wird. Ein Überblick über meine Begleitung für Erwachsene, Kinder und Gemeinschaft.",
},
});
console.log(" ↺ Global „Angebote (Einleitung)“ gesetzt");
@@ -199,7 +199,7 @@ async function seedGlobals(payload: Awaited<ReturnType<typeof getPayload>>) {
data: {
eyebrow: "Kontakt",
title: "Ich freue mich, von dir zu hören",
lead: "Ob Frage, Anliegen oder der Wunsch nach einem Kennenlerngespräch – schreib mir gerne.",
lead: "Ob Frage, Anliegen oder der Wunsch nach einem Kennenlerngespräch - schreib mir gerne.",
email: "info@anouma.org",
phone: "+49 151 53611786",
region: "Haldenweg 3, 79853 Lenzkirch",
@@ -224,11 +224,11 @@ async function seedGlobals(payload: Awaited<ReturnType<typeof getPayload>>) {
data: {
eyebrow: "Termin buchen",
title: "Kennenlernen & Termine vereinbaren",
lead: "Der erste Schritt ist oft der wichtigste. Melde dich gerne – unverbindlich und in deinem Tempo.",
lead: "Der erste Schritt ist oft der wichtigste. Melde dich gerne - unverbindlich und in deinem Tempo.",
steps: [
{
title: "Nachricht schreiben",
text: "Schildere kurz dein Anliegen und welches Angebot dich interessiert – über das Formular unten oder direkt per E-Mail.",
text: "Schildere kurz dein Anliegen und welches Angebot dich interessiert - über das Formular unten oder direkt per E-Mail.",
},
{
title: "Kennenlernen",
+4 -4
View File
@@ -1,5 +1,5 @@
/**
* Optional, dev-only SEO sanity check — NOT part of the build or deploy
* Optional, dev-only SEO sanity check - NOT part of the build or deploy
* pipeline, never blocks production. Run manually:
*
* npm run seo:check
@@ -34,8 +34,8 @@ async function checkCollection(
}
for (const doc of docs as { slug?: string | null; title?: string; seo?: { description?: string | null } | null }[]) {
if (!doc.title?.trim()) warn(`Dokument ohne Titel (slug: ${doc.slug ?? "—"}).`);
if (!doc.slug?.trim()) warn(`Dokument ohne Slug: „${doc.title ?? "—"}“.`);
if (!doc.title?.trim()) warn(`Dokument ohne Titel (slug: ${doc.slug ?? "-"}).`);
if (!doc.slug?.trim()) warn(`Dokument ohne Slug: „${doc.title ?? "-"}“.`);
}
if (docs.length === 0) console.log(" (keine Einträge)");
@@ -60,7 +60,7 @@ async function run() {
await checkCollection(payload, "posts", "Aktuelles");
await checkMedia(payload);
console.log(`\n${warnings === 0 ? "Keine Auffälligkeiten gefunden." : `${warnings} Hinweis(e) gefunden — siehe oben.`}`);
console.log(`\n${warnings === 0 ? "Keine Auffälligkeiten gefunden." : `${warnings} Hinweis(e) gefunden - siehe oben.`}`);
process.exit(0);
}