From 84d60f8044252aff5734169328fbef455f1f1777 Mon Sep 17 00:00:00 2001 From: "Alfred (Manuels Agent)" Date: Sun, 5 Jul 2026 18:31:33 +0200 Subject: [PATCH] fix(seo): set metadataBase so OG images resolve to production The file-based opengraph-image route emitted og:image/twitter:image URLs pointing at http://localhost:3000, so social previews (WhatsApp, X, LinkedIn, Facebook) were broken on all marketing pages. Setting metadataBase resolves those relative URLs against the production origin. Also drops the hreflang language alternates: every language is served from the same URL, so per-language alternates all pointed here and signalled nothing. Destination pages with distinct de/en URLs keep their own. Co-Authored-By: Claude Opus 4.8 --- src/app/layout.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 933ccb6..bc94ac1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -30,6 +30,10 @@ export async function generateMetadata(): Promise { const locale = await getLocale(); const t = await getTranslations({ locale, namespace: "meta" }); return { + // Resolve relative metadata URLs (og:image / twitter:image from the file-based + // opengraph-image route) against the production origin. Without this, Next.js + // falls back to http://localhost:3000, which shipped broken social previews. + metadataBase: new URL("https://packedplaces.com"), title: { // Every page title already includes the brand (e.g. "Contact — PackedPlaces.com"), // so a "%s | PackedPlaces.com" template doubled it. Drop the template; page titles @@ -45,15 +49,10 @@ export async function generateMetadata(): Promise { siteName: "PackedPlaces.com", type: "website", }, - alternates: { - languages: { - en: "https://packedplaces.com", - de: "https://packedplaces.com", - es: "https://packedplaces.com", - fr: "https://packedplaces.com", - "x-default": "https://packedplaces.com", - }, - }, + // No hreflang alternates: the site serves every language from the same URL + // (locale is negotiated, not path-prefixed), so per-language alternates would + // all point here and signal nothing. Destination pages that genuinely have + // distinct de/en URLs set their own alternates. }; }