Next.js Sitemap

Automatically generate sitemap in Next.js for static routes.

app/sitemap.ts

ts
1/**
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}

Loved this post?

Comments

Interested in
working
with me?

Let's Connect

Stay in touch 👇

© 2021 - 2025 itsrakesh. v2.