#!/usr/bin/env node /* * LM USA — Seed Script * * Usage: * PAYLOAD_URL=http://localhost:3000 PAYLOAD_API_KEY=your-key node seed.mjs * * Creates: * - Contact form * - Home page / * - Virtuell Fiber /virtuell-fiber * - VPS Server /vps * - Contact /contact * - Header navigation * - Footer */ const PAYLOAD_URL = process.env.PAYLOAD_URL || 'http://localhost:3000' const API_KEY = process.env.PAYLOAD_API_KEY if (!API_KEY) { console.error('❌ Missing PAYLOAD_API_KEY environment variable') process.exit(1) } const headers = { 'Content-Type': 'application/json', Authorization: `users API-Key ${API_KEY}`, } // ─── Helpers ────────────────────────────────────────────────────────────────── function richText(text) { const paragraphs = text.split('\n').filter(Boolean) return { root: { type: 'root', children: paragraphs.map((p) => ({ type: 'paragraph', children: [ { type: 'text', text: p, format: 0, detail: 0, mode: 'normal', style: '', version: 1 }, ], direction: 'ltr', format: '', indent: 0, version: 1, })), direction: 'ltr', format: '', indent: 0, version: 1, }, } } async function apiPost(collection, data) { const res = await fetch(`${PAYLOAD_URL}/api/${collection}`, { method: 'POST', headers, body: JSON.stringify(data), }) if (!res.ok) { const err = await res.text() throw new Error(`POST /api/${collection} failed (${res.status}): ${err}`) } return res.json() } async function apiGet(collection, query = '') { const res = await fetch(`${PAYLOAD_URL}/api/${collection}${query}`, { headers }) if (!res.ok) { const err = await res.text() throw new Error(`GET /api/${collection} failed (${res.status}): ${err}`) } return res.json() } async function apiUpdateGlobal(slug, data) { const res = await fetch(`${PAYLOAD_URL}/api/globals/${slug}`, { method: 'POST', headers, body: JSON.stringify(data), }) if (!res.ok) { const err = await res.text() throw new Error(`POST /api/globals/${slug} failed (${res.status}): ${err}`) } return res.json() } async function createPageIfNotExists(slug, data) { const existing = await apiGet('pages', `?where[slug][equals]=${slug}&limit=1`) if (existing.docs?.length > 0) { console.log(` ⏭ Page "${slug}" already exists — skipping`) return existing.docs[0] } const result = await apiPost('pages', data) return result.doc } // ─── Main ───────────────────────────────────────────────────────────────────── async function seed() { console.log(`🌱 Seeding LM USA database at ${PAYLOAD_URL}...`) // ─── 1. Contact Form ─────────────────────────────────────────────────────── console.log(' → Creating contact form...') let contactForm const existingForms = await apiGet('forms', '?where[title][equals]=Contact Form&limit=1') if (existingForms.docs?.length > 0) { console.log(' ⏭ Contact form already exists — skipping') contactForm = existingForms.docs[0] } else { const result = await apiPost('forms', { title: 'Contact Form', fields: [ { name: 'name', label: 'Name', blockType: 'text', required: true, width: 50 }, { name: 'company', label: 'Company', blockType: 'text', required: false, width: 50 }, { name: 'email', label: 'Email', blockType: 'email', required: true, width: 50 }, { name: 'phone', label: 'Phone', blockType: 'text', required: false, width: 50 }, { name: 'message', label: 'Message', blockType: 'textarea', required: true }, ], submitButtonLabel: 'Send Message', confirmationType: 'message', confirmationMessage: richText( "Thanks for reaching out. We'll get back to you within 24 hours.", ), }) contactForm = result.doc } // ─── 2. Home Page ────────────────────────────────────────────────────────── console.log(' → Creating Home page...') await createPageIfNotExists('index', { title: 'Home', slug: 'index', _status: 'published', publishedAt: new Date().toISOString(), layout: [ // Hero // theme: 'light' | 'dark' // textColor: 'auto' | 'white' | 'dark' { blockType: 'lmHero', heading: 'Infrastructure Without Borders', subheading: 'Layer & Mesh USA', body: 'Edge compute, virtual fiber, and managed servers — built for businesses that need sovereign, reliable infrastructure. Configure your setup and get started in minutes.', ctaText: 'Explore Products', ctaLink: '#products', secondaryCtaText: 'Contact Us', secondaryCtaLink: '/contact', theme: 'dark', textColor: 'auto', }, // Link Cards // cardStyle: 'outlined' | 'dark' | 'gray' | 'yellow' // sectionBackground: 'white' | 'gray' | 'dark' // title is textarea (supports \n) { blockType: 'lmLinkCards', heading: 'Choose Your Infrastructure', description: 'Two paths to managed IT — hardware at your location or virtual in our cloud.', columns: '2', cardStyle: 'outlined', sectionBackground: 'dark', anchorId: 'products', cards: [ { title: 'Virtuell Fiber\nEdge compute hardware deployed at your location. Plug in, connect to the mesh — instant private infrastructure.', linkLabel: 'Explore VF Enhet', linkUrl: '/virtuell-fiber', }, { title: 'VPS Servers\nCloud-hosted virtual servers on Layer & Mesh infrastructure. Full root access, instant provisioning, sovereign data.', linkLabel: 'Configure a VPS', linkUrl: '/vps', }, ], }, // Statistics // numberColor: 'gradient' | 'yellow' | 'mint' | 'dark' | 'white' // sectionBackground: 'white' | 'dark' | 'gray' { blockType: 'lmStatistics', heading: 'Built for Reliability', sectionBackground: 'dark', numberColor: 'gradient', stats: [ { number: '99.99%', label: 'Uptime SLA' }, { number: '<5ms', label: 'Edge Latency' }, { number: '24/7', label: 'Support' }, { number: '100%', label: 'Swedish Sovereign' }, ], }, // Swedish CTA // sectionBackground: 'dark' | 'elevated' | 'gray' { blockType: 'lmSwedishCta', headingText: 'Söker du Fiber Direkt i Sverige?', subText: 'Visit our Swedish site for local fiber and hosting services.', ctaLabel: 'fiberdirekt.se', ctaUrl: 'https://fiberdirekt.se', sectionBackground: 'dark', }, // Bottom CTA // sectionBackground: 'yellow' | 'dark' | 'gray' | 'white' // alignment: 'center' | 'left' // size: 'small' | 'medium' | 'large' { blockType: 'lmCtaBanner', heading: 'Ready to get started?', subheading: 'Configure your infrastructure or talk to our team — no commitment required.', ctaText: 'Contact Us', ctaLink: '/contact', secondaryCtaText: 'View VPS Pricing', secondaryCtaLink: '/vps', sectionBackground: 'yellow', alignment: 'center', size: 'medium', }, ], }) // ─── 3. Virtuell Fiber Page ──────────────────────────────────────────────── console.log(' → Creating Virtuell Fiber page...') await createPageIfNotExists('virtuell-fiber', { title: 'Virtuell Fiber', slug: 'virtuell-fiber', _status: 'published', publishedAt: new Date().toISOString(), layout: [ // Product Detail // sectionBackground: 'white' | 'dark' // cartProductType: 'hardware' | 'vps' | 'service' { blockType: 'lmProductDetail', eyebrow: 'Hardware', productName: 'VF Enhet', description: 'Purpose-built edge compute hardware for virtuell fiber deployment. Plug the VF Enhet into your location, connect it to the Layer & Mesh network, and get instant private infrastructure — no data center required. Each unit runs a full mesh node with encrypted backhaul, local compute, and automatic failover.', ctaText: 'Add to Cart', ctaLink: '/contact', secondaryCtaText: 'Contact Sales', secondaryCtaLink: '/contact', enableCart: true, cartProductName: 'VF Enhet', cartPrice: 149, cartProductType: 'hardware', sectionBackground: 'dark', }, // Tech Properties — maxRows: 4! // categoryColor: 'white' | 'dark' // valueColor: 'yellow' | 'white' | 'dark' // sectionBackground: 'dark' | 'white' | 'gray' | 'yellow' { blockType: 'lmTechProperties', sectionBackground: 'dark', categoryColor: 'white', valueColor: 'yellow', properties: [ { category: 'Processor', value: 'ARM Cortex-A76 Quad-Core' }, { category: 'Memory', value: '8 GB DDR4' }, { category: 'Storage', value: '256 GB NVMe SSD' }, { category: 'Network', value: '2.5 GbE + Wi-Fi 6' }, ], }, // Second Tech Properties block for remaining specs { blockType: 'lmTechProperties', sectionBackground: 'dark', categoryColor: 'white', valueColor: 'white', properties: [ { category: 'Power', value: '12W idle / 25W peak' }, { category: 'Dimensions', value: '145 × 100 × 40 mm' }, { category: 'Connectivity', value: 'Encrypted mesh backhaul' }, { category: 'Management', value: 'Remote dashboard included' }, ], }, // FAQ — answer is richText // theme: 'gray' | 'light' | 'dark' { blockType: 'lmFaq', heading: 'Frequently Asked Questions', theme: 'dark', items: [ { question: 'What is the VF Enhet?', answer: richText( 'A compact hardware node that connects your location directly to the Layer & Mesh network. It provides edge compute, encrypted connectivity, and mesh routing — all in a box smaller than a paperback book.', ), }, { question: 'Do I need special wiring or a server room?', answer: richText( 'No. The VF Enhet plugs into any standard ethernet connection and power outlet. It runs silently at 12W idle — about the same as a phone charger.', ), }, { question: 'How is this different from a VPS?', answer: richText( 'A VPS runs in our cloud. The VF Enhet runs at your location. Both connect to the same Layer & Mesh network, but the Enhet gives you physical edge compute with lower latency.', ), }, { question: 'Can I cancel?', answer: richText( 'Yes. Month-to-month with no long-term commitment. Give us 30 days notice and we will arrange return of the hardware.', ), }, ], }, // CTA { blockType: 'lmCtaBanner', heading: 'Need a custom deployment?', subheading: 'Talk to our team about multi-unit rollouts, custom configurations, or enterprise pricing.', ctaText: 'Contact Us', ctaLink: '/contact', sectionBackground: 'yellow', alignment: 'left', size: 'small', }, ], }) // ─── 4. VPS Server Page ──────────────────────────────────────────────────── console.log(' → Creating VPS page...') await createPageIfNotExists('vps', { title: 'VPS Servers', slug: 'vps', _status: 'published', publishedAt: new Date().toISOString(), layout: [ // Alternate Hero // sectionBackground: 'white' | 'dark' | 'gray' { blockType: 'lmAlternateHero', heading: 'Virtual Private Servers', description: 'Cloud-hosted servers on Layer & Mesh infrastructure. Full root access, instant provisioning, and Swedish-sovereign data. Configure your resources below — pricing updates in real-time.', primaryCtaText: 'Configure Below', primaryCtaLink: '#calculator', secondaryCtaText: 'Contact Sales', secondaryCtaLink: '/contact', sectionBackground: 'dark', }, // VPS Calculator // sectionBackground: 'dark' | 'gray' | 'teal' // currency: 'usd' | 'sek' | 'eur' { blockType: 'lmVpsCalculator', heading: 'Estimate your cost', orderCtaText: 'Add to Cart', contactCtaText: 'Questions?', contactCtaLink: '/contact', currency: 'usd', sectionBackground: 'dark', pricingCpuPerCore: 12, pricingRamPerGb: 5, pricingSsdPerGb: 0.08, pricingHddPerGb: 0.02, pricingWindowsLicense: 25, anchorId: 'calculator', }, // USP Table — description is richText // checkColor: 'dark' | 'yellow' | 'gray' // textColor: 'dark' | 'white' // sectionBackground: 'white' | 'gray' | 'dark' { blockType: 'lmUspTable', heading: "What's Included", sectionBackground: 'dark', checkColor: 'dark', textColor: 'white', rows: [ { title: 'Full Root Access', description: richText('SSH, VNC, or console — full control of your server.'), }, { title: 'Unmetered Bandwidth', description: richText('No traffic caps or overage fees.'), }, { title: 'NVMe Storage', description: richText('Enterprise-grade SSDs for maximum I/O.'), }, { title: 'Instant Provisioning', description: richText('Your server is ready in under 60 seconds.'), }, { title: '99.99% Uptime SLA', description: richText('Guaranteed availability with automatic failover.'), }, { title: 'Swedish Sovereignty', description: richText('Data stored and processed in Sweden.'), }, ], }, // CTA { blockType: 'lmCtaBanner', heading: 'Need dedicated hardware?', subheading: 'Check out the VF Enhet — edge compute deployed at your location.', ctaText: 'Learn About VF Enhet', ctaLink: '/virtuell-fiber', secondaryCtaText: 'Contact Sales', secondaryCtaLink: '/contact', sectionBackground: 'yellow', alignment: 'left', size: 'small', }, ], }) // ─── 5. Contact Page ─────────────────────────────────────────────────────── console.log(' → Creating Contact page...') await createPageIfNotExists('contact', { title: 'Contact', slug: 'contact', _status: 'published', publishedAt: new Date().toISOString(), layout: [ // Contact Form // sectionBackground: 'white' | 'gray' | 'dark' | 'navyGradient' // layout: 'standard' | 'withImage' | 'card' { blockType: 'lmContactForm', heading: 'Get in Touch', description: 'Tell us about your infrastructure needs — our team will get back to you within 24 hours.', form: contactForm.id, submitText: 'Send Message', sectionBackground: 'dark', layout: 'card', }, // FAQ { blockType: 'lmFaq', heading: 'Common Questions', theme: 'dark', items: [ { question: 'Where are you located?', answer: richText( 'Layer & Mesh operates infrastructure in Sweden with support available globally. Our US operations serve North American customers.', ), }, { question: 'How quickly can I get started?', answer: richText( 'VPS servers are provisioned instantly. VF Enhet hardware typically ships within 5–7 business days.', ), }, { question: 'Do you offer enterprise pricing?', answer: richText( 'Yes. Contact us for volume pricing, custom SLAs, and dedicated account management.', ), }, ], }, ], }) // ─── 6. Header Navigation ───────────────────────────────────────────────── // Header navItems are flat: { label, type, url } directly on each item console.log(' → Setting up header...') await apiUpdateGlobal('header', { logoLink: { type: 'custom', url: '/' }, navItems: [ { label: 'Virtuell Fiber', type: 'custom', url: '/virtuell-fiber' }, { label: 'VPS Servers', type: 'custom', url: '/vps' }, { label: 'Contact', type: 'custom', url: '/contact' }, ], }) // ─── 7. Footer ──────────────────────────────────────────────────────────── // Footer navItems use link() field: { link: { type, label, url } } console.log(' → Setting up footer...') await apiUpdateGlobal('footer', { logoLink: { type: 'custom', url: '/' }, navItems: [ { link: { type: 'custom', label: 'Virtuell Fiber', url: '/virtuell-fiber' } }, { link: { type: 'custom', label: 'VPS Servers', url: '/vps' } }, { link: { type: 'custom', label: 'Contact', url: '/contact' } }, { link: { type: 'custom', label: 'Fiber Direkt (Sweden)', url: 'https://fiberdirekt.se', newTab: true } }, ], }) console.log('') console.log('✅ Seed complete!') console.log(' Pages: /, /virtuell-fiber, /vps, /contact') } seed().catch((err) => { console.error('❌ Seed failed:', err.message || err) process.exit(1) })