Overview
Set per-page title and description with generateMetadata and i18n.
Meta tags describe the content of a page. Set them for each marketing route so search engines understand the page and your SEO stays strong.
Base title
The marketing root layout (apps/marketing/src/app/layout.tsx) is a passthrough. Default title and template live on the locale layout:
export async function generateMetadata({
params,
}: LocaleLayoutProps): Promise<Metadata> {
const { locale } = await params;
setRequestLocale(locale);
const t = await getTranslations("meta");
return {
title: {
template: t("titleTemplate"),
default: t("defaultTitle"),
},
};
}Brand strings come from the marketing catalog — not a shared config.appName:
{
"meta": {
"titleTemplate": "%s | TurboJet",
"defaultTitle": "TurboJet"
}
}- Pages without a title use
defaultTitle(for exampleTurboJet). - Pages that set a title apply the template. If the page title is
Privacy Policy, the document title becomesPrivacy Policy | TurboJet.
Keep en.json and id.json in sync when you change these keys. See i18n.
Per-page metadata
Export generateMetadata from the page and return title / description. Prefer translations so each locale gets the right copy:
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("meta");
return {
title: t("homeTitle"),
description: t("homeDescription"),
};
}Other marketing pages follow the same shape:
| Page | Translation namespace / keys |
|---|---|
| Home | meta.homeTitle / homeDescription |
| Privacy Policy | meta.privacyTitle / privacyDescription |
| Terms of Service | meta.termsTitle / termsDescription |
| License | meta.licenseTitle / licenseDescription |
| Checkout success | checkoutSuccess.metaTitle / metaDescription |
Add new strings under packages/i18n/src/marketing/en.json and id.json, then wire them in that page’s generateMetadata.
Learn more in the Next.js generateMetadata docs.