# 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.

> Pagina: https://ui.eneawork.it/blog/nextjs-sitemap-robot-generati
> Markdown: https://ui.eneawork.it/blog/nextjs-sitemap-robot-generati.md

*2026-11-01*

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

Il catalogo EneUI indicizza 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie: numeri misurati il 1 novembre 2026 su /api/stats. Le sitemap del sito contengono 13.096 URL in 12 file, contati il 1 novembre 2026 su data/cache: sitemap-icons.xml ne ha 5.000, sitemap-components-1.xml 2.000 per il tetto SEO, sitemap-blog.xml 798.

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.

## FAQ

### 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.
