React
sitemap.ts e robots.ts generati
Due file TypeScript producono /sitemap.xml e /robots.txt dallo stesso codice delle rotte. Tipi, hreflang, il tetto di 50.000 URL e il file statico.
In sintesi
- app/sitemap.ts e app/robots.ts sono rotte: producono /sitemap.xml e /robots.txt.
- Il tipo MetadataRoute impone la forma, non valida gli URL.
- Oltre 50.000 URL per file serve generateSitemaps.
- Un public/robots.txt convive male con app/robots.ts: tieni una fonte sola.
Due file TypeScript generano gli artefatti che i crawler leggono: app/sitemap.ts produce /sitemap.xml e app/robots.ts produce /robots.txt. Sono rotte come le altre, con gli stessi limiti di caching.
La sitemap
// app/sitemap.ts
import type { MetadataRoute } from "next";
const BASE = "https://ui.eneawork.it";
const PAGES = ["", "/pricing", "/blog"];
export default function sitemap(): MetadataRoute.Sitemap {
return PAGES.map((path) => ({
url: `${BASE}${path}`,
lastModified: new Date(),
changeFrequency: "weekly" as const,
priority: path === "" ? 1 : 0.7,
alternates: {
languages: { it: `${BASE}/it${path}`, en: `${BASE}/en${path}` },
},
}));
}
Il tipo MetadataRoute.Sitemap accetta url, lastModified, changeFrequency, priority e alternates.languages. Il campo alternates scrive gli xhtml:link per hreflang: senza, la sitemap resta valida ma non dice nulla sulle traduzioni.
Il robots
// app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: [{ userAgent: "*", allow: "/", disallow: ["/api/", "/admin/"] }],
sitemap: "https://ui.eneawork.it/sitemap.xml",
host: "https://ui.eneawork.it",
};
}
Il tetto dei 50.000
Un file di sitemap regge al massimo 50.000 URL e 50 MB non compressi. Oltre quella soglia si usa generateSitemaps, che restituisce un array di id e lascia a te generare un file per id.
// app/sitemap.ts
export async function generateSitemaps() {
return [{ id: 0 }, { id: 1 }, { id: 2 }];
}
export default async function sitemap({ id }: { id: number }) {
const rows = await loadUrls();
return rows.slice(id * 50000, id * 50000 + 50000);
}
Statico o dinamico
| File | Rotta | Quando è statico |
|---|---|---|
app/sitemap.ts | /sitemap.xml | Se non legge cookie, header o query |
app/robots.ts | /robots.txt | Quasi sempre |
public/sitemap.xml | /sitemap.xml | Sempre, ma va rimosso se esiste app/sitemap.ts |
Le rotte che finiscono in sitemap sono pagine: blocchi blog, paginazione e breadcrumb coprono l'archivio senza inventare URL.
Indice o file unico è in sitemap index vs file unico; l'invio a Google in Search Console e indicizzazione; i link interni in strategia di link interni. Confronto: Next.js vs Vite per un sito marketing.
curl -s http://localhost:3000/sitemap.xml
Limite noto: la sitemap dichiara URL, non li verifica. Una page.tsx rimossa senza togliere la voce produce un 404 che Search Console segnala; il controllo va messo in CI, non fatto a occhio.
Domande frequenti
sitemap.ts e robots.ts sono statici o dinamici?
Dipende dal codice. Se non leggono cookie, header o query, Next.js li genera una volta in build; se leggono dati dinamici vengono eseguiti a ogni richiesta.
Posso superare i 50.000 URL?
Sì, con generateSitemaps: restituisci un array di id e Next.js espone un file per id, ognuno sotto il tetto.
Dove dichiaro le lingue nella sitemap?
Nel campo alternates.languages di ogni voce. Diventa un blocco xhtml:link con hreflang per ogni lingua.
Meglio public/robots.txt o app/robots.ts?
app/robots.ts, se vuoi che i valori vengano dal codice. Il file statico va bene solo se non cambia mai, e non deve convivere con la rotta.
La sitemap aiuta il ranking?
No, aiuta la scoperta. Serve a far trovare URL nuovi o profondi; la posizione dipende da contenuto, link e qualità della pagina.