Files
anouma/scripts/seed.ts
T
maro e26da639ce
CI / test (push) Canceled after 0s
CI / build-image (push) Canceled after 0s
fix: add missing globals migration and await seed
2026-09-16 21:23:55 +02:00

266 lines
9.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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);
});