Next.js Sitemap
Automatically generate sitemap in Next.js for static routes.
app/sitemap.ts
ts1/** 2 * @see https://github.com/iamvishnusankar/next-sitemap/issues/895#issuecomment-2741949689 3 */ 4 5import fs from "fs"; 6import path from "path"; 7 8import { siteConfig } from "@/config/site"; 9import type { MetadataRoute } from "next"; 10 11async function getStaticRoutes( 12 dir = "src/app", 13 parentPath = "" 14): Promise<string[]> { 15 const currentDir = path.join(process.cwd(), dir); 16 const entries = fs.readdirSync(currentDir, { withFileTypes: true }); 17 18 let routes: string[] = []; 19 20 for (const entry of entries) { 21 const fullPath = path.join(currentDir, entry.name); 22 23 if (entry.isDirectory()) { 24 // Check if this is a route group (wrapped in parentheses) 25 const isRouteGroup = 26 entry.name.startsWith("(") && entry.name.endsWith(")"); 27 28 // For route groups, don't include the folder name in the path 29 const routePath = isRouteGroup 30 ? parentPath 31 : path.join(parentPath, entry.name); 32 33 const hasPage = ["page.tsx", "page.jsx"].some((file) => 34 fs.existsSync(path.join(fullPath, file)) 35 ); 36 37 if (hasPage && !isRouteGroup) { 38 // Only add route if it's not a route group folder 39 routes.push(`/${routePath}`); 40 } 41 42 const nestedRoutes = await getStaticRoutes( 43 path.join(dir, entry.name), 44 routePath 45 ); 46 47 const nestedStaticRoutes = nestedRoutes.filter( 48 (route) => !route.match(/\[.+\]/) 49 ); 50 51 routes = routes.concat(nestedStaticRoutes); 52 } 53 } 54 55 return parentPath === "" ? ["/", ...routes] : routes; 56} 57 58export default async function sitemap(): Promise<MetadataRoute.Sitemap> { 59 const allRoutes = (await Promise.all([getStaticRoutes()])).flat(); 60 61 return allRoutes.map((route) => ({ 62 url: encodeURI(`${siteConfig.url}${route}`), 63 lastModified: new Date().toISOString(), 64 priority: route === "/" ? 1 : 0.8, 65 })); 66}