Next.js 55: sitemap.ts & robots.ts
easy⏱ 5 mincoursenextjs
Special files, generated output
Both files live at the root of app/ and are picked up automatically — visiting /sitemap.xml or /robots.txt in production serves whatever your functions return, converted to the right format. Because it is just a function, you can await a database query for every blog post or product before building the URL list.
// app/sitemap.ts
export default async function sitemap() {
const posts = await getAllPosts();
return [
{ url: "https://example.com", lastModified: new Date() },
...posts.map((p) => ({
url: "https://example.com/blog/" + p.slug,
lastModified: p.updatedAt,
})),
];
}
// app/robots.ts
export default function robots() {
return {
rules: { userAgent: "*", allow: "/", disallow: "/admin" },
sitemap: "https://example.com/sitemap.xml",
};
}
Add a post to the sitemap
A third post, app-router-deep-dive, has already been pushed onto the POSTS array — confirm the generated urlset below has a matching url entry for it. Then push a post of your own (any slug and updatedAt work) and watch the sitemap grow again.
Keep them in sync automatically
Because sitemap.ts reads from the same data source as your pages, a new blog post that appears in your CMS shows up in the sitemap on the very next build — no separate step to remember, and no stale URLs pointing at deleted pages.