From 6b0befe9ca5f4384cf6ad7299d02e1773f8d2981 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 2 Oct 2026 14:25:08 -0700 Subject: [PATCH 1/2] fix(landing): return 404 for unknown library, blog, integration, model, and author slugs --- apps/docs/app/sitemap.ts | 12 ++++++++---- apps/sim/app/(landing)/blog/[slug]/page.tsx | 7 +++++-- apps/sim/app/(landing)/blog/authors/[id]/page.tsx | 11 +++++++++++ .../(landing)/integrations/(shell)/[slug]/page.tsx | 7 +++++-- apps/sim/app/(landing)/library/[slug]/page.tsx | 7 +++++-- apps/sim/app/(landing)/library/authors/[id]/page.tsx | 11 +++++++++++ .../models/(shell)/[provider]/[model]/page.tsx | 7 +++++-- .../app/(landing)/models/(shell)/[provider]/page.tsx | 7 +++++-- 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/apps/docs/app/sitemap.ts b/apps/docs/app/sitemap.ts index 5dabe2daa44..17e36be5d4b 100644 --- a/apps/docs/app/sitemap.ts +++ b/apps/docs/app/sitemap.ts @@ -5,8 +5,12 @@ import { DOCS_BASE_URL } from '@/lib/urls' export const revalidate = 3600 export default function sitemap(): MetadataRoute.Sitemap { - return source.getPages().map((page) => ({ - url: `${DOCS_BASE_URL}${page.url}`, - lastModified: 'lastModified' in page.data ? page.data.lastModified : undefined, - })) + // The docs root redirects to /introduction, which is listed on its own. + return source + .getPages() + .filter((page) => page.url !== '/') + .map((page) => ({ + url: `${DOCS_BASE_URL}${page.url}`, + lastModified: 'lastModified' in page.data ? page.data.lastModified : undefined, + })) } diff --git a/apps/sim/app/(landing)/blog/[slug]/page.tsx b/apps/sim/app/(landing)/blog/[slug]/page.tsx index 5ae7a1d8fc7..a14550b75f6 100644 --- a/apps/sim/app/(landing)/blog/[slug]/page.tsx +++ b/apps/sim/app/(landing)/blog/[slug]/page.tsx @@ -4,8 +4,11 @@ import { getAllPostMeta, getPostBySlug, getRelatedPosts } from '@/lib/blog/regis import { BLOG_SECTION, buildPostGraphJsonLd, buildPostMetadata } from '@/lib/blog/seo' import { ContentPostPage } from '@/app/(landing)/components' -/** Unknown slugs reach the section 404 while known pages remain pre-rendered. */ -export const dynamicParams = true +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false export async function generateStaticParams() { const posts = await getAllPostMeta() diff --git a/apps/sim/app/(landing)/blog/authors/[id]/page.tsx b/apps/sim/app/(landing)/blog/authors/[id]/page.tsx index 77aea381d78..c6b235b8db8 100644 --- a/apps/sim/app/(landing)/blog/authors/[id]/page.tsx +++ b/apps/sim/app/(landing)/blog/authors/[id]/page.tsx @@ -6,6 +6,17 @@ import { ContentAuthorPage } from '@/app/(landing)/components' export const revalidate = 3600 +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false + +export async function generateStaticParams() { + const ids = new Set((await getAllPostMeta()).flatMap((p) => p.authors.map((a) => a.id))) + return [...ids].map((id) => ({ id })) +} + export async function generateMetadata({ params, }: { diff --git a/apps/sim/app/(landing)/integrations/(shell)/[slug]/page.tsx b/apps/sim/app/(landing)/integrations/(shell)/[slug]/page.tsx index 881ae42aaa7..b913c431682 100644 --- a/apps/sim/app/(landing)/integrations/(shell)/[slug]/page.tsx +++ b/apps/sim/app/(landing)/integrations/(shell)/[slug]/page.tsx @@ -47,8 +47,11 @@ const MAX_TEMPLATES_SHOWN = 12 const bySlug = new Map(allIntegrations.map((i) => [i.slug, i])) const byType = new Map(allIntegrations.map((i) => [i.type, i])) -/** Unknown slugs reach the section 404 while known pages remain pre-rendered. */ -export const dynamicParams = true +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false /** * Returns up to `limit` related integration slugs from the same category, so diff --git a/apps/sim/app/(landing)/library/[slug]/page.tsx b/apps/sim/app/(landing)/library/[slug]/page.tsx index 57df49bb272..8e2e0f8a4f2 100644 --- a/apps/sim/app/(landing)/library/[slug]/page.tsx +++ b/apps/sim/app/(landing)/library/[slug]/page.tsx @@ -6,8 +6,11 @@ import { ComparisonLinks } from '@/app/(landing)/comparisons/components/comparis import { getComparisonsForPost } from '@/app/(landing)/comparisons/library-links' import { ContentPostPage } from '@/app/(landing)/components' -/** Unknown slugs reach the section 404 while known pages remain pre-rendered. */ -export const dynamicParams = true +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false export async function generateStaticParams() { const posts = await getAllPostMeta() diff --git a/apps/sim/app/(landing)/library/authors/[id]/page.tsx b/apps/sim/app/(landing)/library/authors/[id]/page.tsx index 7af8169eb9d..ecb57807631 100644 --- a/apps/sim/app/(landing)/library/authors/[id]/page.tsx +++ b/apps/sim/app/(landing)/library/authors/[id]/page.tsx @@ -6,6 +6,17 @@ import { ContentAuthorPage } from '@/app/(landing)/components' export const revalidate = 3600 +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false + +export async function generateStaticParams() { + const ids = new Set((await getAllPostMeta()).flatMap((p) => p.authors.map((a) => a.id))) + return [...ids].map((id) => ({ id })) +} + export async function generateMetadata({ params, }: { diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx index 47eb53e18a8..7d6a878a20b 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx @@ -25,8 +25,11 @@ import { const baseUrl = SITE_URL -/** Unknown slugs reach the section 404 while known pages remain pre-rendered. */ -export const dynamicParams = true +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false export async function generateStaticParams() { return ALL_CATALOG_MODELS.map((model) => ({ diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx index 24421550348..8e40fe4e83f 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx @@ -24,8 +24,11 @@ import { const baseUrl = SITE_URL -/** Unknown slugs reach the section 404 while known pages remain pre-rendered. */ -export const dynamicParams = true +/** + * Unknown params must 404 before rendering: `notFound()` during render streams this segment's + * `loading.tsx` with a 200 status first. + */ +export const dynamicParams = false export async function generateStaticParams() { return MODEL_PROVIDERS_WITH_CATALOGS.map((provider) => ({ From cb3c2988a42240d1be1cff1672959955aed6aea9 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 2 Oct 2026 14:32:54 -0700 Subject: [PATCH 2/2] fix(landing): pre-render reseller model pages so they keep resolving --- .../(landing)/models/(shell)/[provider]/[model]/page.tsx | 9 ++++----- .../sim/app/(landing)/models/(shell)/[provider]/page.tsx | 3 ++- apps/sim/app/(landing)/models/utils.ts | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx index 7d6a878a20b..c2eb4c7dc55 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/[model]/page.tsx @@ -10,7 +10,6 @@ import { LANDING_CONTENT_WIDTH, LANDING_GUTTER } from '@/app/(landing)/component import { ShareButton } from '@/app/(landing)/components/share-button' import { FeaturedModelCard, ProviderIcon } from '@/app/(landing)/models/components/model-primitives' import { - ALL_CATALOG_MODELS, buildModelCapabilityFacts, buildModelFaqs, formatPrice, @@ -21,6 +20,7 @@ import { getPricingBounds, getProviderBySlug, getRelatedModels, + MODEL_PROVIDERS_WITH_MODELS, } from '@/app/(landing)/models/utils' const baseUrl = SITE_URL @@ -32,10 +32,9 @@ const baseUrl = SITE_URL export const dynamicParams = false export async function generateStaticParams() { - return ALL_CATALOG_MODELS.map((model) => ({ - provider: model.providerSlug, - model: model.slug, - })) + return MODEL_PROVIDERS_WITH_MODELS.flatMap((provider) => + provider.models.map((model) => ({ provider: provider.slug, model: model.slug })) + ) } export async function generateMetadata({ diff --git a/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx b/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx index 8e40fe4e83f..a49935c38cc 100644 --- a/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx +++ b/apps/sim/app/(landing)/models/(shell)/[provider]/page.tsx @@ -19,6 +19,7 @@ import { formatTokenCount, getProviderBySlug, MODEL_PROVIDERS_WITH_CATALOGS, + MODEL_PROVIDERS_WITH_MODELS, TOP_MODEL_PROVIDERS, } from '@/app/(landing)/models/utils' @@ -31,7 +32,7 @@ const baseUrl = SITE_URL export const dynamicParams = false export async function generateStaticParams() { - return MODEL_PROVIDERS_WITH_CATALOGS.map((provider) => ({ + return MODEL_PROVIDERS_WITH_MODELS.map((provider) => ({ provider: provider.slug, })) } diff --git a/apps/sim/app/(landing)/models/utils.ts b/apps/sim/app/(landing)/models/utils.ts index 61a0947dd61..3761baaa8ed 100644 --- a/apps/sim/app/(landing)/models/utils.ts +++ b/apps/sim/app/(landing)/models/utils.ts @@ -578,6 +578,10 @@ function assertUniqueGeneratedRoutes(providers: CatalogProvider[]): void { assertUniqueGeneratedRoutes(rawProviders) export const MODEL_CATALOG_PROVIDERS: CatalogProvider[] = rawProviders +/** Every provider with a page: those with a model catalog, resellers included. */ +export const MODEL_PROVIDERS_WITH_MODELS = MODEL_CATALOG_PROVIDERS.filter( + (provider) => provider.models.length > 0 +) export const MODEL_PROVIDERS_WITH_CATALOGS = MODEL_CATALOG_PROVIDERS.filter( (provider) => provider.models.length > 0 && !provider.isReseller )