Use real git commit dates in sitemap lastmod values

Static routes had no lastModified at all, giving Google Search Console no freshness signal for the site's core marketing pages. Derive lastmod per page from git log on its source file, matching the fix already shipped in the smbcloud monorepo's copy of this site. Verified against real next build output. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

keypair34 committed Jul 6, 2026 at 19:05 UTC 9bb345a956f034e118fd6b884b2dcc1b07bc6211
1 file changed +48 -82
app/sitemap.ts
+48 -82
@@ -1,92 +1,58 @@
1 +import { execSync } from "child_process";
2 import { MetadataRoute } from "next";
3 import { allKtis, allPages, allPosts } from "contentlayer/generated";
4 import { absoluteUrl } from "./seo";
5
6 export const dynamic = "force-static";
7
8 +// Static routes have no frontmatter date, so pull the real last-edited date
9 +// from git history instead of stamping every one with the build time —
10 +// accurate lastmod values are a genuine freshness signal for crawlers.
11 +function lastCommitDate(sourceFile: string): Date | undefined {
12 + try {
13 + const iso = execSync(`git log -1 --format=%cI -- "${sourceFile}"`, {
14 + cwd: process.cwd(),
15 + encoding: "utf8",
16 + }).trim();
17 + return iso ? new Date(iso) : undefined;
18 + } catch {
19 + return undefined;
20 + }
21 +}
22 +
23 +interface StaticRoute {
24 + path: string;
25 + sourceFile: string;
26 + changeFrequency: MetadataRoute.Sitemap[number]["changeFrequency"];
27 + priority: number;
28 +}
29 +
30 +const STATIC_ROUTES: StaticRoute[] = [
31 + { path: "/", sourceFile: "app/page.tsx", changeFrequency: "weekly", priority: 1 },
32 + { path: "/services", sourceFile: "app/services/page.tsx", changeFrequency: "weekly", priority: 0.9 },
33 + { path: "/mail", sourceFile: "app/mail/page.tsx", changeFrequency: "weekly", priority: 0.9 },
34 + { path: "/auth", sourceFile: "app/auth/page.tsx", changeFrequency: "weekly", priority: 0.9 },
35 + { path: "/posts", sourceFile: "app/posts/page.tsx", changeFrequency: "weekly", priority: 0.8 },
36 + { path: "/kti", sourceFile: "app/kti/page.tsx", changeFrequency: "weekly", priority: 0.8 },
37 + { path: "/heroku-alternative", sourceFile: "app/heroku-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
38 + { path: "/railway-alternative", sourceFile: "app/railway-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
39 + { path: "/resend-alternative", sourceFile: "app/resend-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
40 + { path: "/usesend-alternative", sourceFile: "app/usesend-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
41 + { path: "/sendgrid-alternative", sourceFile: "app/sendgrid-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
42 + { path: "/auth0-alternative", sourceFile: "app/auth0-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
43 + { path: "/clerk-alternative", sourceFile: "app/clerk-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
44 + { path: "/supabase-alternative", sourceFile: "app/supabase-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
45 + { path: "/neon-alternative", sourceFile: "app/neon-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
46 + { path: "/planetscale-alternative", sourceFile: "app/planetscale-alternative/page.tsx", changeFrequency: "weekly", priority: 0.8 },
47 +];
48 +
49 export default function sitemap(): MetadataRoute.Sitemap {
8 - const staticRoutes: MetadataRoute.Sitemap = [
9 - {
10 - url: absoluteUrl("/"),
11 - changeFrequency: "weekly",
12 - priority: 1,
13 - },
14 - {
15 - url: absoluteUrl("/services"),
16 - changeFrequency: "weekly",
17 - priority: 0.9,
18 - },
19 - {
20 - url: absoluteUrl("/mail"),
21 - changeFrequency: "weekly",
22 - priority: 0.9,
23 - },
24 - {
25 - url: absoluteUrl("/auth"),
26 - changeFrequency: "weekly",
27 - priority: 0.9,
28 - },
29 - {
30 - url: absoluteUrl("/posts"),
31 - changeFrequency: "weekly",
32 - priority: 0.8,
33 - },
34 - {
35 - url: absoluteUrl("/kti"),
36 - changeFrequency: "weekly",
37 - priority: 0.8,
38 - },
39 - {
40 - url: absoluteUrl("/heroku-alternative"),
41 - changeFrequency: "weekly",
42 - priority: 0.8,
43 - },
44 - {
45 - url: absoluteUrl("/railway-alternative"),
46 - changeFrequency: "weekly",
47 - priority: 0.8,
48 - },
49 - {
50 - url: absoluteUrl("/resend-alternative"),
51 - changeFrequency: "weekly",
52 - priority: 0.8,
53 - },
54 - {
55 - url: absoluteUrl("/usesend-alternative"),
56 - changeFrequency: "weekly",
57 - priority: 0.8,
58 - },
59 - {
60 - url: absoluteUrl("/sendgrid-alternative"),
61 - changeFrequency: "weekly",
62 - priority: 0.8,
63 - },
64 - {
65 - url: absoluteUrl("/auth0-alternative"),
66 - changeFrequency: "weekly",
67 - priority: 0.8,
68 - },
69 - {
70 - url: absoluteUrl("/clerk-alternative"),
71 - changeFrequency: "weekly",
72 - priority: 0.8,
73 - },
74 - {
75 - url: absoluteUrl("/supabase-alternative"),
76 - changeFrequency: "weekly",
77 - priority: 0.8,
78 - },
79 - {
80 - url: absoluteUrl("/neon-alternative"),
81 - changeFrequency: "weekly",
82 - priority: 0.8,
83 - },
84 - {
85 - url: absoluteUrl("/planetscale-alternative"),
86 - changeFrequency: "weekly",
87 - priority: 0.8,
88 - },
89 - ];
50 + const staticRoutes: MetadataRoute.Sitemap = STATIC_ROUTES.map((route) => ({
51 + url: absoluteUrl(route.path),
52 + lastModified: lastCommitDate(route.sourceFile),
53 + changeFrequency: route.changeFrequency,
54 + priority: route.priority,
55 + }));
56
57 const postRoutes: MetadataRoute.Sitemap = allPosts
58 .filter((post) => post.published)