Why it matters
lib/utils/urls.ts already exports getSiteUrl(), which reads NEXT_PUBLIC_SITE_URL, falls back to NEXT_PUBLIC_APP_URL, strips trailing slashes, and only then falls back to the production domain. But several files re-implement a weaker version of that logic inline:
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "https://agentpostmortem.com";
That copy ignores NEXT_PUBLIC_APP_URL and does not strip a trailing slash, so a preview deploy configured with https://preview.example.com/ produces double-slash URLs in the sitemap and RSS feed.
Where
Replace the inline fallback with import { getSiteUrl } from "@/lib/utils/urls" in:
app/sitemap.ts (line ~10)
app/robots.ts (line ~5)
app/feed.xml/route.ts (line ~8)
app/(public)/agent/[slug]/page.tsx (line ~21)
app/(public)/tag/[slug]/page.tsx (line ~21)
app/(public)/case/[caseNumber]/page.tsx (lines ~44 and ~135)
app/layout.tsx and lib/resend/send.ts already do it the right way, so use those as the reference.
Notes
- Leave the hardcoded
agentpostmortem.com strings that are display text or mailto: addresses alone. This is only about URL construction.
- Run
npm test and npm run format before opening the PR.
Scope is a handful of one-line edits, comfortably under an hour.
Questions are very welcome. Comment here to claim it and ask anything you are unsure about, you will usually get a reply within a day.
Why it matters
lib/utils/urls.tsalready exportsgetSiteUrl(), which readsNEXT_PUBLIC_SITE_URL, falls back toNEXT_PUBLIC_APP_URL, strips trailing slashes, and only then falls back to the production domain. But several files re-implement a weaker version of that logic inline:That copy ignores
NEXT_PUBLIC_APP_URLand does not strip a trailing slash, so a preview deploy configured withhttps://preview.example.com/produces double-slash URLs in the sitemap and RSS feed.Where
Replace the inline fallback with
import { getSiteUrl } from "@/lib/utils/urls"in:app/sitemap.ts(line ~10)app/robots.ts(line ~5)app/feed.xml/route.ts(line ~8)app/(public)/agent/[slug]/page.tsx(line ~21)app/(public)/tag/[slug]/page.tsx(line ~21)app/(public)/case/[caseNumber]/page.tsx(lines ~44 and ~135)app/layout.tsxandlib/resend/send.tsalready do it the right way, so use those as the reference.Notes
agentpostmortem.comstrings that are display text ormailto:addresses alone. This is only about URL construction.npm testandnpm run formatbefore opening the PR.Scope is a handful of one-line edits, comfortably under an hour.
Questions are very welcome. Comment here to claim it and ask anything you are unsure about, you will usually get a reply within a day.