Headless Browser rendert SPA-Seiten als statisches HTML für Suchmaschinen

    Playwright SSG Tutorial: So machst du Lovable Apps für Google sichtbar

    Till FreitagTill Freitag14. April 20265 min Lesezeit
    Till Freitag

    TL;DR: „Playwright crawlt deine SPA-Routen zur Build-Zeit und speichert vollständig gerendertes HTML als statische Dateien. Ergebnis: Google sieht alles, Lighthouse geht hoch, und du musst kein Framework wechseln."

    — Till Freitag

    Das Problem: Google sieht deine Lovable App nicht

    Du hast mit Lovable eine fantastische App gebaut. Design sitzt, Funktionalität läuft, Nutzer sind begeistert. Aber Google? Google sieht eine leere Seite.

    Das liegt daran, dass Lovable – wie alle Vibe Coding Tools – Single Page Applications (SPAs) erzeugt. Der Server liefert eine leere index.html, und JavaScript rendert den Inhalt im Browser. Das funktioniert für Menschen, aber nicht für Crawlers.

    Hintergrund: In unserem Vibe Coding SEO Guide erklären wir das Problem im Detail. Dieser Artikel ist der praktische Deep-Dive für die Lösung mit Playwright.

    Was ist Playwright SSG?

    SSG steht für Static Site Generation. Die Idee: Anstatt darauf zu hoffen, dass Googlebot JavaScript ausführt, rendern wir alle Seiten zur Build-Zeit selbst – mit einem echten Browser.

    Playwright ist Microsofts Browser-Automatisierungs-Framework. Es startet einen echten Chromium-Browser, navigiert zu jeder Route deiner App, wartet bis alles gerendert ist, und speichert das fertige HTML.

    Das Ergebnis:

    • Jede Route hat eine vollständige HTML-Datei
    • Google sieht sofort den gesamten Content
    • First Contentful Paint wird dramatisch schneller
    • Social Previews funktionieren sofort

    Voraussetzungen

    Bevor du startest, brauchst du:

    1. Deine Lovable App auf GitHub – Exportiere den Code über Lovable's GitHub-Integration
    2. Node.js 18+ auf deinem Build-System
    3. Grundkenntnisse in der Kommandozeile

    Noch nicht auf GitHub? Unser Lovable → GitHub → Vercel Flow Guide zeigt dir den gesamten Prozess.

    Schritt 1: Playwright installieren

    npm install -D playwright-core @playwright/test
    npx playwright install chromium

    Du brauchst nur Chromium – Firefox und WebKit sind für SSG nicht nötig.

    Schritt 2: Routen-Liste erstellen

    Playwright muss wissen, welche Seiten es rendern soll. Du hast zwei Optionen:

    Option A: Statische Route-Liste

    // scripts/routes.ts
    export const routes = [
      '/',
      '/about',
      '/blog',
      '/blog/mein-erster-artikel',
      '/kontakt',
      // ... alle deine Routen
    ];

    Option B: Automatisches Crawling

    // scripts/discover-routes.ts
    import { chromium } from 'playwright-core';
    
    async function discoverRoutes(baseUrl: string): Promise<string[]> {
      const browser = await chromium.launch();
      const page = await browser.newPage();
      const discovered = new Set<string>(['/']);
      const queue = ['/'];
    
      while (queue.length > 0) {
        const route = queue.shift()!;
        await page.goto(`${baseUrl}${route}`, { waitUntil: 'networkidle' });
        
        const links = await page.$$eval('a[href]', anchors =>
          anchors
            .map(a => new URL(a.href, window.location.origin).pathname)
            .filter(href => href.startsWith('/') && !href.includes('.'))
        );
    
        for (const link of links) {
          if (!discovered.has(link)) {
            discovered.add(link);
            queue.push(link);
          }
        }
      }
    
      await browser.close();
      return [...discovered];
    }

    Wir empfehlen Option B für Websites mit vielen dynamischen Routen (z. B. Blog-Artikel).

    Schritt 3: Das SSG-Script

    Hier ist das Herzstück – das Script, das alle Routen rendert und als HTML speichert:

    // scripts/ssg.ts
    import { chromium } from 'playwright-core';
    import { writeFileSync, mkdirSync } from 'fs';
    import { join, dirname } from 'path';
    
    const DIST_DIR = './dist';
    const BASE_URL = 'http://localhost:4173'; // Vite preview port
    
    async function renderRoutes(routes: string[]) {
      const browser = await chromium.launch();
      const context = await browser.newContext();
    
      for (const route of routes) {
        const page = await context.newPage();
        
        await page.goto(`${BASE_URL}${route}`, {
          waitUntil: 'networkidle',
          timeout: 30000,
        });
    
        // Warte auf dynamische Inhalte
        await page.waitForTimeout(1000);
    
        const html = await page.content();
        
        // Speichere als index.html im Route-Verzeichnis
        const filePath = route === '/'
          ? join(DIST_DIR, 'index.html')
          : join(DIST_DIR, route, 'index.html');
        
        mkdirSync(dirname(filePath), { recursive: true });
        writeFileSync(filePath, html, 'utf-8');
        
        console.log(`✅ Rendered: ${route}`);
        await page.close();
      }
    
      await browser.close();
      console.log(`\n🎉 ${routes.length} Seiten gerendert!`);
    }

    Schritt 4: Build-Script zusammenbauen

    Füge ein ssg-Script in deine package.json ein:

    {
      "scripts": {
        "build": "vite build",
        "preview": "vite preview",
        "ssg": "npm run build && npm run preview & sleep 3 && tsx scripts/ssg.ts"
      }
    }

    Was passiert:

    1. vite build erstellt den Production Build
    2. vite preview startet einen lokalen Server
    3. tsx scripts/ssg.ts rendert alle Routen und überschreibt die HTML-Dateien im dist-Verzeichnis

    Schritt 5: GitHub Actions CI/CD

    Automatisiere den SSG-Prozess mit einer GitHub Action:

    # .github/workflows/ssg.yml
    name: Build & SSG
    on:
      push:
        branches: [main]
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: 20
    
          - run: npm ci
          - run: npx playwright install chromium --with-deps
          - run: npm run build
    
          # Starte Preview-Server im Hintergrund
          - run: npm run preview &
          - run: sleep 5
    
          # Rendere alle Seiten
          - run: npx tsx scripts/ssg.ts
    
          # Deploy zu Vercel (oder anderem Hoster)
          - uses: amondnet/vercel-action@v25
            with:
              vercel-token: ${{ secrets.VERCEL_TOKEN }}
              vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
              vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
              working-directory: ./dist

    Schritt 6: Ergebnisse verifizieren

    Nach dem ersten SSG-Build kannst du die Ergebnisse prüfen:

    Lighthouse Score

    npx lighthouse https://deine-domain.com --output html --output-path ./lighthouse.html

    Typische Verbesserungen:

    Metrik Vor SSG Nach SSG
    First Contentful Paint 2.8s 0.4s
    Largest Contentful Paint 3.5s 0.8s
    Time to Interactive 4.2s 1.1s
    SEO Score 60-70 95-100

    Google Search Console

    Nach dem Deployment kannst du in der Google Search Console prüfen:

    1. URL-Prüfung → Zeigt die gerenderte Seite
    2. Abdeckung → Keine „Nicht indexiert"-Fehler mehr
    3. Core Web Vitals → Grüne Werte

    Häufige Probleme und Lösungen

    Problem: Dynamische Inhalte werden nicht gerendert

    Lösung: Erhöhe den waitForTimeout oder warte auf spezifische Selektoren:

    await page.waitForSelector('[data-loaded="true"]', { timeout: 10000 });

    Problem: API-Calls im Browser schlagen fehl

    Lösung: Stelle sicher, dass dein Preview-Server Zugriff auf alle APIs hat. Alternativ: Mock die Daten für den SSG-Build.

    Problem: Hash-Routing (#) statt Path-Routing (/)

    Lösung: Lovable verwendet React Router mit Path-Routing. Falls du Hash-Routing hast, stelle auf BrowserRouter um.

    Problem: Build wird zu langsam

    Lösung: Parallelisiere das Rendering:

    // Rendere 5 Seiten gleichzeitig
    const CONCURRENCY = 5;
    const chunks = [];
    for (let i = 0; i < routes.length; i += CONCURRENCY) {
      chunks.push(routes.slice(i, i + CONCURRENCY));
    }
    
    for (const chunk of chunks) {
      await Promise.all(chunk.map(route => renderRoute(route)));
    }

    Was noch fehlt: Schema & Meta-Tags

    SSG löst das Rendering-Problem. Aber für vollständige SEO brauchst du zusätzlich:

    • JSON-LD Schema für strukturierte Daten → JSON-LD Schema für SPAs automatisieren
    • Meta-Tags für Social Previews (og:title, og:image, etc.)
    • Sitemap und robots.txt
    • Canonical URLs für mehrsprachige Inhalte

    Fazit: SSG ist der Gamechanger für Vibe Coding SEO

    Playwright SSG ist die fehlende Brücke zwischen Vibe Coding und Suchmaschinen. Du behältst alle Vorteile der SPA-Architektur – interaktive UI, schnelles Development, AI-generierter Code – und bekommst dazu vollständige SEO-Sichtbarkeit.

    Der komplette Stack:

    1. Lovable → Generiert die App
    2. GitHub → Versioniert den Code
    3. Playwright → Rendert statisches HTML (dieser Artikel)
    4. Vercel → Liefert über Edge CDN aus

    Das ist exakt der Stack, mit dem wir till-freitag.com auf Lighthouse 100 gebracht haben.


    Du willst das nicht selbst aufsetzen? Wir machen das für dich →

    Unser SEO-Audit zeigt dir in 48 Stunden, wo deine Vibe Coding App steht – und was nötig ist, um sie sichtbar zu machen.

    Verwandte Artikel

    TeilenLinkedInWhatsAppE-Mail

    Verwandte Artikel

    Rakete aus Code-Elementen startet durch Suchergebnisseiten mit Lighthouse Score 100
    14. April 20265 min

    Vibe Coding & SEO: Warum KI-generierte Apps unsichtbar bleiben – und wie wir das lösen

    Lovable, Bolt, v0 – Vibe Coding Tools erzeugen SPAs, die Google nicht sieht. Unser Playbook macht sie SEO-ready: SSG, Sc…

    Weiterlesen
    Google Search Console Dashboard mit Performance-Graphen und Coverage Reports
    14. April 20264 min

    Google Search Console für Vibe-Coding-Projekte: Setup, Debugging & Indexierung

    Deine Lovable-App ist live auf Vercel – aber Google indexiert nichts? So richtest du die Search Console ein, debuggst Cr…

    Weiterlesen
    Pipeline-Diagramm mit drei Stationen: Lovable, GitHub, Vercel
    14. April 20264 min

    Lovable → GitHub → Vercel: Der komplette Deployment-Flow für SEO-ready Apps

    Lovable generiert die App, GitHub versioniert den Code, Vercel liefert mit < 50ms TTFB aus. Dieser Guide zeigt den kompl…

    Weiterlesen
    Social Media Preview Cards mit OG-Image Meta Tags schweben im dunklen Raum
    14. April 20264 min

    OG-Image Best Practices für SPAs: So werden deine Vibe-Coding-Projekte teilbar

    Wenn du einen Link aus deiner Lovable-App teilst, zeigt LinkedIn ein leeres Kästchen. Warum SPAs keine Social Previews l…

    Weiterlesen
    SaaS Analytics Dashboard mit KPI-Karten, Line Charts und Datentabellen, gebaut in Lovable
    8. März 20264 min

    SaaS Dashboard mit Lovable bauen: Vom Prompt zum fertigen Produkt

    Ein komplettes SaaS Dashboard mit Charts, Auth und Datenbank – gebaut mit Lovable in einem Nachmittag. Step-by-Step Tuto…

    Weiterlesen
    Vernetzte Schema-Knoten als leuchtender Graph auf dunklem Hintergrund
    14. April 20265 min

    JSON-LD Schema für SPAs automatisieren: Structured Data ohne Backend

    SPAs haben keine Structured Data – und Google zeigt keine Rich Snippets. Dieses Tutorial zeigt, wie du JSON-LD Schemas i…

    Weiterlesen
    Architektur-Diagramm eines modernen Vibe Coding Stacks mit Lovable, Supabase und Resend als Kernkomponenten
    16. März 20265 min

    Der Vibe Coding Stack 2026: Lovable, Supabase, Resend – und was noch fehlt

    Das ist der Tech-Stack, mit dem wir 2026 Full-Stack-Apps bauen – ohne klassisches Dev-Team. Drei Tools im Kern, zwei für…

    Weiterlesen
    Laptop mit farbenfrohem immersivem Website-Design auf einem warmen Schreibtisch
    13. März 20264 min

    Immersive Websites mit Lovable bauen – so geht's

    Die meisten KI-generierten Websites sehen gleich aus. So baust du mit Lovable immersive, interaktive Seiten – mit smarte…

    Weiterlesen
    Futuristische Code-Editor-Fenster mit Turquoise- und Blue-Akzenten auf dunklem Hintergrund
    10. März 20266 min

    Wir sind keine Webagentur – und das ist der Punkt

    Ihr sucht eine Webagentur? Dann seid ihr bei uns falsch. Ihr sucht jemanden, der euer digitales Problem löst? Dann seid …

    Weiterlesen