SEO and Metadata
How the marketing site builds canonical URLs, Open Graph and Twitter tags, and JSON-LD structured data from a single config-derived helper.
The marketing site centralizes SEO in apps/marketing/src/lib/seo.ts. Every page
derives its canonical URL and social tags from NEXT_PUBLIC_SITE_URL, so there
are no hard-coded domains to update at launch.
Per-page metadata
Use buildMetadata in a route's metadata export (or generateMetadata):
import { buildMetadata } from "@/lib/seo";
export const metadata = buildMetadata({
title: "Pricing",
description: "Simple, one-time pricing.",
path: "/pricing", // canonical path; absolute URL is derived
});It produces a config-derived canonical URL plus Open Graph and Twitter tags. Options:
| Option | Purpose |
|---|---|
title / description | Page title and meta description. |
path | Canonical path; turned into an absolute URL via absoluteUrl. |
type | "website" (default) or "article" for posts. |
publishedTime / modifiedTime | Article timestamps for OG. |
noindex | Excludes preview/draft pages from search. |
metadataBase, the sitemap, and robots are all driven by the same site URL.
Draft content is served noindex.
Structured data (JSON-LD)
seo.ts also exports typed JSON-LD builders. Render the returned object in a
<script type="application/ld+json">:
blogPostingJsonLd— a blog article.faqJsonLd— the FAQ //faqpage.breadcrumbJsonLd— breadcrumb trails.softwareApplicationJsonLd— the product. Only emit it when a real, visible price exists, and keep theOfferin sync with the price on the page.
Images
Open Graph / Twitter images fall back to the site-wide generated image. Override per page by providing your own OG image where needed.