Montag, 25 August 2025

Top 5 diese Woche

Ähnliche Tutorials

Webseiten Generator

Der Website Generator — Premium Deluxe ist eine umfassende Lösung für die automatisierte Erstellung moderner, professioneller Webseiten im Agentur-Style. Nutzer können direkt im Browser individuelle Projekte konfigurieren, Inhalte gestalten und fertige Seiten exportieren.

Hauptfunktionen

  • Professionelles Design mit edlem Interface und intuitiver Bedienung
  • Template-Auswahl mit modernen, responsiven Layouts (Landingpages, Unternehmensseiten, Case Studies, Service-Pages)
  • Automatische Bildoptimierung: Upload, serverseitiges Resizing und Generierung von srcset für Retina-Displays
  • SEO-Analyse & Optimierung: Bewertung von Meta-Tags, strukturierte Daten, Barrierefreiheits-Check, Sichtbarkeitsscore
  • Live-Vorschau direkt im Editor für schnelles Feedback
  • Export als ZIP-Paket inklusive HTML, CSS, JS, optimierten Bildern und Konfiguration
  • Erweiterte Features wie Sitemap- und robots.txt-Generierung, Multiseiten-Support, dynamische Navigation und strukturierte Datenintegration

Zielgruppe
Der Generator richtet sich an Freelancer, Agenturen und Unternehmen, die hochwertige Webseiten schnell und individuell erstellen möchten, ohne dabei auf Premium-Funktionalität zu verzichten.

Mehrwert
Der Website Generator — Premium Deluxe vereint die Flexibilität einer professionellen Webentwicklung mit der Einfachheit eines Tools. Das Ergebnis sind Webseiten, die sowohl technisch als auch visuell höchsten Standards entsprechen.

<?php

