{
  "id": "build-a-static-seo-site-with-astro",
  "type": "playbooks",
  "category": "playbooks",
  "locale": "fr",
  "url": "/fr/playbooks/build-a-static-seo-site-with-astro",
  "title": "Prompt-to-PR : Créer un site statique SEO avec Astro",
  "description": "SOP complète pour générer un site statique SEO piloté par le contenu avec Astro, Tailwind, collections de contenu MDX, sitemap et balises canoniques à partir de zéro.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Astro",
    "TypeScript",
    "Tailwind"
  ],
  "tags": [
    "astro",
    "seo",
    "tailwind",
    "typescript",
    "search"
  ],
  "difficulty": "medium",
  "updated": "2026-06-08",
  "markdown": "Créez un site Astro 5 entièrement statique prêt pour la production, optimisé pour la recherche organique : collections de contenu, typographie Tailwind, `@astrojs/sitemap` et métadonnées `<head>` correctes intégrées dès le départ.\n\n## 1. Exigence\n\nCréez un site statique de marketing/contenu qui obtient un score de 100 sur Lighthouse SEO et Accessibilité. Le contenu est rédigé dans des fichiers MDX gérés par les collections de contenu Astro. Aucun framework JavaScript nécessaire — la sortie est du HTML+CSS pur avec des îlots optionnels.\n\n## 2. Premier 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. Modifications de fichiers attendues\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. Liste de vérification\n\n- `astro.config.ts` définit `site` — nécessaire pour que `@astrojs/sitemap` émette des URLs absolues.\n- `BaseLayout.astro` produit une balise `<link rel=\"canonical\">` en utilisant `Astro.url.href`.\n- La page de liste du blog utilise `Astro.props.page.data` de `paginate()` — pas un appel brut à `getCollection()`.\n- Les brouillons (`draft: true`) sont exclus en production via la garde `import.meta.env.PROD`.\n- `<html lang=\"en\">` est défini sur l'élément racine.\n- `tailwind.config.ts` inclut le plugin `typography` et cible `src/**/*.{astro,mdx}`.\n- L'intégration `sitemap()` est présente — vérifiez que `dist/sitemap-index.xml` existe après `bun run build`.\n\n## 5. Commandes de test\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. Échecs courants\n\n- **Le sitemap génère des URLs relatives** — `site` manquant dans `astro.config.ts`. Ajoutez-le.\n- **`getCollection` retourne les brouillons en production** — filtrez : `posts.filter(p => !p.data.draft || !import.meta.env.PROD)`.\n- **Pagination 404 sur `/blog`** — la première page doit être `/blog/` (index), pas `/blog/1`. Astro's `paginate()` produit `/blog/`, `/blog/2/`, etc. par défaut.\n- **Contenu MDX non stylisé** — la classe `prose` de `@tailwindcss/typography` manque sur le wrapper d'article dans `[slug].astro`.\n- **Les balises OG utilisent un chemin d'image relatif** — doit être une URL absolue. Préfixez avec `Astro.site`.\n\n## 7. Prompt de correction\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. Description de la PR\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```"
}