{
  "id": "ai-ignores-seo-metadata",
  "type": "failures",
  "category": "failures",
  "locale": "de",
  "url": "/de/failures/ai-ignores-seo-metadata",
  "title": "So beheben Sie, dass KI SEO-Metadaten ignoriert",
  "description": "KI-Agenten erstellen Next.js- und Astro-Seiten ohne Titel-Tags, Open-Graph-Metadaten oder kanonische URLs und liefern Seiten aus, die für Suchmaschinen und Social Crawler unsichtbar sind.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "Astro",
    "TypeScript"
  ],
  "tags": [
    "seo",
    "nextjs",
    "astro"
  ],
  "difficulty": null,
  "updated": "2026-06-08",
  "markdown": "Der Agent erstellt Seitenkomponenten ohne `Metadata`-Export, ohne `title`-Tag und ohne Open-Graph-Tags, was zu Seiten führt, die schlecht ranken und sich schlecht in sozialen Medien teilen lassen.\n\n## Das Symptom\n\nEine Next.js App Router-Seite wird ohne Metadata-Export erstellt, sodass der Tab-Titel leer bleibt und der `head` außer den Next.js-Standardwerten leer ist.\n\n```tsx\n// app/blog/[slug]/page.tsx — WRONG\nexport default async function BlogPost({ params }: { params: { slug: string } }) {\n  const post = await getPost(params.slug);\n  return (\n    <article>\n      <h1>{post.title}</h1>\n      <div dangerouslySetInnerHTML={{ __html: post.html }} />\n    </article>\n  );\n  // No <title>, no meta description, no og:image, no canonical URL\n}\n```\n\nGoogle sieht: `Unbenanntes Dokument`. Twitter/LinkedIn zeigen eine leere Karte.\n\n## Warum es passiert\n\nDer Agent konzentriert sich auf die sichtbare Benutzeroberfläche – Datenabruf und Rendering – und behandelt `head`-Metadaten als nachträglichen Einfall. SEO ist während der lokalen Entwicklung unsichtbar und erzeugt keinen Laufzeitfehler, sodass der Agent nie Rückmeldung erhält, dass es fehlt.\n\n## Wie man es erkennt\n\n- Kein `export const metadata` oder `export async function generateMetadata` in App Router-Seitendateien.\n- Kein `Astro.props` oder Frontmatter-gesteuertes `title` / `description` in Astro-Layouts.\n- Lighthouse SEO-Score unter 90 auf einer neuen Seite.\n- `curl -s http://localhost:3000/blog/my-post | grep \"<title>\"` gibt nichts oder einen generischen Seitentitel zurück.\n- `og:image` fehlt im `head` (Social Preview zeigt eine leere Karte).\n\n## So beheben Sie es\n\nExportieren Sie `generateMetadata` für dynamische Seiten und fügen Sie alle erforderlichen Tags hinzu.\n\n```tsx\n// app/blog/[slug]/page.tsx — CORRECT\nimport type { Metadata } from \"next\";\n\nexport async function generateMetadata({\n  params,\n}: {\n  params: { slug: string };\n}): Promise<Metadata> {\n  const post = await getPost(params.slug);\n  return {\n    title: post.title,\n    description: post.excerpt,\n    alternates: { canonical: `https://example.com/blog/${params.slug}` },\n    openGraph: {\n      title: post.title,\n      description: post.excerpt,\n      url: `https://example.com/blog/${params.slug}`,\n      images: [{ url: post.ogImage, width: 1200, height: 630, alt: post.title }],\n      type: \"article\",\n      publishedTime: post.publishedAt,\n    },\n    twitter: {\n      card: \"summary_large_image\",\n      title: post.title,\n      description: post.excerpt,\n      images: [post.ogImage],\n    },\n  };\n}\n\nexport default async function BlogPost({ params }: { params: { slug: string } }) {\n  const post = await getPost(params.slug);\n  return (\n    <article>\n      <h1>{post.title}</h1>\n      <div dangerouslySetInnerHTML={{ __html: post.html }} />\n    </article>\n  );\n}\n```\n\nFür Astro übergeben Sie Metadaten über das Layout:\n\n```astro\n---\n// src/pages/blog/[slug].astro\nconst { post } = Astro.props;\n---\n<Layout\n  title={post.title}\n  description={post.excerpt}\n  ogImage={post.ogImage}\n  canonical={`https://example.com/blog/${post.slug}`}\n>\n  <article>\n    <h1>{post.title}</h1>\n    <post.Content />\n  </article>\n</Layout>\n```\n\n```txt\n[ ] Every page exports generateMetadata (Next.js) or passes title+description to layout (Astro)\n[ ] title is unique per page — not just the site name\n[ ] description is 120-160 characters and describes the page content\n[ ] og:title, og:description, og:image (1200x630), og:url are all set\n[ ] twitter:card is \"summary_large_image\" for pages with images\n[ ] canonical URL is set to the preferred URL (no trailing slash ambiguity)\n[ ] robots meta is not accidentally set to \"noindex\"\n[ ] Verify with: curl -s <url> | grep -E \"<title>|og:title|description\"\n```\n\n## Korrektur-Prompt\n\n```txt title=\"Fix Prompt\"\nThis page component is missing all SEO metadata. Add an async generateMetadata\nexport (Next.js App Router) that returns title, description, canonical URL, full\nopenGraph object (title, description, url, images with 1200x630 dimensions, type),\nand twitter card metadata. Derive values from the page's data fetch — do not use\nplaceholder strings. Also confirm that no parent layout accidentally sets\nrobots: noindex.\n```\n\n## Test\n\n```bash\n# Check that <title> and og:title appear in the server-rendered HTML\ncurl -s http://localhost:3000/blog/my-post \\\n  | grep -E '<title>|og:title|og:description|og:image|canonical' \\\n  | grep -v \"node_modules\" \\\n  && echo \"Metadata present\" || echo \"FAIL: metadata missing\"\n```"
}