Takeaway: SPAs und Next.js-Apps sind fuer Googlebots strukturell schwer zugaenglich — ohne korrektes SSR, dynamisches Rendering und technische SEO-Konfiguration bleibt deine React-App unsichtbar.

while.chat selbst hatte das Problem. Die Seite war live, die Artikel waren fertig — und Google indexierte genau einen einzigen Treffer. Nicht wegen schlechter Inhalte. Sondern weil ein JavaScript-gerendetes Frontend für Googlebots strukturell schwer zugänglich ist, wenn Server-Side Rendering fehlt oder unvollständig konfiguriert ist.

Single Page Applications und moderne React-Frameworks haben die Art verändert, wie Websites gebaut werden. Next.js, Nuxt, Remix, SvelteKit — diese Frameworks sind produktiv, schnell in der Entwicklung und erzeugen hervorragende Nutzer-Erlebnisse. Was sie nicht automatisch erzeugen: eine SEO-freundliche Architektur. Der Grund ist technisch präzise: Googlebots rendern JavaScript, aber langsamer, weniger vollständig und unter anderen Bedingungen als echte Nutzer-Browser. Was ein Nutzer sieht und was Googlebot crawlt, kann erheblich divergieren.

Dieser Artikel erklärt die technischen Ursachen, die kritischsten Fehler und den pragmatischen Fix-Pfad — spezifisch für Next.js, aber übertragbar auf jeden SPA-Stack.

I

Warum SPAs und SEO grundsätzlich in Konflikt stehen

Klassische Websites liefern bei jedem Request vollständiges HTML: Server verarbeitet Anfrage, gibt fertiges HTML zurück, Browser rendert. Googlebot liest das HTML und indexiert den Inhalt. Einfach.

Eine Single Page Application funktioniert anders: Der Server liefert eine minimale HTML-Shell mit einem JavaScript-Bundle. Der Browser lädt das Bundle, führt es aus, und erst dann entsteht der sichtbare Content — durch JavaScript, das die DOM-Struktur dynamisch aufbaut.

Das Kernproblem

Googlebot crawlt in zwei Wellen. Welle 1: HTML sofort nach dem Request — das ist bei einem SPA ohne SSR oft nur ein leeres <div id="root"></div>. Welle 2: JavaScript-Rendering, verzögert um Stunden bis Tage. Inhalte, die erst in Welle 2 indexiert werden, ranken später, tauchen in GSC-Berichten verzögert auf und werden bei häufigen Deployments möglicherweise nie vollständig gecrawlt.

Google hat das JavaScript-Rendering-Problem erkannt und verbessert kontinuierlich seine Crawling-Infrastruktur. Aber selbst 2026 gilt: Server-Side Rendering ist zuverlässiger als auf Googlebots JS-Execution zu vertrauen. Die Google-eigene Dokumentation empfiehlt explizit SSR oder Static Generation für SEO-kritische Inhalte.

II

Die vier Rendering-Strategien und ihre SEO-Implikationen

Strategie Wie SEO Ideal für
CSR
Client-Side Rendering
JS im Browser rendert alles Kritisch Apps hinter Login, keine SEO-Anforderung
SSR
Server-Side Rendering
Vollständiges HTML per Request Sehr gut Dynamische Seiten (User-Content, Echtzeit)
SSG
Static Site Generation
HTML beim Build generiert Optimal Blog, Docs, Marketing-Seiten
ISR
Incremental Static Regen.
SSG + zeitgesteuerte Neugenerierung Sehr gut Häufig aktualisierte statische Inhalte
Hybrid
SSR + SSG gemischt
Pro Route konfigurierbar Gut (wenn richtig) Große Apps mit unterschiedlichen Anforderungen

Für while.chat und vergleichbare Blogs mit statischen Artikeln ist SSG die richtige Wahl: Artikel werden beim Build zu HTML kompiliert, Vercel liefert fertige HTML-Dateien aus dem CDN, Googlebot bekommt vollständiges HTML in Welle 1. Kein JavaScript-Rendering erforderlich.

III

Next.js SEO: Die kritischen Konfigurationspunkte

Next.js macht vieles richtig — aber die SEO-Defaults sind nicht automatisch optimal. Diese Punkte müssen explizit konfiguriert werden.

1. Metadata API (App Router, Next.js 13+)

Im App Router erfolgt Metadaten-Konfiguration über das metadata-Objekt oder die generateMetadata-Funktion — nicht mehr über next/head.

// app/posts/[slug]/page.tsx export async function generateMetadata({ params }) { const post = await getPost(params.slug); return { title: post.title, description: post.excerpt, openGraph: { title: post.title, description: post.excerpt, url: `https://while.chat/posts/${params.slug}`, type: 'article', }, alternates: { canonical: `https://while.chat/posts/${params.slug}`, }, }; }

