Sitemap Generation
Automatically generate sitemap.xml from your Trident content.
Next.js App Router
Use the built-in Next.js sitemap convention with our helper:
// app/sitemap.ts
import { trident } from "@/lib/trident";
import { generateSitemapEntries } from "@trident/client/nextjs";
export default async function sitemap() {
const entries = await trident.getSitemap();
// Generate entries with your base URL
const articleEntries = generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/blog/:slug", // Default: "/blog/:slug"
});
// Add your static pages
const staticPages = [
{ url: "https://yourdomain.com", lastModified: new Date() },
{ url: "https://yourdomain.com/about", lastModified: new Date() },
{ url: "https://yourdomain.com/contact", lastModified: new Date() },
];
return [...staticPages, ...articleEntries];
}
// Revalidate every hour
export const revalidate = 3600;Custom URL Patterns
Customize the URL pattern for your articles:
// Different URL patterns
generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/blog/:slug", // /blog/my-article
});
generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/articles/:slug", // /articles/my-article
});
generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/:productSlug/:slug", // /my-product/my-article
});
generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/:languageCode/blog/:slug", // /en/blog/my-article
});Available placeholders
| Placeholder | Value |
|---|---|
| :slug | Article slug |
| :productSlug | Product slug |
| :languageCode | Language code (e.g., "en") |
| :territoryCode | Territory code (e.g., "US") |
XML Route Handler
For more control, use the route handler factory to serve sitemap.xml directly:
// app/sitemap.xml/route.ts
import { trident } from "@/lib/trident";
import { createSitemapRouteHandler } from "@trident/client/nextjs";
export const { GET } = createSitemapRouteHandler({
client: trident,
baseUrl: "https://yourdomain.com",
urlPattern: "/blog/:slug",
// Optional: add static entries
staticEntries: [
{ loc: "https://yourdomain.com", lastmod: new Date().toISOString() },
{ loc: "https://yourdomain.com/about", lastmod: new Date().toISOString() },
],
});
// Revalidate every hour
export const revalidate = 3600;Sitemap Index Entries
Build sitemap index entries when you split large sitemaps:
import {
buildSitemapIndexEntries,
generateSitemapIndexXml,
} from "@trident/client/nextjs";
const indexEntries = buildSitemapIndexEntries(entries, {
baseUrl: "https://yourdomain.com",
maxUrlsPerSitemap: 50000,
});
const xml = generateSitemapIndexXml(indexEntries);Generate XML Manually
For non-Next.js frameworks, generate XML manually:
import { generateSitemapXml } from "@trident/client/nextjs";
// Fetch entries from Trident
const entries = await trident.getSitemap();
// Generate sitemap entries
const sitemapEntries = generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/blog/:slug",
});
// Generate XML string
const xml = generateSitemapXml(sitemapEntries);
// Serve as XML response
return new Response(xml, {
headers: {
"Content-Type": "application/xml",
"Cache-Control": "public, max-age=3600",
},
});Multi-Territory Sitemaps
Handle multiple territories with hreflang annotations:
// app/sitemap.ts
import { trident } from "@/lib/trident";
export default async function sitemap() {
const entries = await trident.getSitemap();
// Group entries by slug to find alternate versions
const bySlug = entries.reduce((acc, entry) => {
const baseSlug = entry.slug.replace(/-[a-z]{2}(-[a-z]{2})?$/, "");
if (!acc[baseSlug]) acc[baseSlug] = [];
acc[baseSlug].push(entry);
return acc;
}, {} as Record<string, typeof entries>);
return Object.entries(bySlug).flatMap(([baseSlug, versions]) => {
return versions.map((entry) => ({
url: `https://yourdomain.com/${entry.languageCode}/blog/${entry.slug}`,
lastModified: entry.updatedAt,
alternates: {
languages: Object.fromEntries(
versions.map((v) => [
v.languageCode,
`https://yourdomain.com/${v.languageCode}/blog/${v.slug}`,
])
),
},
}));
});
}Static Generation
Use sitemap entries to generate static pages at build time:
// app/blog/[slug]/page.tsx
import { trident } from "@/lib/trident";
export async function generateStaticParams() {
const entries = await trident.getSitemap();
return entries.map((entry) => ({
slug: entry.slug,
}));
}
export default async function ArticlePage({ params }) {
const article = await trident.getArticle(params.slug);
// ...
}