{
  "id": "build-a-static-seo-site-with-astro",
  "type": "playbooks",
  "category": "playbooks",
  "locale": "de",
  "url": "/de/playbooks/build-a-static-seo-site-with-astro",
  "title": "Prompt-to-PR: Erstellen einer statischen SEO-Website mit Astro",
  "description": "Vollständige SOP für das Aufsetzen einer inhaltsgesteuerten statischen SEO-Website mit Astro, Tailwind, MDX-Content-Collections, Sitemap und kanonischen Tags von Grund auf.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Astro",
    "TypeScript",
    "Tailwind"
  ],
  "tags": [
    "astro",
    "seo",
    "tailwind",
    "typescript",
    "search"
  ],
  "difficulty": "medium",
  "updated": "2026-06-08",
  "markdown": "Erstellen Sie eine produktionsreife, vollständig statische Astro-5-Website, die für die organische Suche optimiert ist: Content-Collections, Tailwind-Typografie, `@astrojs/sitemap` und korrekte `<head>`-Metadaten von Anfang an.\n\n## 1. Anforderung\n\nErstellen Sie eine statische Marketing-/Content-Website, die bei Lighthouse SEO und Barrierefreiheit 100 Punkte erreicht. Die Inhalte werden in MDX-Dateien verfasst, die von Astro-Content-Collections verwaltet werden. Kein JavaScript-Framework erforderlich – die Ausgabe ist reines HTML+CSS mit opt-in Islands.\n\n## 2. Erster Prompt\n\n```txt title=\"First Prompt\"\nScaffold a new Astro 5 static SEO site from scratch in the current directory.\n\nRequirements:\n1. Init with: `bunx create astro@latest . --template minimal --typescript strict --no-git`\n2. Add integrations:\n   - `@astrojs/tailwind` with `@tailwindcss/typography`\n   - `@astrojs/sitemap`\n   - `@astrojs/mdx`\n3. Create a content collection `blog` in `src/content/blog/` with this Zod schema:\n   title, description, pubDate (Date), updatedDate (Date, optional),\n   author (string, default \"Admin\"), tags (string[], default []), draft (bool, default false).\n4. Create a BaseLayout.astro with:\n   - A `<head>` block: charset, viewport, canonical (`Astro.url.href`),\n     og:title, og:description, og:url, og:type, twitter:card.\n   - Accept `title`, `description`, `image` props.\n5. Create pages:\n   - `/` — hero + last 6 non-draft posts\n   - `/blog` — paginated list (10 per page) using `paginate()`\n   - `/blog/[slug]` — single post rendered with `<Content />`\n   - `/tags/[tag]` — posts filtered by tag\n6. Create `src/content/blog/hello-world.mdx` as a real sample post.\n7. Configure `astro.config.ts`:\n   - `site: process.env.SITE_URL ?? \"http://localhost:4321\"`\n   - `integrations: [tailwind(), sitemap(), mdx()]`\n   - `output: \"static\"`\n8. Add a `.env.example` with `SITE_URL=https://example.com`.\n```\n\n## 3. Erwartete Dateiänderungen\n\n```txt\nastro.config.ts\ntailwind.config.ts\nsrc/content.config.ts                    (blog collection schema)\nsrc/layouts/BaseLayout.astro             (head + canonical + OG tags)\nsrc/pages/index.astro\nsrc/pages/blog/index.astro               (paginated)\nsrc/pages/blog/[slug].astro\nsrc/pages/tags/[tag].astro\nsrc/content/blog/hello-world.mdx\n.env.example\npackage.json                             (updated with all integrations)\n```\n\n## 4. Checkliste zur Überprüfung\n\n- `astro.config.ts` setzt `site` — erforderlich, damit `@astrojs/sitemap` absolute URLs ausgibt.\n- `BaseLayout.astro` gibt ein `<link rel=\"canonical\">` unter Verwendung von `Astro.url.href` aus.\n- Die Blog-Listenseite verwendet `Astro.props.page.data` von `paginate()` — keinen direkten `getCollection()`-Aufruf.\n- Entwurfsposts (`draft: true`) werden in der Produktion durch `import.meta.env.PROD`-Guard ausgeschlossen.\n- `<html lang=\"en\">` wird auf dem Root-Element gesetzt.\n- `tailwind.config.ts` enthält das `typography`-Plugin und zielt auf `src/**/*.{astro,mdx}` ab.\n- Die `sitemap()`-Integration ist vorhanden — überprüfen Sie, ob `dist/sitemap-index.xml` nach `bun run build` existiert.\n\n## 5. Testbefehle\n\n```bash\nbun install\nbun run dev\n# visit http://localhost:4321 and confirm hero + posts render\n\nbun run build\n# expect zero errors\n\nbun run preview\n# check /sitemap-index.xml and /sitemap-0.xml exist\n# check /blog and /blog/hello-world render with correct <title> and canonical\n\n# Lighthouse CLI smoke test (optional)\nbunx lighthouse http://localhost:4321 --output json --quiet | jq '.categories.seo.score'\n# expect 1 (100%)\n```\n\n## 6. Häufige Fehler\n\n- **Sitemap generiert relative URLs** — `site` fehlt in `astro.config.ts`. Fügen Sie es hinzu.\n- **`getCollection` gibt Entwürfe in der Produktion zurück** — Filter: `posts.filter(p => !p.data.draft || !import.meta.env.PROD)`.\n- **Pagination 404 bei `/blog`** — die erste Seite muss `/blog/` (Index) sein, nicht `/blog/1`. Astros `paginate()` gibt standardmäßig `/blog/`, `/blog/2/` usw. aus.\n- **MDX-Inhalte nicht gestaltet** — `@tailwindcss/typography` `prose`-Klasse fehlt auf dem Artikel-Wrapper in `[slug].astro`.\n- **OG-Tags verwenden relativen Bildpfad** — muss eine absolute URL sein. Voranstellen mit `Astro.site`.\n\n## 7. Korrektur-Prompt\n\n```txt title=\"Fix Prompt\"\nThe sitemap at /sitemap-0.xml contains relative paths like \"/blog/hello-world\"\ninstead of absolute URLs like \"https://example.com/blog/hello-world\".\n\nFix: add `site: \"https://example.com\"` (or `process.env.SITE_URL`) to the\ntop-level astro.config.ts object. The sitemap integration reads this value\nto prefix all URLs.\n```\n\n## 8. PR-Beschreibung\n\n```md title=\"PR description\"\n## Init: Static Astro 5 SEO site\n\n- Astro 5 + TypeScript strict + Tailwind (with `@tailwindcss/typography`)\n- `@astrojs/sitemap` and `@astrojs/mdx` integrations\n- Content collection `blog` with Zod schema (title, description, pubDate, tags, draft)\n- BaseLayout with canonical, OG, and Twitter Card meta tags\n- Pages: home, paginated blog list, single post, tag archive\n- Sample `hello-world.mdx` post\n- `bun run build` emits `sitemap-index.xml` and all static pages\n```"
}