From 42ef2b1dbbf237feadb4f9e72a469cd94c572e52 Mon Sep 17 00:00:00 2001 From: Waleed Date: Tue, 21 Apr 2026 12:43:43 -0700 Subject: [PATCH] fix(landing): resolve error-page crash on invalid /models and /integrations routes (#4243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(layout): use plain inline script for PublicEnvScript to set env before chunks eval on error pages * fix(landing): handle runtime env race on error-page renders React skips SSR on unhandled server errors and re-renders on the client (see vercel/next.js#63980, #82456). Root-layout scripts — including the runtime env script that populates window.__ENV — are inserted but not executed on that client re-render, so any client module that reads env at module evaluation crashes the render into a blank "Application error" overlay instead of rendering the styled 404. This replaces the earlier PublicEnvScript tweak with the architectural fix: - auth-client.ts: fall back to window.location.origin when getBaseUrl() throws on the client. Auth endpoints are same-origin, so this is the correct baseURL on the client. Server-side we still throw on genuine misconfig. - loading.tsx under /models/[provider], /models/[provider]/[model], and /integrations/[slug]: establishes a Suspense boundary below the root layout so a page-level notFound() no longer invalidates the layout's SSR output (the fix endorsed by Next.js maintainers in #63980). - layout.tsx: revert disableNextScript — the research showed this doesn't actually fix error-page renders. The real fix is above. * improvement(landing): use emcn Loader in scoped loading.tsx, trim auth-client comment Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: Claude Opus 4.7 --- .../sim/app/(landing)/integrations/[slug]/loading.tsx | 9 +++++++++ .../(landing)/models/[provider]/[model]/loading.tsx | 9 +++++++++ apps/sim/app/(landing)/models/[provider]/loading.tsx | 9 +++++++++ apps/sim/lib/auth/auth-client.ts | 11 ++++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 apps/sim/app/(landing)/integrations/[slug]/loading.tsx create mode 100644 apps/sim/app/(landing)/models/[provider]/[model]/loading.tsx create mode 100644 apps/sim/app/(landing)/models/[provider]/loading.tsx diff --git a/apps/sim/app/(landing)/integrations/[slug]/loading.tsx b/apps/sim/app/(landing)/integrations/[slug]/loading.tsx new file mode 100644 index 0000000000..3ee348ad1f --- /dev/null +++ b/apps/sim/app/(landing)/integrations/[slug]/loading.tsx @@ -0,0 +1,9 @@ +import { Loader } from '@/components/emcn' + +export default function IntegrationDetailLoading() { + return ( +
+ +
+ ) +} diff --git a/apps/sim/app/(landing)/models/[provider]/[model]/loading.tsx b/apps/sim/app/(landing)/models/[provider]/[model]/loading.tsx new file mode 100644 index 0000000000..af530c8b60 --- /dev/null +++ b/apps/sim/app/(landing)/models/[provider]/[model]/loading.tsx @@ -0,0 +1,9 @@ +import { Loader } from '@/components/emcn' + +export default function ModelDetailLoading() { + return ( +
+ +
+ ) +} diff --git a/apps/sim/app/(landing)/models/[provider]/loading.tsx b/apps/sim/app/(landing)/models/[provider]/loading.tsx new file mode 100644 index 0000000000..7738ad1ed1 --- /dev/null +++ b/apps/sim/app/(landing)/models/[provider]/loading.tsx @@ -0,0 +1,9 @@ +import { Loader } from '@/components/emcn' + +export default function ModelProviderLoading() { + return ( +
+ +
+ ) +} diff --git a/apps/sim/lib/auth/auth-client.ts b/apps/sim/lib/auth/auth-client.ts index ac52461729..a0ce3585b0 100644 --- a/apps/sim/lib/auth/auth-client.ts +++ b/apps/sim/lib/auth/auth-client.ts @@ -15,8 +15,17 @@ import { isBillingEnabled, isOrganizationsEnabled } from '@/lib/core/config/feat import { getBaseUrl } from '@/lib/core/utils/urls' import { SessionContext, type SessionHookResult } from '@/app/_shell/providers/session-provider' +function getAuthBaseUrl(): string { + try { + return getBaseUrl() + } catch (e) { + if (typeof window !== 'undefined') return window.location.origin + throw e + } +} + export const client = createAuthClient({ - baseURL: getBaseUrl(), + baseURL: getAuthBaseUrl(), plugins: [ adminClient(), emailOTPClient(),