TanStack SEO Guide: So ranken Sie Ihre App in 2026

TanStack SEO-Setup, das funktioniert: SSR mit TanStack Start, Meta Tags, Sitemaps, strukturierte Daten und Core Web Vitals – eine Checkliste für Top-Rankings 2026.

Huifer
Huifer
18. September 20269 min read
Auch verfügbar auf:English · 中文

Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Ich habe drei SaaS-Produkte mit TanStack-Bibliotheken entwickelt, und jedes einzelne hatte beim Launch dasselbe SEO-Problem: Google indexierte das JavaScript, rendert nichts und zeigte die falsche Meta-Beschreibung in den Suchergebnissen. Die Lösung war stets SSR – Server-Side Rendering. Aber SSR mit TanStack-Bibliotheken in einem benutzerdefinierten Vite-Setup einzurichten, ist schmerzhaft. TanStack Start löst dieses Problem, indem es SSR zum Standard macht – nicht zur Nachdenksache. Dieser Guide deckt ab, was ich beim Sichtbarmachen von TanStack-Apps für Google gelernt habe.

Verifizierte Quellen: TanStack Start SSR · Google SSR SEO-Dokumentation · Core Web Vitals · Strukturierte Daten Letztes Update: 2026-09-18 · Changelog

TL;DR: Drei Dinge machen eine TanStack-App rankfähig: SSR (damit Google den gerenderten HTML-Code sieht), korrekte Meta Tags pro Route und Core Web Vitals, die bestehen. TanStack Start handhabt alle drei nativ. Das ist der vollständige Implementierungsguide.


Das SSR-Problem mit TanStack-Apps

Single-Page-Apps, die mit TanStack Router, TanStack Query und React gebaut wurden, haben ein Rendering-Problem: Googlebot indexiert das JavaScript, wartet aber nicht auf dessen Ausführung. Das Ergebnis: Google sieht eine leere Seite oder den falschen Inhalt.

Die Lösung ist Server-Side Rendering. Mit SSR führt der Server den React-Komponentenbaum aus, erzeugt HTML und sendet dieses HTML an Google. Das JavaScript wird danach auf dem Client ausgeführt – die sogenannte „Hydration"-Phase.

Für TanStack-Apps gibt es zwei Wege:

  1. TanStack Start: SSR ist integriert. Das Framework handhabt Hydration, Meta Tags und Caching automatisch.
  2. Benutzerdefiniertes Vite + React-Setup: SSR erfordert eine manuelle Konfiguration mit @vitejs/plugin-react und einem Node.js-Server.

TanStack Start ist die richtige Wahl für neue Projekte. Dieser Guide deckt beide Wege ab.


TanStack Start: SSR von Haus aus

TanStack Start bietet erstklassige SSR-Unterstützung. Routes werden auf dem Server gerendert und senden HTML an den Client:

typescript
// src/routes/posts.$postId.tsx
import { createFileRoute, Link } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/start/server'

const fetchPost = createServerFn({ method: 'GET' })
  .validator(z.object({ postId: z.string() }))
  .handler(async ({ data }) => {
    const post = await db.post.findUnique({ where: { id: data.postId } })
    if (!post) throw new Response('Not Found', { status: 404 })
    return post
  })

export const Route = createFileRoute('/posts/$postId')({
  validateSearch: z.object({
    ref: z.string().optional(),
  }),
  loader: async ({ params, deps }) => {
    const post = await deps.posts.findUnique(params.postId)
    return { post }
  },
  meta: ({ params, deps }) => [
    { title: `${deps.post?.title} | My App` },
    { name: 'description', content: deps.post?.description },
    { property: 'og:title', content: deps.post?.title },
    { property: 'og:image', content: deps.post?.ogImage },
  ],
  component: PostPage,
})

Die meta-Funktion setzt Meta Tags pro Route. Google liest diese aus dem server-gerenderten HTML – ohne JavaScript-Ausführung.


Meta Tags: Das Per-Route-Muster

In TanStack Start werden Meta Tags pro Route über die meta-Funktion gesetzt. Die Tags werden server-seitig gerendert und in den HTML-<head> eingefügt:

typescript
export const Route = createFileRoute('/products/$productId')({
  loader: async ({ params }) => {
    const product = await getProduct(params.productId)
    return { product }
  },
  meta: ({ data }) => [
    { title: `${data.product.name} — Buyer's Guide` },
    { name: 'description', content: truncate(data.product.description, 160) },
    { property: 'og:title', content: data.product.name },
    { property: 'og:description', content: data.product.description },
    { property: 'og:image', content: data.product.heroImage },
    { property: 'og:type', content: 'product' },
    { name: 'twitter:card', content: 'summary_large_image' },
    // Strukturierte Daten
    { tagName: 'script', type: 'application/ld+json', children: JSON.stringify({
      '@context': 'https://schema.org',
      '@type': 'Product',
      name: data.product.name,
      description: data.product.description,
      image: data.product.heroImage,
      offers: {
        '@type': 'Offer',
        price: data.product.price,
        priceCurrency: 'USD',
      },
    })},
  ],
  component: ProductPage,
})