2. generateStaticParams für SSG

Ohne generateStaticParams rendert Next.js dynamische Routen on-demand (SSR). Für Blog-Artikel, die sich selten ändern, ist SSG die richtige Wahl:

// app/posts/[slug]/page.tsx export async function generateStaticParams() { const posts = await getAllPosts(); return posts.map(p => ({ slug: p.slug })); } // Beim Build werden alle Slugs als statisches HTML generiert

3. Sitemap.xml dynamisch generieren

Next.js 13.3+ unterstützt eine sitemap.ts-Datei im App Directory, die automatisch eine /sitemap.xml-Route erzeugt:

// app/sitemap.ts import { getAllPosts } from '@/lib/posts'; export default async function sitemap() { const posts = await getAllPosts(); return [ { url: 'https://while.chat', lastModified: new Date(), priority: 1 }, { url: 'https://while.chat/artikel', lastModified: new Date(), priority: 0.9 }, ...posts.map(p => ({ url: `https://while.chat/posts/${p.slug}`, lastModified: new Date(p.updatedAt), priority: 0.8, })), ]; }

4. robots.txt

// app/robots.ts export default function robots() { return { rules: { userAgent: '*', allow: '/' }, sitemap: 'https://while.chat/sitemap.xml', }; }
IV

Core Web Vitals: Was im SPA-Kontext besonders wichtig ist

Core Web Vitals sind Google-Ranking-Faktoren seit Mai 2021. Im SPA-Kontext versagen einige klassische Optimierungsansätze, weil sie für serverseitig gerenderte Seiten entwickelt wurden.

LCP — Largest Contentful Paint

Ziel: unter 2,5 Sekunden. Das größte sichtbare Element (meist Hero-Bild oder H1) muss schnell laden. Häufiger SPA-Fehler: Das LCP-Element ist ein dynamisch geladenes Bild ohne priority-Flag. In Next.js:

  • Hero-Bild mit <Image priority /> markieren
  • Fonts mit preload-Link im Head
  • Critical CSS inline im Initial-HTML

INP — Interaction to Next Paint

Ersetzt CLS seit März 2024. Ziel: unter 200ms. Misst die Reaktionszeit auf User-Inputs. In React-Apps häufige Ursachen: schwere Re-Renders durch unkontrollierte State-Updates, synchrone Event-Handler, lange JavaScript-Tasks. Fixes:

  • React useTransition für nicht-kritische Updates
  • Code-Splitting mit dynamischen Imports
  • Debounce auf häufige Event-Handler

CLS — Cumulative Layout Shift

Ziel: unter 0,1. Visuelle Stabilität während des Ladens. In SPAs typische Ursachen: Bilder ohne definierte Dimensionen, dynamisch eingefügte Elemente (Consent-Banner, Cookie-Notices), Web-Fonts die FOUT erzeugen. Fixes:

  • Immer width und height auf <Image>
  • Fonts mit font-display: optional oder swap
  • Consent-Banner per CSS reservierter Raum

TTFB — Time to First Byte

Kein offizieller CWV, aber starker Ranking-Indikator. Ziel: unter 800ms. Bei Vercel-Deployment: Edge-Functions und CDN-Caching halten TTFB typischerweise unter 100ms für statische Assets. Kritisch wird es bei SSR-Routen mit Datenbank-Queries ohne Caching.

  • Statische Routen bevorzugen (SSG statt SSR)
  • unstable_cache für Datenbankabfragen
  • Edge-Runtime für leichte API-Routes
V

Strukturierte Daten in Next.js implementieren

Schema.org JSON-LD ist für Generative Engine Optimization genauso wichtig wie für klassisches SEO — und in Next.js einfach zu implementieren, wenn der richtige Ort dafür bekannt ist.

// Artikel-Seite: JSON-LD als Script-Tag im Head export default function PostPage({ post }) { const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', headline: post.title, description: post.excerpt, author: { '@type': 'Person', name: 'Max Goette' }, datePublished: post.publishedAt, dateModified: post.updatedAt, }; return ( <> <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} /> {/* Artikel-Content */} </> ); }

Für FAQ-Seiten das FAQPage-Schema ergänzen:

const faqSchema = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faqs.map(f => ({ '@type': 'Question', name: f.question, acceptedAnswer: { '@type': 'Answer', text: f.answer }, })), };
VI

Die häufigsten Technical-SEO-Fehler im SPA-Stack

Diese Probleme treten in der Mehrheit der SPA-Projekte auf, die noch nicht explizit auf SEO optimiert wurden.

