Dienstag, 20 Januar 2026

Diese Woche am beliebtesten

Vertiefendes Material

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);
}
?>
Dreamcodes Redaktion
Dreamcodes Redaktion
Qualität als Standard. Verantwortung als Prinzip. Jede Ressource auf Dreamcodes basiert auf geprüften Best Practices und fundierter Praxiserfahrung. Unser Anspruch ist ein belastbares Fundament statt experimenteller Lösungen. Die Integration und Absicherung der Inhalte liegt in Ihrem Ermessen. Wir liefern die fachliche Basis, die Verantwortung für den produktiven Einsatz verbleibt bei Ihnen.
Vorheriges Tutorial
Nächstes Tutorial

Vielleicht einen Blick WERT?