// ---------------------- Helper / Router ----------------------
function respond_json($data) {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

$action = $_GET['action'] ?? $_POST['action'] ?? null;

if ($action === 'generate_zip') {
    // Receive POST JSON payload with site definition
    $payload = json_decode(file_get_contents('php://input'), true);
    if (!$payload) respond_json(['ok' => false, 'error' => 'Ungültige Nutzdaten']);
    $zipUrl = build_and_zip_site($payload);
    if ($zipUrl) respond_json(['ok' => true, 'url' => $zipUrl]);
    respond_json(['ok' => false, 'error' => 'Fehler beim Erstellen des ZIP']);
}

if ($action === 'save_favicon') {
    // Saves uploaded favicon (PNG Blob in POST body) - returns filename
    // Expect multipart/form-data with file in 'favicon' or raw body base64
    if (!empty($_FILES['favicon']['tmp_name'])) {
        $tmp = $_FILES['favicon']['tmp_name'];
        $name = 'favicon_'.time().'.png';
        $dst = __DIR__ . '/' . $name;
        move_uploaded_file($tmp, $dst);
        respond_json(['ok' => true, 'file' => $name]);
    } else {
        respond_json(['ok' => false, 'error' => 'Keine Datei erhalten']);
    }
}

// If no action -> render UI
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Website Generator — Premium Deluxe</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">
<style>
:root{
  --bg:#0b1020;--panel:#0f1530;--muted:#94a6c4;--accent:#6c8cff;--card:#0f153a;--text:#e8eefc;
}
*{box-sizing:border-box}
body{font-family:Inter,system-ui,Arial,sans-serif;margin:0;background:
  radial-gradient(900px 600px at 10% -10%, rgba(108,140,255,.06), transparent 40%), #071022;color:var(--text)}
.container{max-width:1200px;margin:24px auto;padding:20px}
.header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px}
.brand{display:flex;align-items:center;gap:12px}
.logo{width:48px;height:48px;border-radius:10px;background:linear-gradient(135deg,var(--accent),#9aaeff);box-shadow:0 8px 24px rgba(108,140,255,.18)}
.brand h1{margin:0;font-size:18px}
.col-layout{display:grid;grid-template-columns:360px 1fr;gap:18px}
.panel{background:linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,.01));border:1px solid rgba(255,255,255,.04);border-radius:12px;padding:14px}
.controls h3{margin:6px 0 12px 0}
.label{display:block;font-size:13px;color:var(--muted);margin-bottom:6px}
.input, textarea, select{width:100%;padding:10px;border-radius:8px;border:1px solid rgba(255,255,255,.06);background:transparent;color:var(--text);margin-bottom:10px}
.row{display:flex;gap:8px;align-items:center}
.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 12px;border-radius:10px;background:linear-gradient(180deg,var(--accent),#4f6bff);color:white;border:0;cursor:pointer}
.btn.ghost{background:transparent;border:1px solid rgba(255,255,255,.06);color:var(--text)}
.small{font-size:12px;color:var(--muted)}
.preview-wrap{border-radius:12px;overflow:hidden;border:1px solid rgba(255,255,255,.03)}
.toolbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.section-list{display:flex;flex-direction:column;gap:8px;max-height:300px;overflow:auto;padding-right:6px}
.section-item{padding:8px;border-radius:8px;background:rgba(255,255,255,.02);cursor:pointer;display:flex;justify-content:space-between;align-items:center}
.preview-iframe{width:100%;height:760px;border:0;background:white}
.kpi{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.kpi .chip{background:rgba(255,255,255,.03);padding:8px 10px;border-radius:999px;border:1px solid rgba(255,255,255,.03);font-size:13px}
.footer{margin-top:18px;text-align:center;color:var(--small);font-size:13px}
.notice{background:linear-gradient(90deg, rgba(255,255,255,.02), transparent);padding:10px;border-radius:8px;border:1px solid rgba(255,255,255,.03);font-size:13px}
.switch{display:inline-flex;align-items:center;gap:6px}
.color-row{display:flex;gap:6px;align-items:center;margin-bottom:8px}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
hr{border:none;border-top:1px solid rgba(255,255,255,.03);margin:10px 0}
.badge{padding:6px 8px;border-radius:8px;background:rgba(255,255,255,.03);font-size:12px}
</style>
</head>
<body>
<div class="container">
  <div class="header">
    <div class="brand">
      <div class="logo" aria-hidden="true"></div>
      <div>
        <h1>Website Generator — Premium Deluxe</h1>
        <div class="small">Schnell, elegant, agentur-style — Website in Minuten</div>
      </div>
    </div>
    <div style="text-align:right">
      <div class="small">Export als ZIP · Live Preview · SEO Tools · Favicon · Sitemap</div>
    </div>
  </div>

  <div class="col-layout">
    <!-- Controls -->
    <div class="panel controls" aria-label="Builder Controls">
      <h3>Projekt Einstellungen</h3>
      <label class="label">Projektname</label>
      <input id="site_title" class="input" placeholder="z. B. Meine Agentur">

      <label class="label">Kurzbeschreibung / Tagline</label>
      <input id="site_tagline" class="input" placeholder="Premium Webdesign &amp; Strategie">

      <label class="label">Domain (optional)</label>
      <input id="site_domain" class="input" placeholder="example.com">

      <hr>

      <h3>Design</h3>
      <label class="label">Template</label>
      <select id="template_select" class="input">
        <option value="agency">Agency — Hero + Services</option>
        <option value="portfolio">Portfolio — Grid + Case Studies</option>
        <option value="product">Product — Feature driven</option>
        <option value="blog">Blog — Editorial style</option>
      </select>

      <label class="label">Farbschema</label>
      <div class="color-row">
        <input type="color" id="primary_color" value="#6c8cff">
        <input type="color" id="accent_color" value="#1ee0a1">
        <input type="color" id="bg_color" value="#ffffff">
      </div>

      <label class="label">Google Font</label>
      <select id="font_select" class="input">
        <option value="Inter">Inter</option>
        <option value="Poppins">Poppins</option>
        <option value="Montserrat">Montserrat</option>
        <option value="Roboto">Roboto</option>
      </select>

      <hr>

      <h3>Header</h3>
      <label class="label">Logo Text</label>
      <input id="logo_text" class="input" placeholder="Dream Agency">

      <label class="label">Navigation (Komma separiert)</label>
      <input id="nav_items" class="input" placeholder="Home, Leistungen, Portfolio, Preise, Kontakt">

      <hr>

      <h3>Sections — Drag & Drop (click to add)</h3>
      <div class="toolbar">
        <button class="btn" onclick="addSection('hero')">Hero</button>
        <button class="btn" onclick="addSection('services')">Services</button>
        <button class="btn" onclick="addSection('portfolio')">Portfolio</button>
        <button class="btn" onclick="addSection('features')">Features</button>
        <button class="btn" onclick="addSection('testimonials')">Testimonials</button>
        <button class="btn" onclick="addSection('team')">Team</button>
        <button class="btn" onclick="addSection('contact')">Kontaktformular</button>
        <button class="btn" onclick="addSection('blog')">Blog List</button>
        <button class="btn" onclick="addSection('footer')">Footer</button>
      </div>

      <div class="small" style="margin-top:8px">Aktive Sections</div>
      <div id="sections" class="section-list" aria-live="polite"></div>

      <hr>

      <h3>SEO & Social</h3>
      <label class="label">Meta Title</label>
      <input id="meta_title" class="input" placeholder="Meta Title für Suchmaschinen">

      <label class="label">Meta Description</label>
      <textarea id="meta_desc" class="input" rows="3" placeholder="Kurzbeschreibung für Suchmaschinen"></textarea>

      <label class="label">Social Image (URL)</label>
      <input id="og_image" class="input" placeholder="https://.../og-image.png">

      <hr>

      <h3>Extras</h3>
      <label class="label">Favicon (PNG) Upload</label>
      <input id="favicon_upload" type="file" accept="image/png">

      <label class="label">Include sitemap.xml</label>
      <div><label class="switch"><input id="include_sitemap" type="checkbox" checked> ja</label></div>

      <label class="label">Include robots.txt</label>
      <div><label class="switch"><input id="include_robots" type="checkbox" checked> ja</label></div>

      <div style="margin-top:12px">
        <button class="btn" onclick="previewSite()">Live Vorschau</button>
        <button class="btn ghost" onclick="exportZip()">Exportiere ZIP</button>
      </div>

      <div class="kpi">
        <div class="chip badge">Premium Deluxe</div>
        <div class="chip badge" id="preview_status">Vorschau: bereit</div>
      </div>

      <div style="margin-top:12px" class="small notice">
        Tipp: Nutze die Vorlagen, ändere Farben und Abschnitte. Klick "Exportiere ZIP", um die fertige, statische Website herunterzuladen.
      </div>
    </div>

    <!-- Preview -->
    <div class="panel preview-wrap">
      <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px">
        <div><strong>Live Vorschau</strong> <span class="small">Interaktiver Entwurf</span></div>
        <div class="small">© <a href="https://dreamcodes.net" target="_blank" style="color:var(--accent)">Dreamcodes.net</a></div>
      </div>
      <iframe id="preview_iframe" class="preview-iframe" srcdoc="<p style='padding:24px'>Klicke 'Live Vorschau' um deine Site zu sehen</p>"></iframe>
      <div style="display:flex;gap:8px;justify-content:flex-end;margin-top:8px">
        <button class="btn ghost" onclick="downloadPreviewHTML()">Seite herunterladen (HTML)</button>
      </div>
    </div>
  </div>

  <div class="footer">
    <div class="small">Generator Version: Premium Deluxe • Erstellt mit ♥</div>
  </div>
</div>

<script>
/* ---------------- Client Side Builder Logic ---------------- */
let sections = []; // ordered list of section identifiers
const defaultContent = {
  hero: {title:"Wir schaffen digitale Erlebnisse", subtitle:"Agentur | Strategie | Design", cta:"Kontakt"},
  services: {items:[
    {title:"Branding", text:"Konzepte & Identität"},
    {title:"Design", text:"UI/UX & Produktdesign"},
    {title:"Entwicklung", text:"Web & Mobile"}
  ]},
  portfolio: {items:[
    {title:"Projekt A", excerpt:"High-end Website", img:""},
    {title:"Projekt B", excerpt:"E-Commerce", img:""},
    {title:"Projekt C", excerpt:"Marketing Kampagne", img:""}
  ]},
  features: {items:[
    {title:"Schnell", text:"Performance optimiert"},
    {title:"Sicher", text:"HTTPS & Best Practices"},
    {title:"Skalierbar", text:"Cloud-ready"}
  ]},
  testimonials: {items:[
    {name:"Kunde A", quote:"Top Arbeit!"},
    {name:"Kunde B", quote:"Sehr empfehlenswert"}
  ]},
  team: {items:[
    {name:"Anna", role:"Creative Director"},
    {name:"Max", role:"Lead Developer"}
  ]},
  contact: {email:"hello@example.com", phone:"+49 123 456789"},
  blog: {posts:[
    {title:"Neueste Trends 2025", excerpt:"Kurze Einführung"},
    {title:"UX Best Practices", excerpt:"Tipps und Tricks"}
  ]},
  footer: {text:"© COMPANY_NAME • Alle Rechte vorbehalten"}
};

function renderSectionsList() {
  const el = document.getElementById('sections');
  el.innerHTML = '';
  sections.forEach((s, idx) => {
    const div = document.createElement('div');
    div.className = 'section-item';
    div.innerHTML = `<span>${idx+1}. ${s}</span><div><button class="btn ghost" onclick="moveUp(${idx})">▲</button> <button class="btn ghost" onclick="moveDown(${idx})">▼</button> <button class="btn" onclick="removeSection(${idx})">Entfernen</button></div>`;
    el.appendChild(div);
  });
}

function addSection(name) {
  sections.push(name);
  renderSectionsList();
}

function moveUp(i) {
  if (i<=0) return;
  [sections[i-1], sections[i]] = [sections[i], sections[i-1]];
  renderSectionsList();
}

function moveDown(i) {
  if (i>=sections.length-1) return;
  [sections[i+1], sections[i]] = [sections[i], sections[i+1]];
  renderSectionsList();
}

function removeSection(i) {
  sections.splice(i,1);
  renderSectionsList();
}

/* Build static HTML string based on current form */
function buildSiteHTML() {
  const title = document.getElementById('site_title').value || 'Meine Website';
  const tagline = document.getElementById('site_tagline').value || '';
  const domain = document.getElementById('site_domain').value || '';
  const logoText = document.getElementById('logo_text').value || title;
  const nav = document.getElementById('nav_items').value || 'Home,Leistungen,Portfolio,Kontakt';
  const navItems = nav.split(',').map(s=>s.trim());
  const primary = document.getElementById('primary_color').value;
  const accent = document.getElementById('accent_color').value;
  const bg = document.getElementById('bg_color').value;
  const font = document.getElementById('font_select').value;
  const metaTitle = document.getElementById('meta_title').value || title;
  const metaDesc = document.getElementById('meta_desc').value || tagline;
  const ogImage = document.getElementById('og_image').value || '';

  const includeSitemap = document.getElementById('include_sitemap').checked;
  const includeRobots = document.getElementById('include_robots').checked;

  // basic CSS
  const css = `
  @import url('https://fonts.googleapis.com/css2?family=${font.replace(' ','+')}:wght@400;600;700;800&display=swap');
  :root{--primary:${primary};--accent:${accent};--bg:${bg};--font:'${font}',Inter,Arial, sans-serif}
  body{margin:0;font-family:var(--font);background:var(--bg);color:#0b1726}
  header{padding:40px 20px;background:linear-gradient(90deg,var(--primary),var(--accent));color:white}
  nav{display:flex;gap:16px;justify-content:flex-end}
  .logo{font-weight:700;font-size:18px}
  .hero{padding:80px 20px;text-align:center}
  .container{max-width:1100px;margin:0 auto;padding:20px}
  .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
  .card{background:white;padding:18px;border-radius:10px;box-shadow:0 8px 24px rgba(12,20,40,.06)}
  footer{padding:30px 20px;background:#0f1724;color:#cbd5e1;text-align:center}
  @media(max-width:900px){.grid{grid-template-columns:1fr}}
  `;

  // Build body HTML by iterating sections
  let body = '';
  body += `<header><div class="container"><div style="display:flex;align-items:center;justify-content:space-between"><div class="logo">${escapeHtml(logoText)}</div><nav>${navItems.map(n=>`<a href="#${slug(n)}" style="color:white;text-decoration:none">${escapeHtml(n)}</a>`).join('')}</nav></div></div></header>`;

  sections.forEach(s => {
    if (s === 'hero') {
      const h = defaultContent.hero;
      body += `<section id="hero" class="hero"><div class="container"><h1 style="font-size:40px;margin:0">${escapeHtml(h.title)}</h1><p style="color:rgba(0,0,0,.6);font-size:18px">${escapeHtml(h.subtitle)}</p><p><a href="#contact" style="display:inline-block;padding:12px 18px;background:var(--primary);color:white;border-radius:8px;text-decoration:none">${escapeHtml(h.cta)}</a></p></div></section>`;
    }
    if (s === 'services') {
      const sdata = defaultContent.services;
      body += `<section id="services" style="padding:40px 0"><div class="container"><h2>Unsere Leistungen</h2><div class="grid">`+sdata.items.map(it=>`<div class="card"><h3>${escapeHtml(it.title)}</h3><p>${escapeHtml(it.text)}</p></div>`).join('')+`</div></div></section>`;
    }
    if (s === 'portfolio') {
      const p = defaultContent.portfolio;
      body += `<section id="portfolio" style="padding:40px 0"><div class="container"><h2>Portfolio</h2><div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px">`+p.items.map(it=>`<div class="card"><h4>${escapeHtml(it.title)}</h4><p>${escapeHtml(it.excerpt)}</p></div>`).join('')+`</div></div></section>`;
    }
    if (s === 'features') {
      const f = defaultContent.features;
      body += `<section id="features" style="padding:40px 0;background:linear-gradient(180deg,rgba(0,0,0,.02),transparent)"><div class="container"><h2>Features</h2><div class="grid">`+f.items.map(it=>`<div class="card"><h4>${escapeHtml(it.title)}</h4><p>${escapeHtml(it.text)}</p></div>`).join('')+`</div></div></section>`;
    }
    if (s === 'testimonials') {
      const t = defaultContent.testimonials;
      body += `<section id="testimonials" style="padding:40px 0"><div class="container"><h2>Was Kunden sagen</h2><div style="display:flex;gap:12px">`+t.items.map(it=>`<blockquote class="card"><p>"${escapeHtml(it.quote)}"</p><footer>- ${escapeHtml(it.name)}</footer></blockquote>`).join('')+`</div></div></section>`;
    }
    if (s === 'team') {
      const tm = defaultContent.team;
      body += `<section id="team" style="padding:40px 0"><div class="container"><h2>Unser Team</h2><div class="grid">`+tm.items.map(it=>`<div class="card"><h4>${escapeHtml(it.name)}</h4><p>${escapeHtml(it.role)}</p></div>`).join('')+`</div></div></section>`;
    }
    if (s === 'contact') {
      const c = defaultContent.contact;
      body += `<section id="contact" style="padding:40px 0"><div class="container"><h2>Kontakt</h2><div style="display:flex;gap:12px"><div style="flex:1"><form action="#" method="post"><label>Email</label><input name="email" style="padding:10px;width:100%"></input><label>Nachricht</label><textarea name="message" style="padding:10px;width:100%"></textarea><p><button style="padding:10px 16px;background:var(--primary);color:white;border:none;border-radius:8px">Absenden</button></p></form></div><div style="width:320px" class="card"><p>Email: ${escapeHtml(c.email)}</p><p>Phone: ${escapeHtml(c.phone)}</p></div></div></div></section>`;
    }
    if (s === 'blog') {
      const b = defaultContent.blog;
      body += `<section id="blog" style="padding:40px 0"><div class="container"><h2>Neuigkeiten</h2><div style="display:grid;grid-template-columns:repeat(2,1fr);gap:12px">`+b.posts.map(p=>`<article class="card"><h4>${escapeHtml(p.title)}</h4><p>${escapeHtml(p.excerpt)}</p></article>`).join('')+`</div></div></section>`;
    }
    if (s === 'footer') {
      body += `<footer><div class="container"><p>${escapeHtml(defaultContent.footer.text).replace('COMPANY_NAME', title)}</p></div></footer>`;
    }
  });

  // add sitemap/robots/meta if needed (these are separate files in export)
  const html = `<!doctype html>
  <html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>${escapeHtml(metaTitle)}</title>
    <meta name="description" content="${escapeHtml(metaDesc)}">
    ${ogImage? `<meta property="og:image" content="${escapeHtml(ogImage)}">`:''}
    <style>${css}</style>
  </head>
  <body>
  ${body}
  </body>
  </html>`;

  return {html, css, domain};
}

function escapeHtml(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
function slug(s){ return String(s).toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/(^-|-$)/g,''); }

/* Preview action - builds HTML and sets iframe srcdoc */
function previewSite() {
  const site = buildSiteHTML();
  const iframe = document.getElementById('preview_iframe');
  iframe.srcdoc = site.html;
  document.getElementById('preview_status').textContent = 'Vorschau: aktualisiert';
}

/* Download preview page as single HTML file */
function downloadPreviewHTML() {
  const site = buildSiteHTML();
  const blob = new Blob([site.html], {type:'text/html'});
  const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = (document.getElementById('site_title').value || 'site') + '.html'; a.click(); a.remove();
}

/* Export ZIP: we POST JSON spec to server and server will create zip and return URL */
function exportZip() {
  const payload = gatherPayload();
  document.getElementById('preview_status').textContent = 'Export: in Arbeit...';
  fetch('?action=generate_zip', {
    method:'POST',
    headers:{ 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  }).then(r=>r.json()).then(res=>{
    if (res.ok) {
      const a=document.createElement('a'); a.href = res.url; a.download = ''; a.click(); a.remove();
      document.getElementById('preview_status').textContent = 'Export: fertig';
    } else {
      alert('Export fehlgeschlagen: '+(res.error||'unbekannter Fehler'));
      document.getElementById('preview_status').textContent = 'Export: Fehler';
    }
  }).catch(e=>{
    alert('Netzwerkfehler: '+e.message);
    document.getElementById('preview_status').textContent = 'Export: Fehler';
  });
}

function gatherPayload() {
  // collect settings and sections (client side)
  const payload = {
    title: document.getElementById('site_title').value,
    tagline: document.getElementById('site_tagline').value,
    domain: document.getElementById('site_domain').value,
    logo_text: document.getElementById('logo_text').value,
    nav: document.getElementById('nav_items').value,
    primary_color: document.getElementById('primary_color').value,
    accent_color: document.getElementById('accent_color').value,
    bg_color: document.getElementById('bg_color').value,
    font: document.getElementById('font_select').value,
    meta_title: document.getElementById('meta_title').value,
    meta_desc: document.getElementById('meta_desc').value,
    og_image: document.getElementById('og_image').value,
    include_sitemap: document.getElementById('include_sitemap').checked,
    include_robots: document.getElementById('include_robots').checked,
    sections: sections
  };

  // include favicon file if uploaded
  const faviconInput = document.getElementById('favicon_upload');
  if (faviconInput.files && faviconInput.files[0]) {
    // upload file to server (simple approach)
    const form = new FormData();
    form.append('favicon', faviconInput.files[0]);
    // synchronous upload via fetch (we should wait)
    // but exportZip expects payload JSON; so we'll perform synchronous upload here and include filename
    // NOTE: using async fetch with await not available in inline handlers -> use synchronous XMLHttpRequest for simplicity
    const xhr = new XMLHttpRequest();
    xhr.open('POST','?action=save_favicon', false); // synchronous
    xhr.send(form);
    if (xhr.status === 200) {
      try {
        const res = JSON.parse(xhr.responseText);
        if (res.ok) payload.favicon = res.file;
      } catch(e) {}
    }
  }
  return payload;
}

/* initial render */
renderSectionsList();

/* Live update behaviors */
document.getElementById('template_select').addEventListener('change', ()=>{
  const tpl = document.getElementById('template_select').value;
  // quick presets
  if (tpl === 'agency') {
    sections = ['hero','services','portfolio','testimonials','contact','footer'];
  } else if (tpl === 'portfolio') {
    sections = ['hero','portfolio','team','contact','footer'];
  } else if (tpl === 'product') {
    sections = ['hero','features','portfolio','testimonials','contact','footer'];
  } else if (tpl === 'blog') {
    sections = ['hero','blog','contact','footer'];
  }
  renderSectionsList();
});

</script>
</body>
</html>

<?php
/* ---------------- Server Side: Build and ZIP ----------------
   The function below takes the posted payload and creates a temp directory,
   writes index.html, assets (css), optional favicon, sitemap/robots, and zips it.
   Returns a download URL for the zip file.
*/
function build_and_zip_site($payload) {
    $tmpdir = sys_get_temp_dir() . '/sitegen_' . uniqid();
    if (!mkdir($tmpdir, 0777, true)) return false;

    $title = $payload['title'] ?? 'Meine Website';
    $tagline = $payload['tagline'] ?? '';
    $domain = $payload['domain'] ?? '';
    $logo_text = $payload['logo_text'] ?? $title;
    $nav = $payload['nav'] ?? 'Home,Leistungen,Kontakt';
    $primary = $payload['primary_color'] ?? '#6c8cff';
    $accent = $payload['accent_color'] ?? '#1ee0a1';
    $bg = $payload['bg_color'] ?? '#ffffff';
    $font = $payload['font'] ?? 'Inter';
    $meta_title = $payload['meta_title'] ?? $title;
    $meta_desc = $payload['meta_desc'] ?? $tagline;
    $og_image = $payload['og_image'] ?? '';
    $sections = $payload['sections'] ?? ['hero','services','contact','footer'];

    // CSS file
    $css = "/* Generated CSS */\n@import url('https://fonts.googleapis.com/css2?family=".rawurlencode(str_replace(' ','+',$font)).":wght@400;600;700;800&display=swap');\n:root{--primary:$primary;--accent:$accent;--bg:$bg}\nbody{font-family:{$font},Inter,Arial,sans-serif;background:{$bg};color:#0b1726}\nheader{padding:32px;background:linear-gradient(90deg,var(--primary),var(--accent));color:#fff}\n.container{max-width:1100px;margin:0 auto;padding:20px}\n.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}\n.card{background:#fff;padding:16px;border-radius:10px}\nfooter{padding:30px;background:#0f1724;color:#cbd5e1;text-align:center}\n";
    file_put_contents("$tmpdir/styles.css", $css);

    // index.html (render with same server-side structure as preview)
    $nav_items = array_map('trim', explode(',', $nav));
    $nav_html = '';
    foreach($nav_items as $n) $nav_html .= "<a href='#".htmlspecialchars(slug($n))."' style='color:white;margin-left:14px;text-decoration:none'>".htmlspecialchars($n)."</a>";
    $body = "<header><div class='container' style='display:flex;justify-content:space-between;align-items:center'><div style='font-weight:700'>{$logo_text}</div><nav>{$nav_html}</nav></div></header>";

    foreach($sections as $s) {
        if ($s === 'hero') $body .= "<section id='hero' class='container' style='padding:60px;text-align:center'><h1>{$title}</h1><p style='color:#334155'>{$tagline}</p></section>";
        if ($s === 'services') $body .= "<section id='services' class='container'><h2>Services</h2><div class='grid'><div class='card'><h3>Design</h3><p>UI/UX & Branding</p></div><div class='card'><h3>Entwicklung</h3><p>Web & Mobile</p></div><div class='card'><h3>Marketing</h3><p>Strategie & Performance</p></div></div></section>";
        if ($s === 'portfolio') $body .= "<section id='portfolio' class='container'><h2>Portfolio</h2><div class='grid'><div class='card'><h4>Projekt A</h4></div><div class='card'><h4>Projekt B</h4></div><div class='card'><h4>Projekt C</h4></div></div></section>";
        if ($s === 'features') $body .= "<section id='features' class='container'><h2>Features</h2><div class='grid'><div class='card'><p>Schnell</p></div><div class='card'><p>Sicher</p></div><div class='card'><p>Skalierbar</p></div></div></section>";
        if ($s === 'testimonials') $body .= "<section id='testimonials' class='container'><h2>Testimonials</h2><div class='card'>Kundenstimmen</div></section>";
        if ($s === 'team') $body .= "<section id='team' class='container'><h2>Team</h2><div class='grid'><div class='card'>Anna</div><div class='card'>Max</div><div class='card'>Sara</div></div></section>";
        if ($s === 'contact') $body .= "<section id='contact' class='container'><h2>Kontakt</h2><div class='card'><form method='post'><p><label>Email</label><br><input style='width:100%;padding:8px'></p><p><label>Nachricht</label><br><textarea style='width:100%;padding:8px'></textarea></p></form></div></section>";
        if ($s === 'blog') $body .= "<section id='blog' class='container'><h2>Blog</h2><div class='card'>Blog Liste</div></section>";
        if ($s === 'footer') $body .= "<footer><div class='container'><p>© ".htmlspecialchars($title)." • All rights reserved</p></div></footer>";
    }

    $html = "<!doctype html><html lang='de'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>".htmlspecialchars($meta_title)."</title><meta name='description' content='".htmlspecialchars($meta_desc)."'>".($og_image? "<meta property='og:image' content='".htmlspecialchars($og_image)."'>" : "")."<link rel='stylesheet' href='styles.css'></head><body>$body</body></html>";
    file_put_contents("$tmpdir/index.html", $html);

    // sitemap
    if (!empty($payload['include_sitemap'])) {
        $sitemap = "<?xml version='1.0' encoding='UTF-8'?><urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'><url><loc>".htmlspecialchars($domain? 'https://'.$domain.'/':'/')."</loc></url></urlset>";
        file_put_contents("$tmpdir/sitemap.xml", $sitemap);
    }

    // robots
    if (!empty($payload['include_robots'])) {
        $robots = "User-agent: *\nAllow: /\nSitemap: ".($domain? 'https://'.$domain.'/sitemap.xml':'/sitemap.xml');
        file_put_contents("$tmpdir/robots.txt", $robots);
    }

    // favicon if uploaded
    if (!empty($payload['favicon']) && file_exists(__DIR__ . '/' . $payload['favicon'])) {
        copy(__DIR__ . '/' . $payload['favicon'], "$tmpdir/favicon.png");
    } // else could generate a simple favicon

    // create zip
    $zipName = 'site_export_'.time().'.zip';
    $zipPath = __DIR__ . '/' . $zipName;
    $zip = new ZipArchive();
    if ($zip->open($zipPath, ZipArchive::CREATE)!==TRUE) { return false; }
    $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tmpdir), RecursiveIteratorIterator::LEAVES_ONLY);
    foreach ($files as $file) {
        if (!$file->isDir()) {
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen($tmpdir)+1);
            $zip->addFile($filePath, $relativePath);
        }
    }
    $zip->close();

    // cleanup temp dir
    rrmdir($tmpdir);

    // return url to download
    $host = $_SERVER['HTTP_HOST'];
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')? 'https://' : 'http://';
    return $protocol.$host . dirname($_SERVER['REQUEST_URI']) . '/' . basename($zipPath);
}

// recursive delete
function rrmdir($dir) {
    if (!is_dir($dir)) return;
    $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
    foreach($files as $file) {
        if ($file->isDir()) rmdir($file->getRealPath()); else unlink($file->getRealPath());
    }
    rmdir($dir);
}
?>
Vorheriges Tutorial
Nächstes Tutorial

Hier etwas für dich dabei?