From d23eabe740116a8cc1079d95dff33bf426bfc54b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 13 Jul 2026 11:06:10 -0700 Subject: [PATCH] fix(landing): fix 404ing OG images for every model and integration page Google Search Console flagged every /models/{provider}/{model}/opengraph-image and /integrations/{slug}/opengraph-image URL as 404 (~230 pages total: 5 sample model pages plus ~130 more models, plus every integration). Root cause: the sibling page.tsx for each of these routes sets `dynamicParams = false`, a segment-level restriction that also blocks the metadata route (opengraph-image.tsx) from rendering any param combination it wasn't statically told about - but Next does not share generateStaticParams between a page and its sibling metadata routes. Since none of the three opengraph-image.tsx files exported their own generateStaticParams, every param was "unknown" to that restriction and 404d, for every single model and integration. Added a matching generateStaticParams to all three files, mirroring each route's own page.tsx. Note: the exact URLs in the audit report (bare /opengraph-image, no suffix) aren't the real ones - Next serves these at a build-generated hash suffix (e.g. /opengraph-image-15dal5?), which is what's actually embedded in each page's tag. The underlying bug the report surfaced is real regardless; verified by requesting the actual hash-suffixed URL each page embeds (previously 404, now 200) for both a model and an integration page, on a real production build. --- .../(shell)/[slug]/opengraph-image.tsx | 11 +++++++++++ .../[provider]/[model]/opengraph-image.tsx | 15 +++++++++++++++ .../models/(shell)/[provider]/opengraph-image.tsx | 14 ++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/apps/sim/app/(landing)/integrations/(shell)/[slug]/opengraph-image.tsx b/apps/sim/app/(landing)/integrations/(shell)/[slug]/opengraph-image.tsx index 41fb9c4386c..9a7f50a2039 100644 --- a/apps/sim/app/(landing)/integrations/(shell)/[slug]/opengraph-image.tsx +++ b/apps/sim/app/(landing)/integrations/(shell)/[slug]/opengraph-image.tsx @@ -19,6 +19,17 @@ const AUTH_LABEL: Record = { none: 'No auth required', } +/** + * The sibling page.tsx sets `dynamicParams = false`, a segment-level + * restriction that also blocks this metadata route from rendering any + * param combination it wasn't statically generated for - but Next does not + * share generateStaticParams between a page and its sibling metadata + * routes, so without this export every integration's OG image 404s. + */ +export async function generateStaticParams() { + return integrations.map((integration) => ({ slug: integration.slug })) +} + export default async function Image({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params const integration = bySlug.get(slug) diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/opengraph-image.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/opengraph-image.tsx index dca1c08152d..a57370d6b81 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/opengraph-image.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/opengraph-image.tsx @@ -1,5 +1,6 @@ import { notFound } from 'next/navigation' import { + ALL_CATALOG_MODELS, formatPrice, formatTokenCount, getModelBySlug, @@ -13,6 +14,20 @@ export const size = { height: 630, } +/** + * The sibling page.tsx sets `dynamicParams = false`, a segment-level + * restriction that also blocks this metadata route from rendering any + * param combination it wasn't statically generated for - but Next does not + * share generateStaticParams between a page and its sibling metadata + * routes, so without this export every model's OG image 404s. + */ +export async function generateStaticParams() { + return ALL_CATALOG_MODELS.map((model) => ({ + provider: model.providerSlug, + model: model.slug, + })) +} + export default async function Image({ params, }: { diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/opengraph-image.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/opengraph-image.tsx index 4a12862394d..2243bb6e60f 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/opengraph-image.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/opengraph-image.tsx @@ -5,6 +5,7 @@ import { getCheapestProviderModel, getLargestContextProviderModel, getProviderBySlug, + MODEL_PROVIDERS_WITH_CATALOGS, } from '@/app/(landing)/models/utils' import { createLandingOgImage } from '@/app/(landing)/og-utils' @@ -14,6 +15,19 @@ export const size = { height: 630, } +/** + * The sibling page.tsx sets `dynamicParams = false`, a segment-level + * restriction that also blocks this metadata route from rendering any + * param combination it wasn't statically generated for - but Next does not + * share generateStaticParams between a page and its sibling metadata + * routes, so without this export every provider's OG image 404s. + */ +export async function generateStaticParams() { + return MODEL_PROVIDERS_WITH_CATALOGS.map((provider) => ({ + provider: provider.slug, + })) +} + export default async function Image({ params }: { params: Promise<{ provider: string }> }) { const { provider: providerSlug } = await params const provider = getProviderBySlug(providerSlug)