Die JSON-LD-Strukturdaten machen das Produkt für Googles Product Rich Results berechtigt – die Sterne und der Preis im Such-Snippet.


Sitemap-Generierung

TanStack Start generiert Sitemaps automatisch:

typescript
// src/routes/sitemap.xml.ts
import { createFileRoute } from '@tanstack/react-router'
import { db } from '@/lib/db'

export const Route = createFileRoute('/sitemap.xml')({
  loader: async () => {
    const posts = await db.post.findMany({
      where: { status: 'published' },
      select: { slug: true, updatedAt: true },
    })

    const staticRoutes = [
      '/',
      '/pricing',
      '/docs',
      '/blog',
    ]

    const dynamicRoutes = posts.map(post => `/blog/${post.slug}`)

    const allRoutes = [...staticRoutes, ...dynamicRoutes]

    return new Response(
      `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${allRoutes
  .map(
    route => `  <url>
    <loc>https://yourdomain.com${route}</loc>
    <lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
    <changefreq>${route === '/' ? 'daily' : 'weekly'}</changefreq>
    <priority>${route === '/' ? '1.0' : route.startsWith('/blog') ? '0.8' : '0.6'}</priority>
  </url>`
  )
  .join('\n')}
</urlset>`,
      {
        headers: { 'Content-Type': 'application/xml' },
      }
    )
  },
})

Über den Sitemaps-Bericht in der Google Search Console einreichen.


Core Web Vitals für TanStack-Apps

LCP (Largest Contentful Paint)

LCP ist das häufigste Vital-Problem bei TanStack-SPAs. Die Lösung: das Hero-Bild optimieren und sicherstellen, dass SSR bedeutsamen Inhalt liefert.

Bei TanStack Start mit SSR enthält das initiale HTML den server-gerenderten Inhalt. LCP misst das größte Bild oder Textblock im Viewport. Stellen Sie sicher, dass das Hero-Bild folgendes hat:

html
<!-- Das Hero-Bild vorladen, damit LCP schnell ist -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />

Setzen Sie außerdem fetchpriority="high" auf dem LCP-Bildelement:

tsx
<img
  src="/hero.webp"
  alt="Hero image"
  fetchpriority="high"
  loading="eager"
/>

INP (Interaction to Next Paint)

INP misst die Reaktionsfähigkeit auf Benutzerinteraktionen. TanStack Query-Mutationen, die die UI aktualisieren, können INP-Regressionen verursachen, wenn sie zu viel neu rendern.

Die Lösung: Mutationen auf die Daten beschränken, die sie aktualisieren, und optimistic Updates verwenden, damit Interaktionen sofort wirken:

typescript
const mutation = useMutation({
  mutationFn: updatePost,
  onMutate: async (newData) => {
    await queryClient.cancelQueries({ queryKey: ['post', newData.id] })
    const previous = queryClient.getQueryData(['post', newData.id])
    queryClient.setQueryData(['post', newData.id], newData)
    return { previous }
  },
  onError: (err, newData, context) => {
    queryClient.setQueryData(['post', newData.id], context.previous)
  },
})

CLS (Cumulative Layout Shift)

CLS tritt auf, wenn Inhalt nach dem initialen Rendern geladen wird und das Layout verschiebt. TanStack Querys placeholderData ist eine häufige CLS-Quelle – es rendert einen leeren Zustand, der sich verschiebt, wenn Daten eintreffen.

Beheben: placeholderData mit derselben Struktur wie reale Daten verwenden und explizite Dimensionen für Inhaltsbereiche setzen:

typescript
const { data } = useQuery({
  queryKey: ['post', postId],
  queryFn: () => fetchPost(postId),
  placeholderData: keepPreviousData, // Beibehaltung der vorherigen Struktur – kein CLS
})

Weiterführende Lektüre: Tanstack Query V5 Guide 2026 · Tanstack Query Best Practices Guide · Tanstack Pacer Complete Guide 2026

Die vollständige TanStack-SEO-Checklist

  • SSR aktiviert — TanStack Start SSR oder benutzerdefiniertes SSR-Setup mit Vite
  • Meta Tags pro Route — title, description, og:title, og:description für jede Route
  • Kanonische URLs — jede Seite hat ein <link rel="canonical">
  • Sitemap generiert — /sitemap.xml enthält alle öffentlichen Routen
  • Strukturierte Daten — JSON-LD für Produkte, Artikel, FAQs nach Bedarf
  • Hero-Bild vorgeladen — <link rel="preload"> mit fetchpriority="high"
  • LCP < 2,5s — mit PageSpeed Insights testen
  • INP < 200ms — optimistic Updates verwenden, große Re-Renders vermeiden
  • CLS < 0,1 — keepPreviousData verwenden, explizite Dimensionen setzen
  • Google Search Console verifiziert — Sitemap einreichen, Abdeckung überwachen

TanStack Ship wird mit vorkonfiguriertem TanStack Start SSR, Meta Tags, Sitemap-Generierung und Core Web Vitals-Optimierung ausgeliefert. Mehr dazu im TanStack Ship Deployment Guide und in der vollständigen Feature-Liste.