Migration von WordPress zu Astro in Geneva
Viele Unternehmen in Geneva nutzen WordPress, stoßen aber an Grenzen bei Performance, Sicherheit und Hosting-Kosten. Astro löst diese Probleme mit statischem HTML, null JavaScript und Edge-Deployment. Ich migriere bestehende WordPress-Seiten zu Astro mit vollständiger SEO-Erhaltung, URL-Mapping und 301-Weiterleitungen.
- PageSpeed 95-100
Statisches HTML ohne JavaScript. Schneller als jede WordPress-Lösung.
- SEO-sichere Migration
URL-Mapping, 301-Weiterleitungen, Google-Rankings erhalten.
- Hosting auf Cloudflare Pages
Globales CDN, kostenloses SSL, sofortige Deployments. Hosting-Kosten nahe null.
Technische SEO in Astro: was im Build entsteht
Ich bin Mariusz Szatkowski, arbeite seit 2006 mit WordPress und baue Websites heute auch mit Astro. Ich sitze in Gdynia, arbeite vollständig remote und schriftlich, ohne Meetings und Telefonate. Diese Seite richtet sich an Unternehmen in Genf, die wissen wollen, welche Suchmaschinen-Technik zu einer Astro-Website gehört und was davon im Build entsteht.
Mein Thema sind sieben Bausteine: die Sitemap-Integration, Canonical-URLs aus Astro.site, Meta- und Open-Graph-Tags in einer Layout-Komponente, Open-Graph-Bilder zur Build-Zeit, strukturierte Daten als JSON-LD, robots.txt und RSS mit @astrojs/rss. Astro-Angaben stammen aus docs.astro.build, Suchmaschinen-Angaben aus developers.google.com/search, die Open-Graph-Felder aus ogp.me. Versionen stammen aus der npm-Registry (Stand 11. November 2026): Astro 7.4.11, @astrojs/sitemap 3.7.4, @astrojs/rss 4.0.19.

