Astro & SEO: Warum statische Seiten besser ranken
Kurz gesagt
SEO mit Astro heißt: statisches HTML als Basis und dazu ein paar Dinge bewusst im Code setzen – Meta-Tags und Canonical im Layout, @astrojs/sitemap, robots.txt, JSON-LD pro Seitentyp, Längen-Regeln per Content-Collection-Schema, astro:assets für Bilder, eine feste Trailing-Slash-Regel und hreflang bei mehreren Sprachen. Kein SEO-Plugin nötig. Was Astro nicht liefert, sind Inhalte, Backlinks und Suchvolumen – das bleibt redaktionelle Arbeit.
„Astro ist gut für SEO” – das liest man häufig. Und das stimmt – aber nur zur Hälfte. Astro löst auf technischer Ebene echte SEO-Probleme: statisches HTML, minimales JavaScript, starke Core Web Vitals. Was es nicht löst: die inhaltliche Arbeit, die Google eigentlich honoriert. Diese Website läuft auf Astro, zweisprachig, vollständig statisch ausgeliefert. Was wir dabei gemessen und gelernt haben, liegt diesem Beitrag zugrunde.
Der Artikel erklärt ohne Hype, warum statische Architektur technisch bevorzugt wird, wo die Grenzen liegen und wie sich Astro ehrlich gegen WordPress aufstellt – auf Grundlage eigener Erfahrung, nicht Theorie.
Warum Astro SEO-freundlich ist
Wenn Google eine Seite crawlt, schickt der Crawler zuerst eine Anfrage für das nackte HTML-Dokument. Was er bekommt, bestimmt, was indiziert wird. Bei einer statischen Astro-Seite bekommt er genau das: vollständiges, direkt lesbares HTML – ohne Wartezeit auf JavaScript-Ausführung, ohne Server-Side-Rendering-Overhead, ohne den Umweg über einen PHP-Interpreter.
Das ist kein Zufall, sondern die Architektur: Astro baut Seiten zur Build-Zeit vor. Zur Laufzeit gibt es kein Rendering mehr – das HTML ist fertig und wird direkt ausgeliefert. Das hat drei direkte SEO-Konsequenzen:
Crawler sehen sofort alle Inhalte. Googles Crawler kann JavaScript ausführen, aber es gibt eine zweistufige Indizierung: zuerst das HTML, später – mit unbekannter Verzögerung – der gerenderte JavaScript-Inhalt. Bei Astro gibt es diese Verzögerung nicht.
Core Web Vitals fallen von Haus aus gut aus. Der Largest Contentful Paint (LCP) – das erste sichtbare, große Element – lädt bei statischen Seiten deutlich früher, weil nichts auf serverseitige Verarbeitung oder Client-Rendering warten muss. Unsere eigene Seite hat auf Desktop einen LCP von 0,4 Sekunden, ohne dass wir das explizit optimiert haben.
Kaum JavaScript bedeutet kaum Blockierung. Astro schickt standardmäßig kein JavaScript an den Browser – es sei denn, es wird explizit angefordert (Islands Architecture). Was nicht geladen wird, kann nicht das Rendering blockieren. Die Total Blocking Time (TBT) auf unserer Seite liegt bei 0 ms.
Die technischen SEO-Vorteile im Detail
Ladezeit und LCP
LCP ist das Kernstück der Core Web Vitals-Bewertung. Google zählt die Core Web Vitals zu den Signalen der Page Experience, die in die Bewertung einfließen – betont in seiner Dokumentation für Google Search Central aber auch, dass relevante, hilfreiche Inhalte schwerer wiegen. Schnelle Ladezeit ersetzt also keinen Inhalt, ist aber ein Vorteil, wenn die Inhalte vergleichbar gut sind. Bei statischen Seiten ist LCP strukturell besser: Die Seite wird nicht erst auf dem Server zusammengebaut oder im Browser gerendert, sondern liegt fertig als HTML bereit – auf dem Webserver oder in einem CDN. Das ergibt schnelle Antwortzeiten – selbst auf einfacheren Hosting-Infrastrukturen.
Wie das in der Praxis aussieht, haben wir im Detail in 100/100 PageSpeed mit Astro beschrieben – mit echten Messwerten von dieser Website.
Kein Client-Rendering-Problem
Bei React-lastigen Frameworks oder klassischem WordPress mit Page-Builder ergibt sich oft ein Problem: Der Browser bekommt zunächst ein fast leeres HTML-Dokument und baut die Seite dann durch JavaScript auf. Google kann das prinzipiell verstehen, aber es hat Risiken: Rendering-Fehler, zu langsame Ausführung, fehlende Meta-Tags zum Zeitpunkt des Crawls. Bei Astro gibt es das nicht. Der Crawler bekommt immer das vollständige, finale Dokument.
Das gilt besonders für Open-Graph-Tags und JSON-LD-Strukturdaten: Wenn diese erst durch JavaScript gesetzt werden, kann der Crawler sie beim ersten Besuch übersehen. Bei Astro sind sie im statischen HTML – ohne Wenn und Aber.
Astro-SEO in der Praxis: was du im Code einrichtest
Statisches HTML ist die Grundlage. Ranken kann eine Seite aber erst, wenn Titel, Canonical, Sitemap, Strukturdaten und Bilder stimmen. In Astro sind das jeweils ein paar Zeilen, aber du musst sie bewusst setzen. Die Beispiele unten sind gekürzt; die APIs haben wir gegen die Astro-Dokumentation (Stand Astro 7) geprüft.
Meta-Tags und Canonical im Layout
Ein einziges Layout-Component rendert den <head> für jede Seite. Die Seite reicht Titel und Beschreibung als Props durch, Canonical und Social-Tags werden daraus abgeleitet:
---
// src/layouts/BaseLayout.astro
interface Props {
title: string;
description: string;
noindex?: boolean;
}
const { title, description, noindex = false } = Astro.props;
const canonical = new URL(Astro.url.pathname, Astro.site);
---
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonical} />
{noindex && <meta name="robots" content="noindex" />}
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonical} />
<slot name="head" />
</head>
<body><slot /></body>
</html>
Astro.site ist die site-URL aus der astro.config.mjs. Ohne sie bleibt der Wert undefined – setz sie deshalb immer. Weil du nur den pathname übernimmst, bleibt der Canonical auch dann sauber, wenn die Seite mit Tracking-Parametern aufgerufen wird. Ein Beispiel für „Canonical über zwei Domains” findest du in Mehrsprachiges Astro: zwei Domains, zwei Sprachen, ein Build.
Sitemap mit @astrojs/sitemap
npx astro add sitemap
// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com', // Pflicht
integrations: [
sitemap({
filter: (page) => !page.includes('/danke/') && !page.includes('/impressum/'),
}),
],
});
Die Integration schreibt beim Build sitemap-index.xml und sitemap-0.xml. Mit filter nimmst du Seiten heraus, die nicht in die Suche sollen. changefreq und priority kannst du setzen, die Astro-Dokumentation weist aber selbst darauf hin, dass Google sie ignoriert. Wichtiger ist, dass nur indexierbare URLs in der Sitemap stehen: keine Weiterleitungen, keine noindex-Seiten.
robots.txt
Die einfachste Lösung ist eine Datei public/robots.txt. Willst du die Sitemap-URL aus der site-Einstellung ableiten, nimmst du einen Endpoint:
// src/pages/robots.txt.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ site }) => {
const sitemap = new URL('sitemap-index.xml', site);
return new Response(`User-agent: *\nAllow: /\n\nSitemap: ${sitemap.href}\n`);
};
Der Dateiname bestimmt das Ausgabeformat: robots.txt.ts wird beim Build zu /robots.txt. Denk daran: Disallow in der robots.txt verhindert das Crawlen, nicht zuverlässig das Indexieren. Eine Seite, die nicht in der Suche auftauchen soll, bekommt noindex im HTML und bleibt crawlbar.
Strukturierte Daten pro Seitentyp
JSON-LD gehört ins statische HTML. Du baust dafür eine kleine Komponente, die ein Objekt serialisiert:
---
// src/components/JsonLd.astro
const { data } = Astro.props;
---
<script type="application/ld+json" set:html={JSON.stringify(data)} />
Astro bündelt nur <script>-Tags ohne Attribute; ein Tag mit type="application/ld+json" bleibt unverändert im HTML. Je Seitentyp setzt du anderes Markup ein:
- Startseite oder Unternehmensseite:
Organizationmit Name, URL, Logo und Kontaktdaten. - Artikel:
BlogPostingmitheadline,datePublished,dateModified,authorund, wenn vorhanden,abstract. Die Daten kommen aus dem Frontmatter, nicht aus einem zweiten Pflegeort. - Seiten mit Brotkrumen:
BreadcrumbList. - Häufige Fragen:
FAQPage, aus denselben Daten wie die sichtbare FAQ.
Das Markup muss zum sichtbaren Inhalt passen. Strukturierte Daten, die auf der Seite nicht vorkommen, helfen nicht, im ungünstigen Fall schaden sie. Prüfen kannst du das Ergebnis mit dem Rich-Results-Test von Google.
Content Collections: Längen im Schema erzwingen
Die verlässlichste Art, schlechte Meta-Daten zu vermeiden: Der Build bricht ab, wenn sie nicht passen. Content Collections validieren das Frontmatter mit einem Zod-Schema:
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const artikel = defineCollection({
loader: glob({ base: './src/content/artikel', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string().min(10).max(70),
description: z.string().min(120).max(160),
publishedAt: z.coerce.date(),
updatedAt: z.coerce.date().optional(),
}),
});
export const collections = { artikel };
Verletzt ein Artikel das Schema, meldet Astro den Fehler beim Build, bevor etwas live geht. Wir setzen das für alle Insights ein: Titel, Beschreibung und die Kurzfassung haben feste Grenzen, und ein vergessenes Feld fällt auf, bevor es jemand sieht. Dieselben Daten füttern danach Meta-Tags, Open Graph und das JSON-LD aus dem Layout.
Bilder mit astro:assets
Bilder sind meist der LCP-Kandidat. Die <Image />-Komponente aus astro:assets optimiert lokale Bilder beim Build und setzt width und height, was Layout-Verschiebungen (CLS) verhindert:
---
import { Image } from 'astro:assets';
import hero from '../assets/hero.jpg';
---
<Image src={hero} alt="Das Team vor dem Büro" format="webp" fetchpriority="high" loading="eager" />
Das Bild über dem Falz lädst du sofort und mit hoher Priorität, alle weiteren bleiben beim Standard (loading="lazy"). Ein sinnvoller alt-Text ist Pflicht (die Komponente verlangt ihn) und hilft auch der Bildersuche. Entfernte Bilder optimiert Astro nur, wenn du die Quelle in der Konfiguration unter image.domains oder image.remotePatterns freigibst. Wie sich das auf die Messwerte auswirkt, steht in 100/100 PageSpeed mit Astro.
Trailing Slash und Weiterleitungen
Eine Seite soll unter genau einer URL erreichbar sein. Sonst konkurrieren /leistungen und /leistungen/ miteinander. Lege es fest:
// astro.config.mjs
export default defineConfig({
trailingSlash: 'always', // oder 'never'; Standard ist 'ignore'
redirects: {
'/alter-pfad/': '/neuer-pfad/',
},
});
Mit 'always' oder 'never' legt Astro die Schreibweise für das Routing fest. Ob die falsche Variante bei statischem Hosting auch per Redirect umgeleitet wird, entscheidet dein Webserver – prüf das einmal mit curl -I. Wichtig bei redirects: Ohne Adapter erzeugt Astro bei einem statischen Build nur HTML-Dateien mit <meta http-equiv="refresh">. Das ist kein echter 301. Für einen sauberen 301 trägst du die Weiterleitung zusätzlich in der Server-Konfiguration ein (bei Apache in der .htaccess) oder nutzt einen Adapter, der sie in die Konfiguration deines Hosters schreibt. Wir pflegen bei Seitenumzügen beides, weil ein Umzug ohne echten 301 Rankings kosten kann.
Mehrsprachigkeit und hreflang
Für zweisprachige Seiten brauchst du drei Dinge: pro Sprache eine eigene URL, einen Canonical, der auf die eigene Sprachversion zeigt, und gegenseitige hreflang-Verweise:
<link rel="alternate" hreflang="de" href="https://example.de/leistungen/" />
<link rel="alternate" hreflang="en" href="https://example.com/services/" />
<link rel="alternate" hreflang="x-default" href="https://example.de/leistungen/" />
Die Verweise müssen in beide Richtungen gesetzt sein, und jede Seite verweist auch auf sich selbst. Setz sie nur, wenn es die andere Sprachversion wirklich gibt. Astro bringt mit der i18n-Konfiguration (locales, defaultLocale, routing.prefixDefaultLocale) das Routing mit, und getRelativeLocaleUrl() aus astro:i18n baut dir die Links. Die Sitemap-Integration kann über ihre i18n-Option zusätzlich xhtml:link-Einträge mit hreflang ausgeben. Die vollständige Umsetzung mit zwei Domains beschreiben wir in Mehrsprachiges Astro: zwei Domains, zwei Sprachen, ein Build.
Islands, View Transitions und Crawlbarkeit
Ohne client:*-Direktive rendert Astro jede UI-Komponente zu reinem HTML und CSS. Mit client:load, client:idle, client:visible oder client:media hydriert nur die einzelne Insel. Der serverseitig gerenderte Inhalt steht trotzdem im HTML, ein Crawler sieht ihn also. Anders ist es bei client:only: Dort wird nichts vorab gerendert, die Komponente erscheint erst im Browser. Alles, was ranken soll (Überschriften, Fließtext, interne Links), gehört deshalb nicht in eine client:only-Insel.
Für Übergänge zwischen Seiten gibt es <ClientRouter /> aus astro:transitions. Er holt die nächste Seite per Fetch und tauscht den Inhalt im Browser aus. Aus unserer Sicht ändert das für Crawler wenig, weil jede URL beim direkten Aufruf weiterhin vollständiges HTML liefert und deine Links normale <a href>-Tags bleiben. Die Astro-Dokumentation äußert sich zum Crawler-Verhalten nicht ausdrücklich; das ist unsere Einschätzung, keine Zusicherung von Google. Wenn du nur einen Übergangseffekt willst, reicht auch die native CSS-Funktion @view-transition, die ohne Router auskommt. Mehr JavaScript heißt immer auch mehr Last für die Core Web Vitals, wie sich das messen lässt, steht in 100/100 PageSpeed mit Astro.
llms.txt kurz
Eine llms.txt ist eine maschinenlesbare Übersicht deiner wichtigsten Seiten für KI-Systeme. In Astro baust du sie als Endpoint (src/pages/llms.txt.ts) aus denselben Daten wie Navigation und Sitemap, statt sie von Hand zu pflegen. Was das bringt und was nicht, steht in llms.txt in der Praxis.
Wo Astro allein nicht reicht
Hier ist die Stelle, die in den meisten Framework-Artikeln fehlt: Technik ist nicht SEO. Technik ist die Grundlage, auf der SEO überhaupt funktionieren kann.
Eine Astro-Site, die schnell lädt und sauber gebaut ist, aber kaum Inhalte hat, wird Google nicht überzeugen. Was Google wirklich bewertet, ist die Kombination aus:
- Inhalten, die Suchanfragen wirklich treffen. Keyword-Recherche, Suchintention, Informationstiefe – das ist redaktionelle Arbeit, die kein Framework abnimmt.
- Autorität und Backlinks. Eine neue Seite, egal auf welcher Technologie, braucht Zeit und externe Verlinkungen, um in den Rankings aufzusteigen. Ein guter LCP hilft dabei nicht direkt.
- Konsistente Pflege. Regelmäßige neue Inhalte, Aktualisierung veralteter Seiten, technische Audits – das ist Betriebsarbeit.
Astro stellt sicher, dass die Technik dir nicht im Weg steht. Das ist ein echter Vorteil. Aber es ist kein Turbo, der dünnen Content nach oben schiebt. Wer mit Astro in die organische Suche investiert, kommt an ernsthafter Content-Arbeit nicht vorbei.
Astro-SEO vs. WordPress-SEO
Diese Frage bekommen wir oft: „Ist Astro besser für SEO als WordPress?” Die ehrliche Antwort: technisch ja, inhaltlich unentschieden.
WordPress hat über Jahrzehnte einen seriösen SEO-Ruf aufgebaut – Yoast, RankMath und Co. sind ausgereifte Tools, und Millionen von WordPress-Seiten ranken gut. Aber WordPress schleppt technische Altlasten mit: PHP-Rendering bei jedem Request, Plugin-Stapel, die JavaScript häufen, und eine LCP-Kurve, die ohne Tuning schnell in den gelben Bereich rutscht. Das ist kein grundlegendes Problem – wir bauen selbst WordPress-Seiten, die Core Web Vitals bestehen. Aber es ist konsequenter Aufwand.
Bei Astro ist die technische Ausgangslage besser – nicht durch nachträgliche Optimierung, sondern durch Architektur. Die Lighthouse-Scores, die wir ohne explizites SEO-Tuning erreichen, wären auf WordPress nur mit erheblichem Konfigurationsaufwand zu reproduzieren.
Was Astro fehlt: die Klick-Oberfläche für Redakteure. Wer eine Seite mit wechselnden Inhalten, verschiedenen Redakteuren und täglichem Publishing-Bedarf betreibt, braucht entweder ein Headless CMS oder bleibt sinnvollerweise bei WordPress. Den vollständigen Vergleich – inklusive konkreter Entscheidungskriterien – findest du in Astro vs. WordPress.
Für inhaltslastige Seiten mit stabilem Redaktionsprozess – genau das, was viele Unternehmenswebsites sind – ist Astro SEO-technisch die bessere Ausgangslage. Ob das für dein Projekt zutrifft, besprichst du am besten direkt mit uns: Astro-Agentur.
Häufige Fragen
Ist Astro wirklich gut für SEO?
Ja – aus technischer Sicht ist Astro eine der besten Grundlagen für SEO, die es aktuell gibt. Statisches HTML, sehr wenig JavaScript und starke Core-Web-Vitals-Werte treffen exakt das, was Google technisch bevorzugt. Was Astro nicht liefert: Inhalte, Backlinks und Suchvolumen. Das ist menschliche Arbeit – kein Framework ersetzt sie.
Brauche ich ein SEO-Plugin für Astro?
Anders als WordPress braucht Astro kein Plugin, um SEO zu ermöglichen. Meta-Tags, Open-Graph-Daten und strukturierte Daten setzt du direkt im Code – präzise und ohne Plugin-Overhead. Wer trotzdem etwas Fertiges will, greift zu astro-seo oder @astrojs/sitemap, die beide ohne Performance-Kosten arbeiten.
Wie wirkt sich Astro auf den LCP aus?
Erheblich. Weil Astro statisches HTML ausliefert und kein Client-Rendering durchläuft, steht das erste sichtbare Element wesentlich früher bereit als bei einer gerenderten React- oder WordPress-Seite. Unsere eigene Website erreicht auf Desktop einen LCP von 0,4 Sekunden – ohne spezielle Optimierung, nur durch die Architektur.
Kann Astro WordPress bei SEO schlagen?
Technisch ja, inhaltlich nein – das ist keine Frage des Frameworks. Eine Astro-Seite ohne Inhalte verliert gegen eine gut gepflegte WordPress-Seite. Eine Astro-Seite mit solidem Content hat aber bessere Karten bei Core Web Vitals, was Google als Rankingfaktor berücksichtigt. Wer beide Welten will, kombiniert Astro als Frontend mit WordPress als Headless-CMS.
Wie mache ich SEO mit Astro Schritt für Schritt?
Setz Titel, Beschreibung und Canonical in einem gemeinsamen Layout. Erzeuge die Sitemap mit @astrojs/sitemap und verweise in der robots.txt darauf. Gib JSON-LD passend zum Seitentyp aus, erzwinge Titel- und Beschreibungslängen per Content-Collection-Schema und binde Bilder über astro:assets ein. Lege eine Trailing-Slash-Regel fest und setze bei mehreren Sprachen hreflang in beide Richtungen.
Schaden View Transitions oder JavaScript-Islands dem SEO?
Nicht automatisch. Komponenten ohne client:-Direktive und Islands mit client:load, client:idle oder client:visible stehen als HTML im Dokument. Anders bei client:only: Dort wird nichts vorab gerendert. Wichtige Inhalte und interne Links gehören deshalb nicht in solche Inseln. Der ClientRouter für View Transitions ändert nichts daran, dass jede URL beim direkten Aufruf vollständiges HTML liefert.
Passende Leistungen
Gründer & Full-Stack-Entwickler
20+ Jahre Erfahrung in der Webentwicklung. Spezialisiert auf Laravel, WordPress und individuelle Software für den Mittelstand.