Fehler 1 — Dynamische Redirects ohne 301-Status: In Next.js können Redirects in next.config.js mit explizitem permanent: true als 301 konfiguriert werden. Client-seitige Redirects (via useRouter().push()) übertragen keinen SEO-Wert und sollten für SEO-kritische URLs nicht genutzt werden.

Fehler 2 — Duplicate Content durch trailing Slash: /artikel und /artikel/ sind für Google unterschiedliche URLs ohne Canonical-Tag. Next.js-Default: trailingSlash: false in next.config.js setzen und in der Sitemap konsequent eine Variante nutzen.

Fehler 3 — Fehlende oder falsche Canonical-Tags: Besonders bei paginierten Inhalten (/artikel?page=2) müssen Canonical-Tags auf die Hauptseite zeigen — oder jede Seite hat ihren eigenen Canonical. Beides ist valide, Inkonsistenz nicht.

Fehler 4 — JavaScript-Fehler blockieren Indexierung: Ein einzelner unbehandelter JS-Fehler kann dazu führen, dass Googlebot die Seite nicht vollständig rendert. Fehler-Boundaries in React implementieren und Core-Rendering-Fehler in der Google Search Console überwachen (Abschnitt "Abdeckung").

Fehler 5 — Sitemap nicht in GSC eingereicht: Eine vorhandene Sitemap wird von Google nicht automatisch gefunden. GSC → Sitemaps → Sitemap-URL einreichen. Nach jedem Major-Deployment neu validieren.

Quick-Check: Ist deine SPA SEO-ready?

Öffne die Seite in Chrome → Rechtsklick → "Seitenquelltext anzeigen" (nicht Devtools Inspect). Wenn der Hauptinhalt im Quelltext sichtbar ist: SSR oder SSG funktioniert. Wenn der Quelltext nur ein leeres <div id="root"> enthält: Du hast ein reines CSR-Setup, das Googlebot kaum crawlen kann.

Häufige Fragen zu Technical SEO und SPAs

Kann Googlebot JavaScript-SPAs wirklich nicht indexieren?

Googlebot kann JavaScript rendern — aber langsamer und weniger zuverlässig als ein Browser. Google unterscheidet zwei Crawling-Wellen: Welle 1 liest das initiale HTML sofort, Welle 2 rendert JavaScript verzögert (Stunden bis Tage). Inhalte, die erst nach JS-Execution sichtbar sind, werden später und weniger zuverlässig indexiert. Für neue Seiten und häufige Updates ist SSR oder SSG deutlich verlässlicher als auf Welle 2 zu warten.

Was ist der Unterschied zwischen SSR und SSG in Next.js für SEO?

Beide liefern vollständiges HTML an Googlebot. Der Unterschied: SSG generiert das HTML beim Build-Zeitpunkt — jeder Request bekommt das gleiche, gecachte HTML vom CDN. SSR generiert das HTML bei jedem Request neu. Für SEO-Zwecke sind beide gleichwertig. Für Performance ist SSG besser (TTFB nahe 0ms vom CDN), für dynamische Inhalte (personalisierte Seiten, Echtzeit-Daten) ist SSR notwendig.

Wie überprüfe ich, ob meine Next.js-Seite korrekt gecrawlt wird?

Drei Methoden: Erstens, "Seitenquelltext anzeigen" im Browser — vollständiges HTML im Source bedeutet SSR/SSG funktioniert. Zweitens, Google Search Console → URL-Prüfung → URL eingeben → "Indexierte Seite abrufen" — zeigt exakt, was Googlebot sieht. Drittens, Google Search Console → Abdeckung → "Entdeckt, aber nicht indexiert" und "Gecrawlt, aber nicht indexiert" analysieren — häufig symptomatisch für JS-Rendering-Probleme.

Brauche ich eine XML-Sitemap wenn meine Next.js-App alle Links intern verlinkt?

Ja. Auch bei vollständiger interner Verlinkung beschleunigt eine Sitemap die Entdeckung neuer Seiten erheblich. Besonders wichtig bei Neu-Deployments und nach der Indexierungs-Reinigung (z.B. nach Slug-Änderungen). Die Sitemap sollte in Google Search Console eingereicht und nach jedem Major-Deployment validiert werden.

Hat Vercel-Deployment einen Einfluss auf SEO?

Indirekt, positiv. Vercel's Edge Network liefert statische Assets aus geografisch nahen CDN-Knoten — TTFB für statische Routes typischerweise unter 50ms. Das verbessert Core Web Vitals (TTFB, LCP) spürbar. Vercel-specific: Deploy Previews bekommen automatisch X-Robots-Tag: noindex, sind also nicht indexierbar. Preview-URLs landen nicht in Googles Index. Nur Production-Deployments werden indexiert.

Quellen