Foto: Yann (talk), CC BY-SA 4.0, Wikimedia Commons.
Ein Blick auf die Website des Kantons zeigt, was bei einer Genfer Seite zuerst zu klären ist. Die Startseite von ge.ch war bei meinem Abruf am 11. November 2026 nur auf Französisch abrufbar und nennt im Fuss Kontakt, Zugänglichkeit (Accessibilité), Datenschutzerklärung (Politique de confidentialité) und Geschäftsbedingungen. Für Ihre Seite heisst das: Sprache und Region gehören ausdrücklich ins Markup, also lang="fr" am html-Element und ein passendes og:locale. Mehrsprachige Auftritte mit Sprachversionen beschreibe ich auf der Seite für Zürich.
Zuerst site: ohne diese Option stimmt nichts
Alles Weitere hängt an einer Zeile in astro.config.mjs. Die Konfigurationsreferenz beschreibt site als Ihre endgültige, veröffentlichte URL und sagt, dass Astro sie für Sitemap und Canonical-URLs im fertigen Build nutzt. Die Dokumentation empfiehlt sie ausdrücklich. Die Sitemap-Integration verlangt zusätzlich, dass der Wert mit http:// oder https:// beginnt.
// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://www.beispiel.ch',
trailingSlash: 'always',
integrations: [sitemap()],
});Astro.site liefert nach der API-Referenz eine URL aus diesem Wert, und undefined, wenn site fehlt. Astro.url ist in einem Build nur dann eine Adresse Ihrer Domain, wenn site gesetzt ist, sonst erhalten vorab gerenderte Seiten eine localhost-Adresse. Ein Build ohne site erzeugt also keine brauchbaren Adressen.
Zwei Einstellungen daneben entscheiden, ob die Adressen einheitlich sind. trailingSlash hat den Standard 'ignore', und dann treffen /leistungen und /leistungen/ dieselbe Route. Mit 'always' gibt es nur die Form mit Schrägstrich. build.format steht standardmässig auf 'directory' und baut /leistungen/index.html. Die Dokumentation empfiehlt, trailingSlash: 'always' mit directory zu kombinieren. Diese Entscheidung treffe ich am Anfang schriftlich mit Ihnen, weil sie in jeder Canonical-URL und jedem Sitemap-Eintrag steht. Wie die Auslieferung dazu passt, steht auf der Seite für Berlin.
Die Sitemap: was die Integration schreibt, was Google davon nutzt
npx astro add sitemap richtet die Integration ein. Im Build entstehen sitemap-index.xml und sitemap-0.xml. Die Optionen, die ich im Alltag brauche:
filtererhält jede Seiten-URL und gibttrueoderfalsezurück. Damit bleiben Danke-Seiten, Testseiten und Seiten mitnoindexdraussen.serialize()wird für jeden Eintrag aufgerufen und kann ihn ändern oder mitundefinedentfernen. Dort setze ich bei Bedarflastmod.i18nerwartetdefaultLocaleundlocales, jeweils mit einer Zuordnung wiefr: 'fr-CH'. Dann trägt die Sitemap die Sprachversionen.entryLimitliegt nach der Dokumentation bei 45000 Einträgen je Datei.
Bei changefreq und priority steht in der Astro-Dokumentation, dass Google beide ignoriert. Google selbst schreibt dasselbe und nutzt lastmod nur, wenn es durchgehend und nachprüfbar stimmt, zum Beispiel nach einer wesentlichen Änderung des Haupttextes. Eine geänderte Jahreszahl im Copyright-Hinweis zählt nicht. Ein pauschales Datum für alle Seiten beim Build wäre also falsch. Besser ist das Änderungsdatum aus dem Frontmatter des jeweiligen Textes, das über serialize() in die Sitemap kommt. Wie solche Felder in Collections liegen, zeige ich auf der Seite für Stuttgart.
Die Sitemap muss vollständige, absolute URLs nennen, die Obergrenze liegt bei 50 MB unkomprimiert oder 50000 URLs je Datei. Die Integration kann laut Dokumentation keine Einträge für dynamische Routen im SSR-Modus erzeugen. Bei einer rein statischen Seite spielt das keine Rolle, bei Seiten mit serverseitigem Rendering plane ich die Einträge anders.
Canonical und Meta-Tags in einer Layout-Komponente
Alles, was in den head gehört, schreibe ich einmal, in einer Komponente Seitenkopf.astro, die jedes Layout einbindet. So kann keine Seite einen Titel ohne Canonical liefern. Die Dokumentation zeigt für das Canonical diese Form: new URL(Astro.url.pathname, Astro.site).
---
const { titel, beschreibung, bild = '/og/standard.png' } = Astro.props;
const canonical = new URL(Astro.url.pathname, Astro.site);
const ogBild = new URL(bild, Astro.site);
---
<title>{titel}</title>
<meta name="description" content={beschreibung} />
<link rel="canonical" href={canonical} />
<meta property="og:title" content={titel} />
<meta property="og:type" content="website" />
<meta property="og:url" content={canonical} />
<meta property="og:image" content={ogBild} />
<meta property="og:image:alt" content={titel} />
<meta property="og:locale" content="fr_CH" />Ist site nicht gesetzt, wirft der URL-Konstruktor bei einem relativen Pfad einen Fehler. Der Build bricht ab, statt falsche Adressen auszuliefern, und das ist hier gewollt.
Aus der Google-Dokumentation zu doppelten URLs stammen drei Regeln, die in dieser Komponente stecken. Das rel="canonical" wird nur akzeptiert, wenn es im head steht. Google empfiehlt absolute statt relative Pfade. Auf der kanonischen Seite selbst gehört ein selbstreferenzierendes Canonical hin. Ein Fragment wie #kontakt gehört nicht hinein. Google nennt Canonical ein starkes Signal, keinen Befehl, und wählt notfalls selbst eine Adresse. Deshalb müssen Canonical, Sitemap und interne Links dieselbe Form nennen.
Die Open-Graph-Spezifikation verlangt vier Angaben: og:title, og:type, og:image und og:url. Empfohlen sind unter anderem og:description, og:site_name, die Bildmasse und og:image:alt. Für og:locale gilt das Format language_TERRITORY und der Standard en_US. Wer das Feld weglässt, meldet eine französischsprachige Seite also als amerikanisches Englisch. Wie das Feld bei einer Migration aus einem SEO-Plugin ankommt, steht auf der Seite zur SEO-Übernahme von Next.js nach Astro, die Plugin-Felder lasse ich hier weg.
Open-Graph-Bilder zur Build-Zeit
Ein Bild je Seite lässt sich zur Build-Zeit erzeugen. Die Endpunkt-Dokumentation beschreibt, wie: Eine Datei wie src/pages/og/[slug].png.ts mit getStaticPaths() baut pro Eintrag eine Datei, und GET gibt eine Response mit den Bytes zurück. Seit Astro 3.0 braucht es für Binärdateien keine Kodierungsangabe.
// src/pages/og/[slug].png.ts
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const seiten = await getCollection('seiten');
return seiten.map((s) => ({
params: { slug: s.id },
props: { titel: s.data.title },
}));
}
export async function GET({ props }) {
const png = await zeichneBild(props.titel); // Ihre Bildbibliothek
return new Response(png);
}zeichneBild ist ein Platzhalter. Welche Bibliothek das Bild zeichnet, hängt vom Projekt ab, und ich wähle sie erst nach dem Briefing. Die Schriften und das Logo kommen aus Ihrem Projektordner, ohne Aufruf an einen fremden Dienst. Das Layout des Bildes liefern Sie, ich setze es um. Bei Bildern mit viel Text prüfe ich im fertigen Build jede Datei einmal an, bevor etwas live geht.
Strukturierte Daten als JSON-LD
Google empfiehlt JSON-LD als die am leichtesten umzusetzende Form, akzeptiert daneben Microdata und RDFa. Die Regel, die ich zuerst nenne: Das Markup muss den sichtbaren Inhalt beschreiben. Informationen, die Besucher nicht sehen, gehören nicht hinein.
Für Organization empfiehlt Google, sie auf der Startseite oder einer Seite über das Unternehmen zu setzen, nicht auf jeder Seite. Pflichtfelder gibt es nicht. Genannt werden unter anderem name, url, logo, address, contactPoint und sameAs. Das Logo muss mindestens 112 mal 112 Pixel gross und crawlbar sein.
---
const organisation = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Beispiel SA',
url: Astro.site?.href,
logo: new URL('/logo.png', Astro.site).href,
};
---
<script is:inline type="application/ld+json" set:html={JSON.stringify(organisation)} />Der Wert kommt aus einem Objekt und wird mit JSON.stringify ausgegeben, damit kein Anführungszeichen von Hand maskiert werden muss. Nach dem Build prüfe ich die Seiten mit dem Rich Results Test von Google und lege fest, welche weiteren Typen Ihre Inhalte tragen, etwa BreadcrumbList für die Pfadnavigation.
robots.txt und RSS als Endpunkte
Die Datei muss nach Google robots.txt heissen, im Stammverzeichnis des Hosts liegen und als UTF-8 gespeichert sein. Jede Sitemap-Zeile braucht eine vollständige URL. Die Regeln gelten nur für Protokoll, Host und Port, auf dem die Datei liegt. Die Astro-Dokumentation nennt zwei Wege: eine feste Datei in public/ oder einen Endpunkt, der den Wert site nutzt.
// src/pages/robots.txt.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ site }) =>
new Response(
`User-agent: *\nAllow: /\n\nSitemap: ${new URL('sitemap-index.xml', site).href}\n`,
);Der Endpunkt hat einen Vorteil: Die Adresse der Sitemap wechselt mit site mit, und eine Testumgebung zeigt nicht auf die Sitemap der Live-Domain. Eine Sache bleibt: robots.txt hält nach Google eine Seite nicht aus dem Index. Eine gesperrte URL kann ohne Beschreibung trotzdem erscheinen. Wer eine Seite ausschliessen will, nimmt noindex oder einen Passwortschutz. Sperrt man dieselbe Seite zusätzlich in robots.txt, kann der Crawler das noindex nicht lesen.
Für RSS installiert man @astrojs/rss und legt src/pages/rss.xml.js an. Pflicht sind title, description, site und items, und site kommt aus context.site. Jeder Eintrag braucht title oder description, dazu kommen link und pubDate.
// src/pages/rss.xml.js
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const beitraege = await getCollection('blog');
return rss({
title: 'Neuigkeiten',
description: 'Neues aus dem Unternehmen',
site: context.site,
items: beitraege.map((b) => ({
title: b.data.title,
pubDate: b.data.pubDate,
description: b.data.description,
link: `/blog/${b.id}/`,
})),
});
}Damit Feed-Programme den Feed finden, gehört in den head ein link rel="alternate" type="application/rss+xml" mit href={new URL("rss.xml", Astro.site)}. Soll der volle Text im Feed stehen, empfiehlt die Dokumentation, ihn mit sanitize-html zu bereinigen.
Checkliste: was ich vor dem Start gegenprüfe
| Baustein | Prüfung im fertigen Build |
|---|---|
site | Gesetzt, mit https://, keine localhost-Adressen in der Ausgabe |
| Schrägstrich | Eine Form für Canonical, Sitemap und interne Links |
| Sitemap | Nur Seiten, die in den Index sollen, absolute URLs, lastmod aus echten Änderungen |
| Canonical | Im head, absolut, selbstreferenzierend, ohne Fragment |
| Open Graph | Die vier Pflichtangaben, og:locale, Bild erreichbar |
| JSON-LD | Beschreibt sichtbaren Inhalt, Rich Results Test ohne Fehler |
robots.txt | Im Stamm des Hosts, Sitemap mit vollständiger URL, kein Ersatz für noindex |
| RSS | Link im head, site gesetzt |
Gegen Auslieferungsfehler hilft die Gegenprobe auf der Live-Domain. Sicherheits-Header, die ebenfalls zur Auslieferung gehören, beschreibe ich auf der Seite für Frankfurt.
Datenschutz: was Art. 19 verlangt
Das revidierte Datenschutzgesetz (revDSG) gilt in der Fassung des Fedlex-Textes vom 1. September 2023. Nach Art. 19 Abs. 2 teilt der Verantwortliche bei der Beschaffung von Personendaten mindestens mit: Identität und Kontaktdaten, Bearbeitungszweck und gegebenenfalls die Empfänger. Das betrifft Ihre Seite dort, wo Daten ankommen, etwa im Kontaktformular oder in einer Statistik. Für Private wie Behörden des Bundes ist der EDÖB (Eidgenössischer Datenschutz- und Öffentlichkeitsbeauftragter) die Aufsichtsstelle. Ich halte im Umfang fest, welche Komponenten Daten erfassen. Ob das rechtlich genügt, beurteilt Ihre Rechtsberatung.
Ablauf eines SEO-Projekts in Astro
- Schriftliches Briefing. Sie schicken mir die Adresse Ihrer Website, Ihr Ziel und die Sprachen.
- Rückfragen schriftlich. Welche Seiten sollen in den Index, wer pflegt die Texte, wo liegen Logo und Schriften?
- Umfang und Annahmen schriftlich.
site, Schrägstrich-Regel, Sitemap-Filter, Felder im Seitenkopf, OG-Bilder, Typen für JSON-LD, Feed. - Testumgebung zur Abnahme. Sie sehen Seitenkopf, Sitemap und Bilder an Ihren eigenen Seiten, bevor etwas live geht.
- Wartung als Option. Ich spiele Updates zuerst in der Testumgebung ein. Ein Stundenkontingent gilt für den jeweiligen Monat und wird nicht übertragen.
Ein Entwurf für Seitenkopf oder Bildvorlage entsteht bei Ihnen, ich setze ihn im Build um. Wo welches Element steht, tragen Sie in eine Tabellenvorlage ein, die ich Ihnen vorher schicke.
Häufige Fragen zur technischen SEO in Astro
Reicht das Sitemap-Plugin, damit Google meine Seiten findet?
Nein. Die Sitemap meldet nur, welche URLs es gibt. Google nutzt sie als einen von mehreren Wegen, und nach eigener Dokumentation sind Weiterleitungen und Canonical stärkere Signale. Ich prüfe deshalb, dass Sitemap, Canonical und interne Links dieselben Adressen nennen.
Muss ich priority und changefreq pflegen?
Nein. Die Dokumentation von Astro vermerkt, dass Google beide Felder ignoriert, und Google schreibt dasselbe. lastmod lohnt sich nur, wenn es nachprüfbar stimmt, etwa aus dem Änderungsdatum eines Textes.
Kann robots.txt eine Seite aus Google heraushalten?
Nein. Nach Google ist robots.txt dafür kein Mittel, eine gesperrte URL kann ohne Beschreibung trotzdem erscheinen. Für Seiten, die nicht in den Index sollen, setze ich noindex und lasse sie crawlbar.
Muss jede Seite strukturierte Daten tragen?
Nein. Google empfiehlt Organization auf der Startseite oder einer Seite über das Unternehmen. Markup gehört nur dorthin, wo der sichtbare Inhalt es trägt. Ich lege die Typen mit Ihnen schriftlich fest.
Was ändert sich bei der Datenschutzerklärung?
Wer Analysewerkzeuge oder Formulare einsetzt, informiert nach Art. 19 des Datenschutzgesetzes über Identität, Zweck und Empfänger. Ob das rechtlich genügt, beurteilt Ihre Rechtsberatung.
Kommen Sie für das Projekt nach Genf?
Nein. Ich sitze in Gdynia und arbeite nur schriftlich. Sie schicken ein Briefing und beantworten Rückfragen, danach folgen der schriftliche Umfang und eine Testumgebung zur Abnahme. Telefonate und Videotermine biete ich nicht an. Die erste schriftliche Einschätzung ist für Sie kostenlos.
Schreiben Sie mir
Schicken Sie mir über das Kontaktformular die Adresse Ihrer Website, Ihr Ziel, Ihren Termin und den aktuellen Stack, am besten mit der Angabe, in welchen Sprachen Sie veröffentlichen und welche Seiten in den Index sollen. Ich lese Ihre Angaben, stelle Rückfragen in Textform und schicke Ihnen eine erste schriftliche Einschätzung. Dafür berechne ich nichts. Passt für Ihr Vorhaben eine andere Lösung besser, schreibe ich das gleich dazu.
Ausgewählte Projekte
Beispiele aus meiner Arbeit.
surfuje.pl - WordPress Projekt | WPPoland
surfuje.pl ist eine Website für Surfer und Wassersportinteressierte, mit klaren Inhalten, einfacher Veröffentlichung und stabilem Betrieb.
Tech Platform: car-mechanic-huntington.co.uk
car-mechanic-huntington.co.uk ist eine WordPress-Website für eine lokale Kfz-Werkstatt, mit klarem Leistungsangebot, Kontaktwegen und technischer Wartung.
Tech Platform: fermentum-mobile.pl
Die Website fermentum-mobile.pl ist eine dedizierte Plattform, die für Fermentationsliebhaber entwickelt wurde, die die Geheimnisse traditioneller Verarbeitu...
WordPress Support & Entwicklung in Geneva
Brauchen Sie die Leistung: Astro-Entwickler in Geneva?
Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.
Projekt beschreibenWeitere WordPress-Dienste und Wissensbasis entdecken
Migration zu Astro, Next.js und Headless WordPress.
WooCommerce-Synchronisierung mit ERP und Großhandel.
Geschäftsprozessautomatisierung rund um WordPress und Firmensysteme.
Bibliothek konkreter Automatisierungsfälle.
Headless WordPress, Sanity, Strapi und Contentful mit Astro oder Next.js.
Astro, MDX, Edge Delivery und an echtem Traffic gemessene Core Web Vitals.
Individuelle WordPress-Entwicklung und Architektur.
Skalierbare Headless-, ERP- und KI-Architektur für Enterprise.
Verwandte Kategorien
Unterstützende Artikel

Sechs bis sechzehn Wochen für typische Projekte, in vier Phasen: Analyse, Scoping, Build und Umstellung, Tuning. Die Variablen sind Katalogumfang, Anzahl der Integrationen, URL-Erhalt und die Bereitschaft des Redaktionsteams, nicht die Wahl des Frameworks.

Umfassende 4-Jahres-TCO-Analyse (Total Cost of Ownership), reale Core-Web-Vitals-Benchmarks, Astro 7 GraphQL APQ-Architektur und eine 10-Punkte-Entscheidungsmatrix für Enterprise-Entscheider zwischen entkoppeltem und traditionellem WordPress.

Die Entscheidung Shopify Plus vs WooCommerce headless im Jahr 2026 ist kein binärer "Plattform vs Custom"-Kompromiss mehr. Beide laufen headless, beide integrieren KI, beide liefern am Edge aus. Die echten Achsen sind Kontrolle, Gesamtkosten über fünf Jahre und Exit-Strategie. Dieser Artikel durchläuft die Entscheidungsmatrix mit bestätigten Plattformfakten.