mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 20:54:11 +00:00
Update home page layout with blog preview (posts-list-block) and contact form (contact-form-block) sections. Replace image-text-block with text-block since no media exists for tenant 13 yet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1159 lines
43 KiB
TypeScript
1159 lines
43 KiB
TypeScript
/**
|
||
* Sensualmoment (Tenant 13) Seed Script
|
||
*
|
||
* Populates tenant 13 with all content for sensualmoment.de:
|
||
* - Site Settings
|
||
* - Social Links (4)
|
||
* - Testimonials (3)
|
||
* - FAQs (12)
|
||
* - Navigation (mainMenu + footerMenu)
|
||
* - Contact Form
|
||
* - Pages (10: home, ueber-mich, galerie, pakete, journal, kontakt, faq, impressum, datenschutz, agb)
|
||
*
|
||
* Run with: npx tsx scripts/seed-sensualmoment.ts
|
||
*/
|
||
|
||
import { getPayload } from 'payload'
|
||
import config from '../src/payload.config'
|
||
|
||
const TENANT_ID = 13
|
||
|
||
// ── Rich Text Helpers (Lexical format) ──────────────────────
|
||
|
||
function createRichText(content: string | string[]): object {
|
||
const paragraphs = Array.isArray(content) ? content : [content]
|
||
return {
|
||
root: {
|
||
type: 'root',
|
||
children: paragraphs.map((text) => ({
|
||
type: 'paragraph',
|
||
children: [{ type: 'text', text }],
|
||
})),
|
||
direction: 'ltr',
|
||
format: '',
|
||
indent: 0,
|
||
version: 1,
|
||
},
|
||
}
|
||
}
|
||
|
||
function createRichTextComplex(
|
||
blocks: Array<
|
||
| { type: 'heading'; tag: string; text: string }
|
||
| { type: 'paragraph'; text: string }
|
||
| { type: 'paragraph-bold'; text: string }
|
||
| { type: 'paragraph-italic'; text: string }
|
||
| { type: 'bullets'; items: string[] }
|
||
>,
|
||
): object {
|
||
return {
|
||
root: {
|
||
type: 'root',
|
||
children: blocks.map((block) => {
|
||
if (block.type === 'heading') {
|
||
return {
|
||
type: 'heading',
|
||
tag: block.tag,
|
||
children: [{ type: 'text', text: block.text }],
|
||
}
|
||
}
|
||
if (block.type === 'paragraph-bold') {
|
||
return {
|
||
type: 'paragraph',
|
||
children: [{ type: 'text', text: block.text, format: 1 }],
|
||
}
|
||
}
|
||
if (block.type === 'paragraph-italic') {
|
||
return {
|
||
type: 'paragraph',
|
||
children: [{ type: 'text', text: block.text, format: 2 }],
|
||
}
|
||
}
|
||
if (block.type === 'bullets') {
|
||
return {
|
||
type: 'list',
|
||
listType: 'bullet',
|
||
children: block.items.map((item) => ({
|
||
type: 'listitem',
|
||
children: [{ type: 'text', text: item }],
|
||
})),
|
||
}
|
||
}
|
||
return {
|
||
type: 'paragraph',
|
||
children: [{ type: 'text', text: block.text }],
|
||
}
|
||
}),
|
||
direction: 'ltr',
|
||
format: '',
|
||
indent: 0,
|
||
version: 1,
|
||
},
|
||
}
|
||
}
|
||
|
||
// ── Helper: Upsert ──────────────────────────────────────────
|
||
|
||
async function upsert(
|
||
payload: any,
|
||
collection: string,
|
||
where: Record<string, any>,
|
||
data: Record<string, any>,
|
||
): Promise<number> {
|
||
const existing = await payload.find({
|
||
collection,
|
||
where: { ...where, tenant: { equals: TENANT_ID } },
|
||
limit: 1,
|
||
})
|
||
|
||
if (existing.docs.length > 0) {
|
||
const doc = await payload.update({
|
||
collection,
|
||
id: existing.docs[0].id,
|
||
data: { ...data, tenant: TENANT_ID },
|
||
})
|
||
return doc.id as number
|
||
}
|
||
|
||
const doc = await payload.create({
|
||
collection,
|
||
data: { ...data, tenant: TENANT_ID },
|
||
})
|
||
return doc.id as number
|
||
}
|
||
|
||
// Lightweight page upsert using direct SQL check to avoid the massive 40+ block join query
|
||
async function upsertPage(
|
||
payload: any,
|
||
slug: string,
|
||
data: Record<string, any>,
|
||
): Promise<number> {
|
||
const pool = (payload as any).db?.pool
|
||
if (!pool) throw new Error('Cannot access DB pool')
|
||
|
||
// Direct SQL with parameterized query
|
||
const result = await pool.query(
|
||
'SELECT p.id FROM pages p JOIN pages_locales pl ON pl."_parent_id" = p.id WHERE pl.slug = $1 AND p.tenant_id = $2 LIMIT 1',
|
||
[slug, TENANT_ID],
|
||
)
|
||
|
||
const existingId = result?.rows?.[0]?.id
|
||
|
||
if (existingId) {
|
||
const doc = await payload.update({
|
||
collection: 'pages',
|
||
id: existingId,
|
||
data: { ...data, tenant: TENANT_ID },
|
||
})
|
||
return doc.id as number
|
||
}
|
||
|
||
const doc = await payload.create({
|
||
collection: 'pages',
|
||
data: { ...data, tenant: TENANT_ID },
|
||
})
|
||
return doc.id as number
|
||
}
|
||
|
||
// ── Main Seed Function ──────────────────────────────────────
|
||
|
||
async function seed() {
|
||
console.log('🚀 Starting sensualmoment.de (Tenant 13) Seed...\n')
|
||
|
||
const payload = await getPayload({ config })
|
||
|
||
// Verify tenant exists
|
||
const tenant = await payload.findByID({ collection: 'tenants', id: TENANT_ID })
|
||
if (!tenant) {
|
||
console.error(`❌ Tenant ${TENANT_ID} not found!`)
|
||
process.exit(1)
|
||
}
|
||
console.log(`✓ Tenant "${tenant.name}" (ID: ${TENANT_ID}) found\n`)
|
||
|
||
// ════════════════════════════════════════════
|
||
// 1. SITE SETTINGS
|
||
// ════════════════════════════════════════════
|
||
console.log('--- 1. Site Settings ---')
|
||
|
||
await upsert(payload, 'site-settings', {}, {
|
||
siteName: 'Sensual Moment Photography',
|
||
siteTagline: 'Boudoir Photography · Dein Moment der Selbstliebe',
|
||
contact: {
|
||
email: 'hello@sensualmoment.de',
|
||
phone: '+49 123 456 78 90',
|
||
},
|
||
address: {
|
||
street: 'Musterstraße 12',
|
||
zip: '12345',
|
||
city: 'Stadt',
|
||
state: 'Nordrhein-Westfalen',
|
||
country: 'Deutschland',
|
||
},
|
||
footer: {
|
||
copyrightText: '© 2026 Sensual Moment Photography. Alle Rechte vorbehalten.',
|
||
showSocialLinks: true,
|
||
},
|
||
seo: {
|
||
defaultMetaTitle: 'Sensual Moment – Boudoir Photography',
|
||
defaultMetaDescription:
|
||
'Dein Boudoir-Shooting als Akt der Selbstliebe. Professionelle Boudoir-Fotografie in geschützter Atmosphäre. Empowerment statt Sexualisierung.',
|
||
},
|
||
})
|
||
console.log('✓ Site Settings created/updated')
|
||
|
||
// ════════════════════════════════════════════
|
||
// 2. SOCIAL LINKS
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 2. Social Links ---')
|
||
|
||
const socialLinks = [
|
||
{ platform: 'instagram', url: 'https://instagram.com/sensualmoment.de', isActive: true },
|
||
{ platform: 'facebook', url: 'https://facebook.com/sensualmoment.de', isActive: true },
|
||
]
|
||
|
||
for (const link of socialLinks) {
|
||
await upsert(payload, 'social-links', { platform: { equals: link.platform } }, link)
|
||
console.log(`✓ Social Link "${link.platform}"`)
|
||
}
|
||
|
||
// ════════════════════════════════════════════
|
||
// 3. TESTIMONIALS
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 3. Testimonials ---')
|
||
|
||
const testimonials = [
|
||
{
|
||
quote:
|
||
'Ich habe mich noch nie so schön gefühlt. Die Atmosphäre war so vertrauensvoll, dass ich komplett loslassen konnte. Die Bilder sind unfassbar.',
|
||
author: 'Sandra, 42',
|
||
role: 'Kundin',
|
||
rating: 5,
|
||
isActive: true,
|
||
order: 1,
|
||
},
|
||
{
|
||
quote:
|
||
'Anfangs war ich nervös, aber nach fünf Minuten fühlte es sich an wie ein Abend mit einer guten Freundin. Die Ergebnisse haben mich zu Tränen gerührt.',
|
||
author: 'Katrin, 38',
|
||
role: 'Kundin',
|
||
rating: 5,
|
||
isActive: true,
|
||
order: 2,
|
||
},
|
||
{
|
||
quote:
|
||
'Ein Geschenk an mich selbst, das ich jeder Frau empfehlen würde. Professionell, einfühlsam und mit unglaublichem Blick für Details.',
|
||
author: 'Maria, 51',
|
||
role: 'Kundin',
|
||
rating: 5,
|
||
isActive: true,
|
||
order: 3,
|
||
},
|
||
]
|
||
|
||
for (const t of testimonials) {
|
||
await upsert(payload, 'testimonials', { author: { equals: t.author } }, t)
|
||
console.log(`✓ Testimonial "${t.author}"`)
|
||
}
|
||
|
||
// ════════════════════════════════════════════
|
||
// 4. FAQS
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 4. FAQs ---')
|
||
|
||
const faqs = [
|
||
// Vor dem Shooting
|
||
{
|
||
question: 'Wie läuft ein Boudoir-Shooting ab?',
|
||
answer: createRichText([
|
||
'Wir starten mit einem kostenlosen Vorgespräch, in dem wir deine Wünsche und Vorstellungen besprechen. Am Tag des Shootings wirst du professionell gestylt und dann entspannt in verschiedenen Posen fotografiert.',
|
||
'Die Atmosphäre ist immer vertrauensvoll und respektvoll. Du bestimmst jederzeit, wie weit du gehen möchtest. Nach dem Shooting wählst du deine Lieblingsbilder in einer persönlichen Bildauswahl-Session.',
|
||
]),
|
||
category: 'vor-dem-shooting',
|
||
order: 1,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Was soll ich zum Shooting mitbringen?',
|
||
answer: createRichText([
|
||
'Bring 3–5 Outfits mit, die dir ein gutes Gefühl geben: Dessous, ein übergroßes Hemd, ein schönes Kleid oder auch nur ein Tuch. Weniger ist oft mehr.',
|
||
'Außerdem empfehle ich bequeme Schuhe für die Anreise, deine Lieblingsmusik und gute Laune. Alles andere – von Styling bis Requisiten – ist vor Ort vorhanden.',
|
||
]),
|
||
category: 'vor-dem-shooting',
|
||
order: 2,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Muss ich Model-Erfahrung haben?',
|
||
answer: createRichText(
|
||
'Absolut nicht! Die allermeisten meiner Kundinnen stehen zum ersten Mal vor einer professionellen Kamera. Ich leite dich durch jede Pose und sorge dafür, dass du dich wohl fühlst. Es geht nicht um perfekte Posen, sondern um echte Momente.',
|
||
),
|
||
category: 'vor-dem-shooting',
|
||
order: 3,
|
||
isActive: true,
|
||
},
|
||
// Während des Shootings
|
||
{
|
||
question: 'Wie lange dauert ein Shooting?',
|
||
answer: createRichText(
|
||
'Je nach Paket dauert das Shooting zwischen 60 Minuten und einem halben Tag. Ich nehme mir immer genug Zeit, damit du ankommen und dich entspannen kannst. Wir arbeiten ohne Zeitdruck.',
|
||
),
|
||
category: 'waehrend-des-shootings',
|
||
order: 4,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Kann ich eine Begleitperson mitbringen?',
|
||
answer: createRichText(
|
||
'Natürlich! Viele Kundinnen bringen ihre beste Freundin oder Partnerin mit. Wichtig ist, dass du dich wohl fühlst. In meinem Studio ist auch ein separater Wartebereich vorhanden.',
|
||
),
|
||
category: 'waehrend-des-shootings',
|
||
order: 5,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Was ist, wenn ich mich unwohl fühle?',
|
||
answer: createRichText(
|
||
'Dein Wohlbefinden hat absolute Priorität. Wir machen jederzeit Pausen, du kannst jede Pose ablehnen und wir besprechen vorher genau, was für dich okay ist und was nicht. Du hast immer die volle Kontrolle.',
|
||
),
|
||
category: 'waehrend-des-shootings',
|
||
order: 6,
|
||
isActive: true,
|
||
},
|
||
// Nachher
|
||
{
|
||
question: 'Wann bekomme ich meine Bilder?',
|
||
answer: createRichText(
|
||
'Innerhalb von 2–3 Wochen nach dem Shooting lade ich deine fertig bearbeiteten Bilder in deine private Online-Galerie hoch. Dort kannst du in Ruhe deine Favoriten auswählen und Abzüge oder ein Fotobuch bestellen.',
|
||
),
|
||
category: 'nachher',
|
||
order: 7,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Werden die Bilder retuschiert?',
|
||
answer: createRichText(
|
||
'Jedes Bild wird professionell bearbeitet: Licht, Farbe und Kontraste werden optimiert. Auf Wunsch entferne ich temporäre Hautunreinheiten. Ich stehe für eine natürliche Bearbeitung – du sollst dich auf den Bildern wiedererkennen, nicht wie eine andere Person aussehen.',
|
||
),
|
||
category: 'nachher',
|
||
order: 8,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Dürfen die Bilder veröffentlicht werden?',
|
||
answer: createRichText(
|
||
'Niemals ohne deine ausdrückliche, schriftliche Einwilligung. Deine Bilder sind privat und bleiben es auch. Wenn du möchtest, dass ausgewählte Bilder in meinem Portfolio erscheinen, besprechen wir das individuell.',
|
||
),
|
||
category: 'nachher',
|
||
order: 9,
|
||
isActive: true,
|
||
},
|
||
// Allgemein
|
||
{
|
||
question: 'Was kostet ein Boudoir-Shooting?',
|
||
answer: createRichText([
|
||
'Meine Pakete starten ab 299 € (Entdecken), über 499 € (Erleben – das beliebteste Paket) bis 799 € (Zelebrieren – der halbe Tag).',
|
||
'Jedes Paket beinhaltet Styling-Beratung, professionelle Bearbeitung und eine private Online-Galerie. Details findest du auf meiner Pakete-Seite.',
|
||
]),
|
||
category: 'allgemein',
|
||
order: 10,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Gibt es Geschenkgutscheine?',
|
||
answer: createRichText(
|
||
'Ja! Ein Boudoir-Shooting ist ein wundervolles Geschenk. Ich erstelle dir einen personalisierten Geschenkgutschein für jedes Paket. Schreib mir einfach eine Nachricht.',
|
||
),
|
||
category: 'allgemein',
|
||
order: 11,
|
||
isActive: true,
|
||
},
|
||
{
|
||
question: 'Wo findet das Shooting statt?',
|
||
answer: createRichText(
|
||
'Die Shootings finden in meinem privaten Studio statt – ein geschützter, warmer Raum, der speziell für Boudoir-Fotografie eingerichtet ist. Auf Wunsch sind auch Outdoor- oder Hotel-Shootings möglich (Aufpreis nach Absprache).',
|
||
),
|
||
category: 'allgemein',
|
||
order: 12,
|
||
isActive: true,
|
||
},
|
||
]
|
||
|
||
for (const faq of faqs) {
|
||
await upsert(payload, 'faqs', { question: { equals: faq.question } }, faq)
|
||
console.log(`✓ FAQ "${faq.question.substring(0, 40)}..."`)
|
||
}
|
||
|
||
// ════════════════════════════════════════════
|
||
// 5. NAVIGATION
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 5. Navigation ---')
|
||
|
||
await upsert(payload, 'navigations', {}, {
|
||
title: 'Hauptnavigation',
|
||
mainMenu: [
|
||
{ label: 'Über mich', type: 'custom', url: '/ueber-mich' },
|
||
{ label: 'Galerie', type: 'custom', url: '/galerie' },
|
||
{ label: 'Pakete', type: 'custom', url: '/pakete' },
|
||
{ label: 'Journal', type: 'custom', url: '/journal' },
|
||
{ label: 'FAQ', type: 'custom', url: '/faq' },
|
||
{ label: 'Kontakt', type: 'custom', url: '/kontakt' },
|
||
],
|
||
footerMenu: [
|
||
{ label: 'Impressum', linkType: 'custom', url: '/impressum' },
|
||
{ label: 'Datenschutz', linkType: 'custom', url: '/datenschutz' },
|
||
{ label: 'AGB', linkType: 'custom', url: '/agb' },
|
||
],
|
||
})
|
||
console.log('✓ Navigation created/updated')
|
||
|
||
// ════════════════════════════════════════════
|
||
// 6. CONTACT FORM
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 6. Contact Form ---')
|
||
|
||
const existingForm = await payload.find({
|
||
collection: 'forms',
|
||
where: { tenant: { equals: TENANT_ID } },
|
||
limit: 1,
|
||
})
|
||
|
||
let contactFormId: number | null = null
|
||
|
||
if (existingForm.docs.length > 0) {
|
||
contactFormId = existingForm.docs[0].id as number
|
||
console.log(`✓ Contact form already exists (ID: ${contactFormId})`)
|
||
} else {
|
||
const form = await payload.create({
|
||
collection: 'forms',
|
||
data: {
|
||
title: 'Kontaktformular',
|
||
tenant: TENANT_ID,
|
||
fields: [
|
||
{
|
||
blockType: 'text',
|
||
name: 'name',
|
||
label: 'Name',
|
||
required: true,
|
||
width: 50,
|
||
},
|
||
{
|
||
blockType: 'email',
|
||
name: 'email',
|
||
label: 'E-Mail',
|
||
required: true,
|
||
width: 50,
|
||
},
|
||
{
|
||
blockType: 'text',
|
||
name: 'phone',
|
||
label: 'Telefon (optional)',
|
||
required: false,
|
||
width: 50,
|
||
},
|
||
{
|
||
blockType: 'select',
|
||
name: 'paket',
|
||
label: 'Welches Paket interessiert dich?',
|
||
required: false,
|
||
width: 50,
|
||
options: [
|
||
{ label: 'Entdecken (ab 299 €)', value: 'entdecken' },
|
||
{ label: 'Erleben (ab 499 €)', value: 'erleben' },
|
||
{ label: 'Zelebrieren (ab 799 €)', value: 'zelebrieren' },
|
||
{ label: 'Noch unsicher', value: 'unsicher' },
|
||
],
|
||
},
|
||
{
|
||
blockType: 'textarea',
|
||
name: 'message',
|
||
label: 'Deine Nachricht',
|
||
required: true,
|
||
width: 100,
|
||
},
|
||
],
|
||
submitButtonLabel: 'Nachricht senden',
|
||
confirmationType: 'message',
|
||
confirmationMessage: createRichText(
|
||
'Vielen Dank für deine Nachricht! Ich melde mich innerhalb von 24 Stunden bei dir. Ich freue mich auf unser Kennenlernen.',
|
||
),
|
||
} as any,
|
||
})
|
||
contactFormId = form.id as number
|
||
console.log(`✓ Contact form created (ID: ${contactFormId})`)
|
||
}
|
||
|
||
// ════════════════════════════════════════════
|
||
// 7. PAGES
|
||
// ════════════════════════════════════════════
|
||
console.log('\n--- 7. Pages ---')
|
||
|
||
const pages = [
|
||
// ── Home ──
|
||
{
|
||
title: 'Startseite',
|
||
slug: 'home',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Sensual Moment',
|
||
subline: 'Boudoir Photography · Dein Moment der Selbstliebe',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
cta: {
|
||
text: 'Dein Shooting buchen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
},
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h2', text: 'Jede Frau verdient es, sich selbst zu feiern' },
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Ich glaube daran, dass wahre Schönheit nicht inszeniert werden muss – sie muss nur sichtbar gemacht werden. In meinem Studio schaffe ich einen geschützten Raum, in dem du dich fallen lassen kannst.',
|
||
},
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Mit einfühlsamer Anleitung und einem Blick für das Besondere entstehen Bilder, die deine Stärke, Sinnlichkeit und Einzigartigkeit einfangen – authentisch und mit Respekt.',
|
||
},
|
||
]),
|
||
},
|
||
{
|
||
blockType: 'testimonials-block',
|
||
title: 'Was meine Kundinnen sagen',
|
||
subtitle: 'Erfahrungen',
|
||
displayMode: 'all',
|
||
layout: 'grid',
|
||
columns: '3',
|
||
showRating: false,
|
||
showQuoteIcon: true,
|
||
backgroundColor: 'light',
|
||
},
|
||
{
|
||
blockType: 'pricing',
|
||
title: 'Pakete & Preise',
|
||
subtitle: 'Investition in dich',
|
||
pricingType: 'one-time',
|
||
currency: '€',
|
||
showCurrencyBefore: false,
|
||
layout: 'cards',
|
||
plans: [
|
||
{
|
||
name: 'Entdecken',
|
||
price: 299,
|
||
priceLabel: 'Ab 299 €',
|
||
description: 'Der perfekte Einstieg in die Welt der Boudoir-Fotografie.',
|
||
featured: false,
|
||
features: [
|
||
{ text: '60 Min. Shooting', included: true },
|
||
{ text: 'Styling-Beratung vorab', included: true },
|
||
{ text: '10 bearbeitete Bilder', included: true },
|
||
{ text: 'Private Online-Galerie', included: true },
|
||
{ text: '5 Feinabzüge 13×18', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
{
|
||
name: 'Erleben',
|
||
price: 499,
|
||
priceLabel: 'Ab 499 €',
|
||
description: 'Das beliebteste Paket für ein unvergessliches Erlebnis.',
|
||
featured: true,
|
||
badge: 'Beliebtestes Paket',
|
||
features: [
|
||
{ text: '120 Min. Shooting', included: true },
|
||
{ text: 'Professionelles Styling', included: true },
|
||
{ text: '25 bearbeitete Bilder', included: true },
|
||
{ text: 'Private Online-Galerie', included: true },
|
||
{ text: 'Hochwertiges Fotobuch', included: true },
|
||
{ text: 'Alle digitalen Dateien', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
{
|
||
name: 'Zelebrieren',
|
||
price: 799,
|
||
priceLabel: 'Ab 799 €',
|
||
description: 'Das ultimative Erlebnis für besondere Momente.',
|
||
featured: false,
|
||
features: [
|
||
{ text: 'Halber Tag (4 Std.)', included: true },
|
||
{ text: 'Styling + Visagistin', included: true },
|
||
{ text: 'Alle bearbeiteten Bilder', included: true },
|
||
{ text: 'Luxus-Leinenalbum', included: true },
|
||
{ text: '3 Wandbilder nach Wahl', included: true },
|
||
{ text: 'Behind-the-Scenes Video', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
],
|
||
style: {
|
||
bg: 'dark',
|
||
cardStyle: 'bordered',
|
||
},
|
||
},
|
||
{
|
||
blockType: 'posts-list-block',
|
||
title: 'Gedanken & Geschichten',
|
||
postType: 'blog',
|
||
layout: 'grid',
|
||
columns: '3',
|
||
limit: 3,
|
||
showExcerpt: true,
|
||
showDate: true,
|
||
showAuthor: false,
|
||
},
|
||
{
|
||
blockType: 'cta-block',
|
||
headline: 'Bereit für deinen Moment?',
|
||
description:
|
||
'Schreib mir unverbindlich – ich melde mich innerhalb von 24 Stunden bei dir. Gemeinsam besprechen wir in einem kostenlosen Vorgespräch, wie dein perfektes Shooting aussehen kann.',
|
||
backgroundColor: 'accent',
|
||
buttons: [
|
||
{
|
||
text: 'Jetzt Shooting buchen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
blockType: 'contact-form-block',
|
||
form: contactFormId,
|
||
headline: 'Bereit für deinen Moment?',
|
||
description:
|
||
'Ich freue mich darauf, dich kennenzulernen und gemeinsam deinen ganz persönlichen Moment zu gestalten. Schreib mir oder ruf mich an – unverbindlich und vertraulich.',
|
||
successMessage: 'Vielen Dank!',
|
||
showContactInfo: true,
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Sensual Moment – Boudoir Photography · Dein Moment der Selbstliebe',
|
||
metaDescription:
|
||
'Professionelle Boudoir-Fotografie in geschützter Atmosphäre. Empowerment statt Sexualisierung. Jetzt dein Shooting buchen.',
|
||
},
|
||
},
|
||
|
||
// ── Über mich ──
|
||
{
|
||
title: 'Über mich',
|
||
slug: 'ueber-mich',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Über mich',
|
||
subline: 'Die Frau hinter der Kamera',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h2', text: 'Meine Geschichte' },
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Mein Name ist [Dein Name] und ich bin leidenschaftliche Boudoir-Fotografin. Was als persönliches Projekt begann, ist heute meine Berufung: Frauen dabei zu helfen, sich in ihrer Haut wohlzufühlen und ihre einzigartige Schönheit zu entdecken.',
|
||
},
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Jedes Shooting ist für mich eine Begegnung auf Augenhöhe. Ich schaffe einen Raum des Vertrauens, in dem du dich fallen lassen kannst – ohne Druck, ohne Erwartungen, ganz in deinem Tempo.',
|
||
},
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Boudoir-Fotografie ist für mich kein Genre – es ist eine Haltung. Es geht darum, die Stärke, Verletzlichkeit und Sinnlichkeit jeder einzelnen Frau sichtbar zu machen. Authentisch, respektvoll und mit Liebe zum Detail.',
|
||
},
|
||
]),
|
||
},
|
||
{
|
||
blockType: 'card-grid-block',
|
||
headline: 'Meine Werte',
|
||
columns: '3',
|
||
cards: [
|
||
{
|
||
mediaType: 'icon',
|
||
icon: 'heart',
|
||
iconPosition: 'top',
|
||
title: 'Empathie',
|
||
description: 'Ich begegne jeder Kundin mit Wärme und Einfühlungsvermögen. Dein Wohlbefinden steht immer an erster Stelle.',
|
||
},
|
||
{
|
||
mediaType: 'icon',
|
||
icon: 'shield',
|
||
iconPosition: 'top',
|
||
title: 'Vertrauen',
|
||
description: 'Was im Studio passiert, bleibt im Studio. Deine Bilder werden niemals ohne deine ausdrückliche Zustimmung geteilt.',
|
||
},
|
||
{
|
||
mediaType: 'icon',
|
||
icon: 'star',
|
||
iconPosition: 'top',
|
||
title: 'Authentizität',
|
||
description: 'Keine übertriebene Retusche, keine aufgesetzten Posen. Ich zeige dich, wie du wirklich bist – und das ist wunderschön.',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
blockType: 'cta-block',
|
||
headline: 'Lass uns kennenlernen',
|
||
description: 'In einem kostenlosen Vorgespräch erzähle ich dir mehr über meine Arbeit und wir besprechen deine Wünsche.',
|
||
backgroundColor: 'dark',
|
||
buttons: [
|
||
{
|
||
text: 'Kontakt aufnehmen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
],
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Über mich – Sensual Moment Photography',
|
||
metaDescription:
|
||
'Lerne die Fotografin hinter Sensual Moment kennen. Professionelle Boudoir-Fotografie mit Herz, Empathie und einem Blick für das Besondere.',
|
||
},
|
||
},
|
||
|
||
// ── Galerie ──
|
||
{
|
||
title: 'Galerie',
|
||
slug: 'galerie',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Portfolio',
|
||
subline: 'Momente der Selbstliebe – ausgewählte Arbeiten mit Einverständnis meiner Kundinnen',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Jedes Bild erzählt eine Geschichte von Mut, Verletzlichkeit und Stärke. Hier findest du eine Auswahl meiner Arbeiten in verschiedenen Stilen – von klassisch elegant bis künstlerisch dramatisch.',
|
||
},
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Alle Bilder werden ausschließlich mit dem ausdrücklichen Einverständnis meiner Kundinnen gezeigt.',
|
||
},
|
||
]),
|
||
},
|
||
{
|
||
blockType: 'cta-block',
|
||
headline: 'Möchtest du auch so strahlen?',
|
||
description: 'Jede Frau hat ihre eigene Geschichte. Lass uns gemeinsam deine erzählen.',
|
||
backgroundColor: 'accent',
|
||
buttons: [
|
||
{
|
||
text: 'Shooting buchen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
],
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Galerie – Sensual Moment Boudoir Portfolio',
|
||
metaDescription:
|
||
'Entdecke ausgewählte Boudoir-Fotografien: klassisch, artistisch, elegant, natürlich. Jedes Bild erzählt eine Geschichte von Stärke und Sinnlichkeit.',
|
||
},
|
||
},
|
||
|
||
// ── Pakete & Preise ──
|
||
{
|
||
title: 'Pakete & Preise',
|
||
slug: 'pakete',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Investition in dich',
|
||
subline: 'Wähle das Paket, das zu dir passt – jedes Shooting ist ein Geschenk an dich selbst.',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichText(
|
||
'Jedes Paket ist so gestaltet, dass du dich von Anfang an wohlfühlst. Von der Styling-Beratung vorab bis zur fertigen Online-Galerie – alles ist inklusive. Du musst dich um nichts kümmern, außer dich auf deinen Moment zu freuen.',
|
||
),
|
||
},
|
||
{
|
||
blockType: 'pricing',
|
||
title: 'Meine Pakete',
|
||
pricingType: 'one-time',
|
||
currency: '€',
|
||
showCurrencyBefore: false,
|
||
layout: 'cards',
|
||
plans: [
|
||
{
|
||
name: 'Entdecken',
|
||
price: 299,
|
||
priceLabel: 'Ab 299 €',
|
||
description: 'Der perfekte Einstieg.',
|
||
featured: false,
|
||
features: [
|
||
{ text: '60 Min. Shooting', included: true },
|
||
{ text: 'Styling-Beratung vorab', included: true },
|
||
{ text: '10 bearbeitete Bilder', included: true },
|
||
{ text: 'Private Online-Galerie', included: true },
|
||
{ text: '5 Feinabzüge 13×18', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
{
|
||
name: 'Erleben',
|
||
price: 499,
|
||
priceLabel: 'Ab 499 €',
|
||
description: 'Das beliebteste Paket.',
|
||
featured: true,
|
||
badge: 'Beliebtestes Paket',
|
||
features: [
|
||
{ text: '120 Min. Shooting', included: true },
|
||
{ text: 'Professionelles Styling', included: true },
|
||
{ text: '25 bearbeitete Bilder', included: true },
|
||
{ text: 'Private Online-Galerie', included: true },
|
||
{ text: 'Hochwertiges Fotobuch', included: true },
|
||
{ text: 'Alle digitalen Dateien', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
{
|
||
name: 'Zelebrieren',
|
||
price: 799,
|
||
priceLabel: 'Ab 799 €',
|
||
description: 'Das ultimative Erlebnis.',
|
||
featured: false,
|
||
features: [
|
||
{ text: 'Halber Tag (4 Std.)', included: true },
|
||
{ text: 'Styling + Visagistin', included: true },
|
||
{ text: 'Alle bearbeiteten Bilder', included: true },
|
||
{ text: 'Luxus-Leinenalbum', included: true },
|
||
{ text: '3 Wandbilder nach Wahl', included: true },
|
||
{ text: 'Behind-the-Scenes Video', included: true },
|
||
],
|
||
cta: { text: 'Anfragen', link: '/kontakt' },
|
||
},
|
||
],
|
||
style: {
|
||
bg: 'dark',
|
||
cardStyle: 'bordered',
|
||
},
|
||
},
|
||
{
|
||
blockType: 'faq-block',
|
||
title: 'Häufige Fragen zu Paketen & Preisen',
|
||
sourceMode: 'collection',
|
||
displayMode: 'category',
|
||
category: 'allgemein',
|
||
layout: 'accordion',
|
||
expandFirst: true,
|
||
allowMultipleOpen: false,
|
||
enableSchemaOrg: true,
|
||
backgroundColor: 'light',
|
||
},
|
||
{
|
||
blockType: 'cta-block',
|
||
headline: 'Noch Fragen?',
|
||
description: 'Jedes Shooting ist individuell. Schreib mir und wir finden gemeinsam das perfekte Paket für dich.',
|
||
backgroundColor: 'dark',
|
||
buttons: [
|
||
{
|
||
text: 'Unverbindlich anfragen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
],
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Pakete & Preise – Boudoir-Shooting bei Sensual Moment',
|
||
metaDescription:
|
||
'Boudoir-Shooting ab 299 €. Drei Pakete für jeden Anspruch: Entdecken, Erleben, Zelebrieren. Professionelles Styling und bearbeitete Bilder inklusive.',
|
||
},
|
||
},
|
||
|
||
// ── Journal (Blog) ──
|
||
{
|
||
title: 'Journal',
|
||
slug: 'journal',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Journal',
|
||
subline: 'Gedanken & Geschichten rund um Boudoir, Selbstliebe und Empowerment',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'posts-list-block',
|
||
title: 'Aktuelle Beiträge',
|
||
displayMode: 'latest',
|
||
columns: '3',
|
||
showImage: true,
|
||
showDate: true,
|
||
showExcerpt: true,
|
||
showAuthor: false,
|
||
postsPerPage: 9,
|
||
layout: 'grid',
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Journal – Sensual Moment Blog',
|
||
metaDescription:
|
||
'Tipps fürs Boudoir-Shooting, Behind-the-Scenes-Einblicke und Geschichten über Selbstliebe. Der Blog von Sensual Moment Photography.',
|
||
},
|
||
},
|
||
|
||
// ── Kontakt ──
|
||
{
|
||
title: 'Kontakt',
|
||
slug: 'kontakt',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Kontakt',
|
||
subline: 'Bereit für deinen Moment? Schreib mir unverbindlich.',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{
|
||
type: 'paragraph',
|
||
text: 'Ich melde mich innerhalb von 24 Stunden bei dir. Gemeinsam besprechen wir in einem kostenlosen Vorgespräch, wie dein perfektes Shooting aussehen kann.',
|
||
},
|
||
]),
|
||
},
|
||
...(contactFormId
|
||
? [
|
||
{
|
||
blockType: 'contact-form-block',
|
||
form: contactFormId,
|
||
headline: 'Schreib mir',
|
||
},
|
||
]
|
||
: []),
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h3', text: 'Kontaktdaten' },
|
||
{ type: 'paragraph', text: 'E-Mail: hello@sensualmoment.de' },
|
||
{ type: 'paragraph', text: 'Telefon: +49 123 456 78 90' },
|
||
{ type: 'paragraph', text: 'Studio: Musterstraße 12, 12345 Stadt' },
|
||
{ type: 'heading', tag: 'h3', text: 'Social Media' },
|
||
{ type: 'paragraph', text: 'Instagram · Pinterest · Facebook' },
|
||
]),
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Kontakt – Sensual Moment Photography',
|
||
metaDescription:
|
||
'Nimm Kontakt auf für dein persönliches Boudoir-Shooting. Kostenloses Vorgespräch, unverbindliche Anfrage. Ich freue mich auf dich.',
|
||
},
|
||
},
|
||
|
||
// ── FAQ ──
|
||
{
|
||
title: 'FAQ – Häufige Fragen',
|
||
slug: 'faq',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'hero-block',
|
||
headline: 'Häufige Fragen',
|
||
subline: 'Alles, was du vor deinem Boudoir-Shooting wissen möchtest',
|
||
alignment: 'center',
|
||
overlay: true,
|
||
},
|
||
{
|
||
blockType: 'faq-block',
|
||
title: 'Vor dem Shooting',
|
||
sourceMode: 'collection',
|
||
displayMode: 'category',
|
||
category: 'vor-dem-shooting',
|
||
layout: 'accordion',
|
||
expandFirst: true,
|
||
allowMultipleOpen: false,
|
||
enableSchemaOrg: true,
|
||
backgroundColor: 'white',
|
||
},
|
||
{
|
||
blockType: 'faq-block',
|
||
title: 'Während des Shootings',
|
||
sourceMode: 'collection',
|
||
displayMode: 'category',
|
||
category: 'waehrend-des-shootings',
|
||
layout: 'accordion',
|
||
expandFirst: false,
|
||
enableSchemaOrg: true,
|
||
backgroundColor: 'light',
|
||
},
|
||
{
|
||
blockType: 'faq-block',
|
||
title: 'Nach dem Shooting',
|
||
sourceMode: 'collection',
|
||
displayMode: 'category',
|
||
category: 'nachher',
|
||
layout: 'accordion',
|
||
expandFirst: false,
|
||
enableSchemaOrg: true,
|
||
backgroundColor: 'white',
|
||
},
|
||
{
|
||
blockType: 'faq-block',
|
||
title: 'Allgemeines',
|
||
sourceMode: 'collection',
|
||
displayMode: 'category',
|
||
category: 'allgemein',
|
||
layout: 'accordion',
|
||
expandFirst: false,
|
||
enableSchemaOrg: true,
|
||
backgroundColor: 'light',
|
||
},
|
||
{
|
||
blockType: 'cta-block',
|
||
headline: 'Deine Frage nicht dabei?',
|
||
description: 'Schreib mir – ich beantworte alle Fragen gerne persönlich.',
|
||
backgroundColor: 'dark',
|
||
buttons: [
|
||
{
|
||
text: 'Kontakt aufnehmen',
|
||
link: '/kontakt',
|
||
style: 'primary',
|
||
},
|
||
],
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'FAQ – Häufige Fragen zum Boudoir-Shooting',
|
||
metaDescription:
|
||
'Antworten auf alle Fragen rund um dein Boudoir-Shooting: Ablauf, Vorbereitung, Kosten, Bildbearbeitung und mehr.',
|
||
},
|
||
},
|
||
|
||
// ── Impressum ──
|
||
{
|
||
title: 'Impressum',
|
||
slug: 'impressum',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h1', text: 'Impressum' },
|
||
{ type: 'heading', tag: 'h2', text: 'Angaben gemäß § 5 TMG' },
|
||
{ type: 'paragraph', text: '[Dein Name]' },
|
||
{ type: 'paragraph', text: 'Sensual Moment Photography' },
|
||
{ type: 'paragraph', text: 'Musterstraße 12' },
|
||
{ type: 'paragraph', text: '12345 Stadt' },
|
||
{ type: 'heading', tag: 'h2', text: 'Kontakt' },
|
||
{ type: 'paragraph', text: 'E-Mail: hello@sensualmoment.de' },
|
||
{ type: 'paragraph', text: 'Telefon: +49 123 456 78 90' },
|
||
{ type: 'heading', tag: 'h2', text: 'Umsatzsteuer-ID' },
|
||
{ type: 'paragraph', text: 'Umsatzsteuer-Identifikationsnummer gemäß § 27a Umsatzsteuergesetz: [Deine USt-IdNr.]' },
|
||
{ type: 'heading', tag: 'h2', text: 'Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV' },
|
||
{ type: 'paragraph', text: '[Dein Name], Musterstraße 12, 12345 Stadt' },
|
||
]),
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Impressum – Sensual Moment Photography',
|
||
metaDescription: 'Impressum und rechtliche Angaben von Sensual Moment Photography.',
|
||
},
|
||
},
|
||
|
||
// ── Datenschutz ──
|
||
{
|
||
title: 'Datenschutz',
|
||
slug: 'datenschutz',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h1', text: 'Datenschutzerklärung' },
|
||
{ type: 'heading', tag: 'h2', text: '1. Datenschutz auf einen Blick' },
|
||
{ type: 'paragraph', text: 'Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese Website besuchen.' },
|
||
{ type: 'heading', tag: 'h2', text: '2. Verantwortliche Stelle' },
|
||
{ type: 'paragraph', text: '[Dein Name], Sensual Moment Photography, Musterstraße 12, 12345 Stadt. E-Mail: hello@sensualmoment.de' },
|
||
{ type: 'heading', tag: 'h2', text: '3. Datenerfassung auf dieser Website' },
|
||
{ type: 'paragraph', text: 'Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Kontaktdaten finden Sie im Impressum.' },
|
||
{ type: 'heading', tag: 'h2', text: '4. Ihre Rechte' },
|
||
{ type: 'paragraph', text: 'Sie haben jederzeit das Recht auf Auskunft, Berichtigung und Löschung Ihrer gespeicherten Daten. Wenden Sie sich dazu an die oben genannte verantwortliche Stelle.' },
|
||
{ type: 'paragraph', text: '[Vollständige Datenschutzerklärung wird vom Rechtsanwalt erstellt und hier eingefügt.]' },
|
||
]),
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'Datenschutz – Sensual Moment Photography',
|
||
metaDescription: 'Datenschutzerklärung von Sensual Moment Photography.',
|
||
},
|
||
},
|
||
|
||
// ── AGB ──
|
||
{
|
||
title: 'Allgemeine Geschäftsbedingungen',
|
||
slug: 'agb',
|
||
status: 'published',
|
||
layout: [
|
||
{
|
||
blockType: 'text-block',
|
||
content: createRichTextComplex([
|
||
{ type: 'heading', tag: 'h1', text: 'Allgemeine Geschäftsbedingungen' },
|
||
{ type: 'heading', tag: 'h2', text: '§ 1 Geltungsbereich' },
|
||
{ type: 'paragraph', text: 'Diese Allgemeinen Geschäftsbedingungen gelten für alle Verträge zwischen Sensual Moment Photography ([Dein Name]) und ihren Kundinnen.' },
|
||
{ type: 'heading', tag: 'h2', text: '§ 2 Buchung und Vertragsschluss' },
|
||
{ type: 'paragraph', text: 'Eine Buchung kommt durch schriftliche Bestätigung (E-Mail) seitens der Fotografin zustande. Eine Anzahlung von 50% des Paketpreises ist innerhalb von 7 Tagen nach Buchungsbestätigung fällig.' },
|
||
{ type: 'heading', tag: 'h2', text: '§ 3 Stornierung' },
|
||
{ type: 'paragraph', text: 'Stornierungen sind bis 14 Tage vor dem Shooting kostenfrei möglich. Bei späterer Stornierung wird die Anzahlung einbehalten. Terminverschiebungen sind einmalig kostenfrei möglich.' },
|
||
{ type: 'heading', tag: 'h2', text: '§ 4 Bildrechte und Veröffentlichung' },
|
||
{ type: 'paragraph', text: 'Die Fotografin behält das Urheberrecht an allen Aufnahmen. Eine Veröffentlichung durch die Fotografin erfolgt ausschließlich mit schriftlicher Einwilligung der Kundin.' },
|
||
{ type: 'paragraph', text: '[Vollständige AGB werden vom Rechtsanwalt erstellt und hier eingefügt.]' },
|
||
]),
|
||
},
|
||
],
|
||
seo: {
|
||
metaTitle: 'AGB – Sensual Moment Photography',
|
||
metaDescription: 'Allgemeine Geschäftsbedingungen von Sensual Moment Photography.',
|
||
},
|
||
},
|
||
]
|
||
|
||
let pageCount = 0
|
||
for (const page of pages) {
|
||
await upsertPage(payload, page.slug, page)
|
||
console.log(`✓ Page "${page.title}" (/${page.slug})`)
|
||
pageCount++
|
||
}
|
||
|
||
// ════════════════════════════════════════════
|
||
// SUMMARY
|
||
// ════════════════════════════════════════════
|
||
console.log('\n════════════════════════════════════════════')
|
||
console.log('✅ Sensualmoment.de Seed complete!')
|
||
console.log('════════════════════════════════════════════')
|
||
console.log(` - Site Settings: 1`)
|
||
console.log(` - Social Links: ${socialLinks.length}`)
|
||
console.log(` - Testimonials: ${testimonials.length}`)
|
||
console.log(` - FAQs: ${faqs.length}`)
|
||
console.log(` - Navigation: 1`)
|
||
console.log(` - Contact Form: 1 (ID: ${contactFormId})`)
|
||
console.log(` - Pages: ${pageCount}`)
|
||
console.log('')
|
||
|
||
process.exit(0)
|
||
}
|
||
|
||
seed().catch((err) => {
|
||
console.error('❌ Seed failed:', err)
|
||
process.exit(1)
|
||
})
|