266 lines
9.4 KiB
TypeScript
266 lines
9.4 KiB
TypeScript
/**
|
||
* 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 —
|
||
* 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
|
||
* created through Payload's own "create first user" screen at /admin, so no
|
||
* password is ever hardcoded here.
|
||
*/
|
||
import { getPayload } from "payload";
|
||
import config from "../payload.config";
|
||
import {
|
||
prozessbegleitung,
|
||
doula,
|
||
erdenkinder,
|
||
maedchenkreis,
|
||
singenImKreis,
|
||
singenFuerSchwangere,
|
||
mamaBabySingkreis,
|
||
ueberMich,
|
||
} from "../lib/texte";
|
||
import { lexicalFromParagraphs, lexicalFromSections } from "./lexical";
|
||
|
||
async function seedOffers(payload: Awaited<ReturnType<typeof getPayload>>) {
|
||
const offers = [
|
||
{
|
||
slug: "prozessbegleitung",
|
||
title: "Prozessbegleitung",
|
||
category: "prozessbegleitung" as const,
|
||
order: 1,
|
||
shortDescription: "Persönliche Begleitung in Lebensphasen, Veränderungen und inneren Prozessen.",
|
||
description: lexicalFromSections(prozessbegleitung.intro, prozessbegleitung.sections),
|
||
},
|
||
{
|
||
slug: "doula-begleitung",
|
||
title: "Doula-Begleitung",
|
||
category: "doula-begleitung" as const,
|
||
order: 2,
|
||
shortDescription: "Begleitung vor, während und nach der Geburt.",
|
||
description: lexicalFromSections(doula.intro, doula.sections),
|
||
},
|
||
{
|
||
slug: "erdenkinder",
|
||
title: "Erdenkinder",
|
||
category: "kindergruppen" as const,
|
||
order: 3,
|
||
shortDescription: "Naturverbunden. Kreativ. Frei. Für Kinder.",
|
||
description: lexicalFromParagraphs(erdenkinder.paragraphs),
|
||
},
|
||
{
|
||
slug: "maedchenkreis",
|
||
title: "Mädchenkreis",
|
||
category: "kindergruppen" as const,
|
||
order: 4,
|
||
shortDescription: "Stärkung. Vertrauen. Gemeinschaft. Für Mädchen.",
|
||
description: lexicalFromParagraphs(maedchenkreis.paragraphs),
|
||
},
|
||
{
|
||
slug: "singen-im-kreis",
|
||
title: "Singen im Kreis",
|
||
category: "singkreise" as const,
|
||
order: 5,
|
||
shortDescription: "Gemeinsam singen. Verbunden sein.",
|
||
description: lexicalFromParagraphs(singenImKreis.paragraphs),
|
||
},
|
||
{
|
||
slug: "singen-fuer-schwangere",
|
||
title: "Singen für Schwangere",
|
||
category: "singkreise" as const,
|
||
order: 6,
|
||
shortDescription: "Lieder, die tragen. Für dich und dein Baby.",
|
||
description: lexicalFromParagraphs(singenFuerSchwangere.paragraphs),
|
||
},
|
||
{
|
||
slug: "mama-baby-singkreis",
|
||
title: "Singen für Mamas mit Baby",
|
||
category: "singkreise" as const,
|
||
order: 7,
|
||
shortDescription: "Zeit für dich und dein Baby. Singen. Austauschen. Auftanken.",
|
||
description: lexicalFromParagraphs(mamaBabySingkreis.paragraphs),
|
||
},
|
||
{
|
||
// 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
|
||
// exactly this kind of 1:1 session in the original texte.txt.
|
||
slug: "einzelbegleitung",
|
||
title: "Einzelbegleitung",
|
||
category: "prozessbegleitung" as const,
|
||
order: 8,
|
||
visibility: "private" as const,
|
||
bookable: true,
|
||
price: "auf Anfrage",
|
||
durationMinutes: 60,
|
||
shortDescription: "Persönliche Einzelbegleitung – vor Ort oder online.",
|
||
description: lexicalFromParagraphs(prozessbegleitung.sections[0].paragraphs),
|
||
},
|
||
];
|
||
|
||
for (const entry of offers) {
|
||
const data = { visibility: "public" as const, ...entry };
|
||
const existing = await payload.find({
|
||
collection: "offers",
|
||
where: { slug: { equals: data.slug } },
|
||
limit: 1,
|
||
});
|
||
|
||
if (existing.docs[0]) {
|
||
await payload.update({ collection: "offers", id: existing.docs[0].id, data, draft: false });
|
||
console.log(` ↺ Angebot aktualisiert: ${data.title}`);
|
||
} else {
|
||
await payload.create({ collection: "offers", data, draft: false });
|
||
console.log(` + Angebot angelegt: ${data.title}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
async function seedGlobals(payload: Awaited<ReturnType<typeof getPayload>>) {
|
||
await payload.updateGlobal({
|
||
slug: "home",
|
||
data: {
|
||
heroEyebrow: "Prozessbegleitung · Doula · Gemeinschaft",
|
||
heroTitle: "Willkommen bei Anouma",
|
||
heroHighlight: ueberMich.closing.highlight,
|
||
heroSupporting: ueberMich.closing.paragraph,
|
||
aboutEyebrow: "Über mich",
|
||
aboutTitle: "Mein Weg, meine Werte und was mich bewegt",
|
||
aboutText: lexicalFromParagraphs(ueberMich.paragraphs.slice(0, 2)),
|
||
valuesEyebrow: "Philosophie",
|
||
valuesTitle: "Räume, in denen wir uns erinnern dürfen, wer wir sind",
|
||
values: [
|
||
{
|
||
title: "Vertrauen",
|
||
quote: "Alles, was wir für unseren Weg brauchen, ist bereits in uns angelegt.",
|
||
},
|
||
{
|
||
title: "Verbindung",
|
||
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." },
|
||
],
|
||
ctaTitle: "Kennenlernen & Termine vereinbaren",
|
||
ctaLead:
|
||
"Ich freue mich, von dir zu hören – schreib mir oder buche direkt ein unverbindliches Kennenlerngespräch.",
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Startseite“ gesetzt");
|
||
|
||
await payload.updateGlobal({
|
||
slug: "about",
|
||
data: {
|
||
eyebrow: "Über mich",
|
||
title: "Mein Weg, meine Werte und was mich bewegt",
|
||
body: lexicalFromParagraphs(ueberMich.paragraphs),
|
||
closingLead: ueberMich.closing.lead,
|
||
closingHighlight: ueberMich.closing.highlight,
|
||
closingParagraph: ueberMich.closing.paragraph,
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Über mich“ gesetzt");
|
||
|
||
await payload.updateGlobal({
|
||
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.",
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Angebote (Einleitung)“ gesetzt");
|
||
|
||
await payload.updateGlobal({
|
||
slug: "aktuelles-intro",
|
||
data: {
|
||
eyebrow: "Aktuelles",
|
||
title: "Neuigkeiten, Termine und Inspiration",
|
||
lead: "Hier findest du künftig aktuelle Termine, Ankündigungen und Impulse rund um die Angebote von Anouma.",
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Aktuelles (Einleitung)“ gesetzt");
|
||
|
||
await payload.updateGlobal({
|
||
slug: "contact",
|
||
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.",
|
||
// Placeholder contact details — replace with the real ones in the admin.
|
||
email: "hallo@anouma.org",
|
||
phone: "+49 000 00 00 00",
|
||
region: "Platzhalter – Ort / Region",
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Kontakt“ gesetzt (mit Platzhalter-Kontaktdaten — bitte im Admin ersetzen)");
|
||
|
||
await payload.updateGlobal({
|
||
slug: "booking",
|
||
data: {
|
||
eyebrow: "Termin buchen",
|
||
title: "Kennenlernen & Termine vereinbaren",
|
||
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.",
|
||
},
|
||
{
|
||
title: "Kennenlernen",
|
||
text: "In einem ersten, unverbindlichen Gespräch schauen wir gemeinsam, was du gerade brauchst und welcher Weg passt.",
|
||
},
|
||
{
|
||
title: "Termin vereinbaren",
|
||
text: "Passt es für euch beide, vereinbaren wir gemeinsam die weiteren Termine.",
|
||
},
|
||
],
|
||
formNote:
|
||
"Aktuell öffnet dieses Formular dein E-Mail-Programm. Sobald ein Buchungstool (z. B. für Online-Terminvergabe) ausgewählt ist, kann es hier eingebunden werden.",
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Termin buchen“ gesetzt");
|
||
|
||
await payload.updateGlobal({
|
||
slug: "cookie-settings",
|
||
data: {
|
||
consentVersion: "1.0",
|
||
necessary: {
|
||
label: "Notwendig",
|
||
description:
|
||
"Für den Betrieb der Website technisch erforderlich (z. B. Login, Sitzung). Kann nicht deaktiviert werden.",
|
||
},
|
||
preferences: {
|
||
label: "Präferenzen",
|
||
description: "Speichert Einstellungen wie z. B. bevorzugte Anzeigeoptionen.",
|
||
enabled: true,
|
||
},
|
||
statistics: {
|
||
label: "Statistik",
|
||
description:
|
||
"Anonymisierte, datensparsame Reichweitenmessung (Seitenaufrufe, Ereignisse) ohne personenbezogene Profile.",
|
||
enabled: true,
|
||
},
|
||
},
|
||
});
|
||
console.log(" ↺ Global „Cookie-Einstellungen“ gesetzt");
|
||
}
|
||
|
||
async function run() {
|
||
const payload = await getPayload({ config });
|
||
|
||
console.log("Angebote:");
|
||
await seedOffers(payload);
|
||
|
||
console.log("Seiteninhalte:");
|
||
await seedGlobals(payload);
|
||
|
||
console.log("\nFertig. Richte jetzt unter /admin den ersten Admin-Zugang ein (dort wird kein Passwort vorgegeben).");
|
||
process.exit(0);
|
||
}
|
||
|
||
await run().catch((err) => {
|
||
console.error(err);
|
||
process.exit(1);
|
||
});
|