Prompt-to-PR : Ajouter un sitemap et un robots.txt
Procédure standard pour ajouter un sitemap XML dynamique et un robots.txt à un projet Next.js ou Astro — format lastmod correct, priorité et règles d'exploration pour le SEO en production.
CursorClaude CodeCodexWindsurf Next.jsAstroTypeScript
Les sitemaps et robots.txt sont les premières primitives SEO qu’un agent manipule, et elles sont souvent erronées — mauvais format lastmod, directive Sitemap: manquante dans robots, ou pages bloquées incluses par inadvertance. Ce guide les corrige.
1. Exigence
Produire un sitemap XML couvrant toutes les routes publiques (contenu statique + dynamique depuis la base de données) et un robots.txt qui bloque les chemins admin/API et référence le sitemap. Fonctionne à la fois avec Next.js App Router et Astro ; choisissez l’approche correcte pour votre framework.
2. Premier prompt
Add a sitemap.xml and robots.txt to this project. Use the correct approachfor the framework detected below.
### If Next.js 14+:1. Create `src/app/sitemap.ts` using the Next.js `MetadataRoute.Sitemap` return type. Include: - All static routes: /, /pricing, /blog, /about (hardcoded is fine). - All dynamic blog posts: fetch slugs from the DB using the existing query helper, return lastModified from the post's updatedAt field. - Use `process.env.NEXT_PUBLIC_APP_URL` as the base URL. - Correct W3C datetime format for lastModified (ISO 8601).2. Create `src/app/robots.ts` using MetadataRoute.Robots. - Allow: all routes. - Disallow: /admin, /api, /dashboard. - Add `sitemap: process.env.NEXT_PUBLIC_APP_URL + "/sitemap.xml"`.
### If Astro:1. Add `@astrojs/sitemap` integration. In astro.config.ts, add `sitemap({ filter: (page) => !page.includes("/admin") })` and set `site: process.env.SITE_URL`.2. Create `public/robots.txt`: User-agent: * Disallow: /admin Disallow: /api Sitemap: <SITE_URL>/sitemap-index.xml
Do not create a custom sitemap endpoint if the integration handles it.Do not block / or any public content pages.3. Modifications de fichiers attendues
### Next.jssrc/app/sitemap.ts (new — dynamic MetadataRoute.Sitemap)src/app/robots.ts (new — MetadataRoute.Robots)
### Astroastro.config.ts (add sitemap integration + filter)public/robots.txt (new).env.example (SITE_URL added if missing)4. Liste de vérification
- L’URL de base provient d’une variable d’environnement — pas codée en dur comme
http://localhost:3000. lastModifiedest un objet JavaScriptDate(Next.js le convertit en ISO 8601) ou déjà une chaîne ISO valide — pas"undefined"ou absent./admin,/apiet/dashboardsont dans la liste Disallow.- La directive
Sitemap:dansrobots.txtutilise une URL absolue. - Les routes dynamiques (articles de blog) sont incluses via une requête DB, pas seulement les routes statiques.
- Le sitemap n’inclut pas les pages 404, de redirection ou noindex.
bun run buildpuiscurl /sitemap.xmlretourne un XML valide (vérifier avecxmllint).
5. Commandes de test
bun run build && bun run start# or for Astro:bun run build && bun run preview
# Validate sitemap XMLcurl -s http://localhost:3000/sitemap.xml | xmllint --format - | head -40
# Confirm robots.txtcurl http://localhost:3000/robots.txt
# Confirm admin is disallowed and sitemap directive is presentgrep -E "Disallow|Sitemap" <(curl -s http://localhost:3000/robots.txt)
# Google Rich Results / URL Inspection simulationcurl -A "Googlebot" http://localhost:3000/sitemap.xml -I6. Échecs courants
lastModifiedest"undefined"— le champupdatedAtdu post est nul. Sécurisation :lastModified: post.updatedAt ?? post.createdAt ?? new Date().- Le sitemap retourne 404 —
src/app/sitemap.tsest manquant ou placé en dehors du répertoireapp. - Toutes les routes interdites — l’agent ajoute
Disallow: /par erreur. Confirmez que seuls les chemins admin/API sont bloqués. - La directive
Sitemap:a une URL relative — Google l’ignore. Doit être absolue :https://example.com/sitemap.xml. - Sitemap statique uniquement — l’agent code en dur les slugs de blog au lieu d’interroger la DB. Confirmez que la fonction sitemap est
asyncet récupère des données réelles.
7. Prompt de correction
The sitemap.xml at /sitemap.xml includes every blog post withlastModified "undefined" (rendered as the string).
Fix in src/app/sitemap.ts: const posts = await getBlogPosts(); return posts.map((post) => ({ url: `${BASE_URL}/blog/${post.slug}`, lastModified: post.updatedAt ?? post.createdAt ?? new Date(), changeFrequency: "weekly", priority: 0.8, }));
Ensure getBlogPosts() returns rows that include updatedAt and createdAt.8. Description de la PR
## SEO: Add dynamic sitemap.xml and robots.txt
**Next.js**: `src/app/sitemap.ts` + `src/app/robots.ts` using built-in`MetadataRoute` types. Sitemap includes static routes + all published blogposts with correct `lastModified` timestamps from the DB.
**robots.txt** disallows `/admin`, `/api`, `/dashboard`; includes absolute`Sitemap:` directive pointing to the generated `/sitemap.xml`.
Base URL read from `NEXT_PUBLIC_APP_URL` — no localhost URLs in production.