Next.js
Beginner
1 min read
Sitemap, Robots.txt, and Open Graph Images
Example
// app/sitemap.ts
import type { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://acme.com';
// Fetch dynamic routes from your data source
const posts = await fetch(`${baseUrl}/api/posts?fields=slug,updatedAt`)
.then((r) => r.json());
const postEntries: MetadataRoute.Sitemap = posts.map(
(post: { slug: string; updatedAt: string }) => ({
url: `${baseUrl}/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly',
priority: 0.8,
}),
);
return [
{ url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1 },
{ url: `${baseUrl}/about`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.5 },
...postEntries,
];
}
// app/robots.ts
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: '*', allow: '/', disallow: ['/dashboard/', '/api/'] },
],
sitemap: 'https://acme.com/sitemap.xml',
};
}
// app/blog/[slug]/opengraph-image.tsx — dynamic OG image
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';
export default async function OgImage({ params }: { params: { slug: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.slug}`)
.then((r) => r.json());
return new ImageResponse(
<div style={{ display: 'flex', background: '#0f172a', width: '100%', height: '100%', padding: 60 }}>
<h1 style={{ color: 'white', fontSize: 60 }}>{post.title}</h1>
</div>,
size,
);
}