# SEO Optimization — Design Spec **Date:** 2026-04-07 **Domain:** letsbe.biz **Stack:** Next.js 16 App Router, next-intl (en/fr, `as-needed` prefix), Payload CMS ## Current State The site has a single `metadata` export in the layout with a generic title/description. No robots.txt, no sitemap, no OG tags, no hreflang, no structured data, no analytics. The services page has a static English-only metadata export. Case study pages and the homepage have no metadata at all. ## 1. Metadata Foundation ### metadataBase Add `metadataBase: new URL('https://letsbe.biz')` to `src/app/(frontend)/[locale]/layout.tsx`. Required for OG images and canonical URLs to resolve as absolute URLs. ### i18n SEO keys Add a `meta` section to both `en.json` and `fr.json`: ```json { "meta": { "home": { "title": "...", "description": "..." }, "about": { "title": "...", "description": "..." }, "services": { "title": "...", "description": "..." }, "work": { "monaco-ocean": { "title": "...", "description": "..." }, "port-nimara": { "title": "...", "description": "..." }, "port-amador": { "title": "...", "description": "..." } } } } ``` ### Per-page generateMetadata Convert every page to use `generateMetadata({ params })`: - Read locale from params - Call `getTranslations({ locale, namespace: 'meta' })` for localized title/description - Set `alternates.canonical` (e.g., `https://letsbe.biz/about` for en, `https://letsbe.biz/fr/about` for fr) - Set `alternates.languages` for hreflang: - `en` → unprefixed path - `fr` → `/fr/` prefixed path - `x-default` → unprefixed (English) ### Layout metadata Convert the layout's static `metadata` to `generateMetadata()` so it can set locale-aware defaults, `metadataBase`, and default OG/Twitter config. ## 2. Social Sharing (Open Graph / Twitter) ### Default OG in layout ```ts openGraph: { type: 'website', siteName: 'LetsBe.', locale: locale === 'fr' ? 'fr_FR' : 'en_US', images: [{ url: '/images/og-default.png', width: 1200, height: 630 }], } twitter: { card: 'summary_large_image', } ``` ### OG image Create a 1200x630 OG default image using sharp — the logo centered on a branded background (the site's surface color with the blue accent). Place at `public/images/og-default.png`. ### Per-page OG Case study pages override with their hero image. Other pages use the default. ## 3. Crawl Infrastructure ### robots.ts `src/app/robots.ts`: - Allow all user agents - Disallow `/admin/`, `/api/` - Sitemap: `https://letsbe.biz/sitemap.xml` ### sitemap.ts `src/app/sitemap.ts`: - Static routes: `/`, `/about`, `/services` - Dynamic routes: `/work/monaco-ocean`, `/work/port-nimara`, `/work/port-amador` - Each entry includes both locale variants in `alternates.languages` - `lastModified` set to build date - `changeFrequency` and `priority` set appropriately ## 4. Structured Data (JSON-LD) Inject via `