Customise
SEO
Defaults come from config.ts. Pages can override. The sitemap is generated on build.
Root layout calls getSEOTags() with config.appName, config.appDescription, and config.domainName. Override per page:
export const metadata = getSEOTags({
title: "Pricing",
description: "One payment. Lifetime access.",
canonicalUrlRelative: "/#pricing",
});metadataBase is http://localhost:3000/ in development and https://{domainName}/ in production.
Share images
Favicons live in app/:
icon.pngapple-icon.png
Slack, iMessage, and Twitter read the Open Graph card from app/opengraph-image.tsx (and app/twitter-image.tsx). It is generated at 1200×630 so the preview is a full card, not a tiny logo. Edit that file to change the share image. You do not register it in libs/seo.tsx.
After you deploy a new card, Slack often keeps the old image until its cache expires. Paste the URL into opengraph.xyz to confirm the live image.
Sitemap and robots
npm run build runs next-sitemap. Output lands in public/ and is gitignored.
Set this on the host:
SITE_URL=https://your-domain.comIf SITE_URL is missing, the sitemap falls back to https://launch-kit.co. That is a different variable from NEXT_PUBLIC_SITE_URL.
/showcase is already noindex.
JSON-LD
renderSchemaTags() in libs/seo.tsx is optional SoftwareApplication markup. Edit the author and offer before you drop it on a page.
Blog posts already emit Article JSON-LD from frontmatter.
Legal pages
/tos and /privacy-policy use components/legal/LegalDoc.tsx for chrome. Edit the copy in app/tos/page.tsx and app/privacy-policy/page.tsx. Set config.resend.supportEmail so both pages have a real contact address.