import React from "react";import * as Sentry from "@sentry/react";import { HeadContent, Outlet, Scripts, createRootRoute, useLocation, useNavigate, useParams,} from "@tanstack/react-router";import { AutumnProvider } from "autumn-js/react";import { isValidOrgSlug } from "@executor-js/api";import posthog from "posthog-js";import { PostHogProvider } from "posthog-js/react";import { createSentryFrontendErrorReporter } from "@executor-js/react/api/error-reporting";import { AnalyticsProvider, type AnalyticsClient } from "@executor-js/react/api/analytics";import { ExecutorProvider } from "@executor-js/react/api/provider";import { OrganizationProvider } from "@executor-js/react/api/organization-context";import { EXECUTOR_ORG_HEADER } from "@executor-js/react/api/server-connection";import { OrgSlugGate } from "@executor-js/react/multiplayer/org-slug-gate";import { Toaster } from "@executor-js/react/components/sonner";import { ExecutorPluginsProvider } from "@executor-js/sdk/client";import { ArtifactRendererProvider } from "@executor-js/react/api/artifact-renderer";import { plugins as clientPlugins } from "virtual:executor/plugins-client";import { AuthProvider, useAuth } from "../web/auth";import { loginPath } from "../auth/return-to";import { ONBOARDING_PATHS, PUBLIC_PATHS } from "../auth/route-paths";import { SupportOptions } from "../web/components/support-options";import { Shell } from "../web/shell";import appCss from "@executor-js/react/globals.css?url"; if (typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_SENTRY_DSN) { Sentry.init({ dsn: import.meta.env.VITE_PUBLIC_SENTRY_DSN, tunnel: "/api/sentry-tunnel", tracesSampleRate: 0, replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, });} if (typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_POSTHOG_KEY) { const analyticsPath = (import.meta.env.VITE_PUBLIC_ANALYTICS_PATH ?? "a").replace( /^\/+|\/+$/g, "", ); posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, { api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST ?? `${window.location.origin}/api/${analyticsPath}`, ui_host: "https://us.posthog.com", defaults: "2025-05-24", person_profiles: "identified_only", disable_session_recording: false, session_recording: { maskAllInputs: true, maskTextSelector: "[data-ph-mask]", blockSelector: "[data-ph-block]", }, });} // The MCP-Apps shell is browser-only — it imports `@tailwindcss/browser`, which// touches `document` at import scope. A static import here would put it in this// SSR app's server graph and 500 every document request, so it is registered as// a dynamic import the artifact page resolves in the browser. Module scope keeps// the loader identity stable, so the lazy component behind it never remounts.const artifactRendererLoader = () => import("@executor-js/mcp-apps-shell/shell/artifact-renderer"); const analyticsClient: AnalyticsClient | undefined = typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_POSTHOG_KEY ? (name, properties) => posthog.capture(name, properties) : undefined; // Shared with the desktop renderer: the factory normalizes the reported value// to a real Error (handed an Effect Cause, Sentry has no message to title or// group on) and owns the executor.ui tags. Only the transport differs.const captureFrontendError = createSentryFrontendErrorReporter((error, applyScope) => { Sentry.captureException(error, (scope) => { applyScope(scope); return scope; });}); function NotFoundPage() { return ( <main className="flex min-h-screen items-center justify-center bg-background px-6 py-10"> <section className="w-full max-w-md text-center"> <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">404</p> <h1 className="mt-2 text-xl font-semibold text-foreground">Page not found</h1> <p className="mt-2 text-sm leading-6 text-muted-foreground"> There's nothing at this address. </p> <a href="/" className="mt-6 inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 transition-colors" > Go home </a> </section> </main> );} export const Route = createRootRoute({ notFoundComponent: NotFoundPage, head: () => ({ meta: [ { charSet: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { title: "Executor Cloud" }, ], links: [ { rel: "icon", type: "image/x-icon", href: "/favicon.ico" }, { rel: "icon", type: "image/png", sizes: "32x32", href: "/favicon-32.png" }, { rel: "icon", type: "image/png", sizes: "192x192", href: "/favicon-192.png" }, { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" }, { rel: "preconnect", href: "https://fonts.googleapis.com" }, { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" }, { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;700&display=swap", }, { rel: "stylesheet", href: appCss }, ], }), component: RootComponent, shellComponent: RootDocument,}); function RootDocument({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> <HeadContent /> </head> <body> {children} <Scripts /> </body> </html> );} function RootComponent() { // SPA mode: no per-request server render, so nothing is dehydrated. Auth // seeds from the client-readable hint cookie one frame after mount // (AuthProvider's own fallback), and origin-derived UI reads the // window-derived global. return ( <PostHogProvider client={posthog}> <AnalyticsProvider client={analyticsClient}> <AuthProvider> <AuthGate /> </AuthProvider> </AnalyticsProvider> </PostHogProvider> );} // Neutral, layout-free placeholder for the moments no UI is correct yet: a// redirect in flight, or the (post-gate, near-impossible) hint-less verified// load. Never the app shell's silhouette — that bet is the bug this file's// gate exists to prevent.function BlankScreen() { return <div className="h-screen bg-background" />;} function ShellErrorFallback() { return ( <main className="flex min-h-screen items-center justify-center bg-background px-6 py-10"> <section className="w-full max-w-md text-center"> <div className="mx-auto mb-5 flex size-11 items-center justify-center rounded-full border border-border bg-muted"> <span className="text-lg font-semibold text-muted-foreground">!</span> </div> <h1 className="text-xl font-semibold text-foreground">Something went wrong</h1> <p className="mt-2 text-sm leading-6 text-muted-foreground"> We've tracked it. Give refreshing a try, and get in touch if support is needed. </p> <p className="mt-6 text-xs font-medium uppercase tracking-wide text-muted-foreground"> Get support </p> <div className="mt-3"> <SupportOptions /> </div> </section> </main> );} function AuthGate() { const auth = useAuth(); const location = useLocation(); const navigate = useNavigate(); const isOnboardingRoute = ONBOARDING_PATHS.has(location.pathname); const isPublicRoute = PUBLIC_PATHS.has(location.pathname); // The org the URL names (the `{-$orgSlug}` segment), if any. `/account/me` // is scoped to it, so `auth.organization` IS this org when the caller is a // member — and `null` when the URL names an org they can't access. const urlOrgSlug = (useParams({ strict: false }) as { orgSlug?: string }).orgSlug; // The same slug derived from the PATHNAME instead of the route params: the // params resolve asynchronously (a fresh load renders once with no orgSlug, // then again with it), and anything keyed on them remounts on that flap. // The pathname is synchronously correct on the very first render, and it is // exactly what the request header derives from (getActiveOrgSlug), so the // registry scope below can never disagree with the header scope. const firstSegment = location.pathname.split("/")[1] ?? ""; const pathnameOrgSlug = isValidOrgSlug(firstSegment) ? firstSegment : null; // The SSR gate already bounced fresh org-less document requests to // /create-org; this catches the MID-SESSION transitions (org deleted, // membership revoked → /account/me now reports no org). Only for BARE paths: // an org-less result on a slugged URL is a wrong address (404 below), not a // reason to send the user to onboarding. const needsOrgRedirect = auth.status === "authenticated" && auth.organization == null && !urlOrgSlug && !isOnboardingRoute && !isPublicRoute; React.useEffect(() => { if (needsOrgRedirect) { void navigate({ to: "/create-org", replace: true }); } }, [needsOrgRedirect, navigate]); // The signed-out safety net behind the SSR gate: if a session dies while // the SPA is already loaded (logout elsewhere, expiry), go to /login the // same way a fresh document request would — keeping where they were. const needsLoginRedirect = auth.status === "unauthenticated" && !isPublicRoute; React.useEffect(() => { if (needsLoginRedirect) { window.location.assign(loginPath(`${location.pathname}${location.searchStr}`)); } }, [needsLoginRedirect, location.pathname, location.searchStr]); if (isPublicRoute) { return <Outlet />; } // Every state that isn't "authenticated with an org, on a page that wants // the shell" is a moment between redirects, or the one frame between mount // and the hint cookie seeding (SPA mode reads it in an effect). Neutral // blank — the one placeholder that's correct whatever happens next. The // app-shell skeleton this file used to render here is exactly the // wrong-UI flash the document gate + hint exist to prevent. if (auth.status === "loading" || auth.status === "unauthenticated") { return <BlankScreen />; } if (isOnboardingRoute) { return <Outlet />; } if (auth.organization == null) { // A URL naming an org this session can't access (`/account/me` returned no // org for its slug) is a wrong address → the route 404, framed by nothing // (the user isn't "in" any org here). A bare path with no org is a new // user — the redirect effect above is taking them to onboarding. return urlOrgSlug ? <NotFoundPage /> : <BlankScreen />; } // The authenticated answer must NAME the org the URL names before any shell // is built from it. `auth.organization` is the auth-hint cookie until // `/account/me` lands, and the hint always names the session's OWN org — so // on a foreign slug it is an answer about a different organization, and // rendering the shell from it puts the user in a workspace the URL never // named. `/account/me` is scoped by the URL's slug (getActiveOrgSlug), so // once it resolves this can only agree or be null; a disagreement is // therefore always an unresolved answer, never a verdict. Blank, not // not-found: the 404 above is the only thing entitled to declare a wrong // address, and it waits for the server. // // The legitimate cold load is untouched: the hint names the slug in the URL, // so this matches on the very first paint and the shell renders with no // round trip. Only a slug the hint does not name pays the wait — a foreign // slug (which then 404s) and the frame after an org switch (which then // renders the org the URL asked for, instead of flashing the previous one). if (pathnameOrgSlug != null && auth.organization.slug !== pathnameOrgSlug) { return <BlankScreen />; } const activeSlug = auth.organization.slug; // The org context's slug feeds the connect card's `/<slug>/mcp` install URL. // Source it from the URL, which is the actual request scope and is correct on // the very first paint. The gate above has already made the two agree // whenever the URL names a slug at all, so this is the same value stated in // the terms the rest of the tree is keyed on. VALIDATED (pathnameOrgSlug, not // the raw route param): the `{-$orgSlug}` param also captures reserved // console roots ("/integrations" → orgSlug "integrations"), which are not // org scopes. Falls back to the auth org on a bare/reserved URL (which // OrgSlugGate canonicalizes onto it below). const scopeSlug = pathnameOrgSlug ?? activeSlug; const billingHeaders = scopeSlug ? { [EXECUTOR_ORG_HEADER]: scopeSlug } : undefined; return ( <AutumnProvider pathPrefix="/api/billing" headers={billingHeaders}> <Sentry.ErrorBoundary fallback={<ShellErrorFallback />} showDialog={false}> {/* scopeKey ties the atom registry to the URL's org: cached query results can never survive an org change, and the bare → slugged canonicalization remounts the registry so anything fetched header-less on first paint (rejected server-side) is refetched with the org header. */} <ExecutorProvider scopeKey={pathnameOrgSlug} onHandledError={captureFrontendError}> <React.Suspense fallback={<BlankScreen />}> <ExecutorPluginsProvider plugins={clientPlugins}> <OrganizationProvider organizationId={auth.organization.id} organizationSlug={scopeSlug} > {/* Canonicalize onto the URL's org, not the auth org: on first paint `auth.organization` is the SSR hint (the COOKIE's org), and canonicalizing onto that would rewrite a multi-org user's /<orgB> URL to /<orgA> during the hint window. `scopeSlug` prefers the URL slug, so a slugged URL is already canonical (a foreign slug 404'd above) and only a bare URL gets rewritten — onto the auth org, the one thing it can mean. */} <OrgSlugGate activeSlug={scopeSlug}> <ArtifactRendererProvider loader={artifactRendererLoader}> <Shell /> </ArtifactRendererProvider> <Toaster /> </OrgSlugGate> </OrganizationProvider> </ExecutorPluginsProvider> </React.Suspense> </ExecutorProvider> </Sentry.ErrorBoundary> </AutumnProvider> );}
import React from "react";
import * as Sentry from "@sentry/react";
import {
HeadContent,
Outlet,
Scripts,
createRootRoute,
useLocation,
useNavigate,
useParams,
} from "@tanstack/react-router";
import { AutumnProvider } from "autumn-js/react";
import { isValidOrgSlug } from "@executor-js/api";
import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react";
import { createSentryFrontendErrorReporter } from "@executor-js/react/api/error-reporting";
import { AnalyticsProvider, type AnalyticsClient } from "@executor-js/react/api/analytics";
import { ExecutorProvider } from "@executor-js/react/api/provider";
import { OrganizationProvider } from "@executor-js/react/api/organization-context";
import { EXECUTOR_ORG_HEADER } from "@executor-js/react/api/server-connection";
import { OrgSlugGate } from "@executor-js/react/multiplayer/org-slug-gate";
import { Toaster } from "@executor-js/react/components/sonner";
import { ExecutorPluginsProvider } from "@executor-js/sdk/client";
import { ArtifactRendererProvider } from "@executor-js/react/api/artifact-renderer";
import { plugins as clientPlugins } from "virtual:executor/plugins-client";
import { AuthProvider, useAuth } from "../web/auth";
import { loginPath } from "../auth/return-to";
import { ONBOARDING_PATHS, PUBLIC_PATHS } from "../auth/route-paths";
import { SupportOptions } from "../web/components/support-options";
import { Shell } from "../web/shell";
import appCss from "@executor-js/react/globals.css?url";
if (typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_SENTRY_DSN) {
Sentry.init({
dsn: import.meta.env.VITE_PUBLIC_SENTRY_DSN,
tunnel: "/api/sentry-tunnel",
tracesSampleRate: 0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
}
if (typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_POSTHOG_KEY) {
const analyticsPath = (import.meta.env.VITE_PUBLIC_ANALYTICS_PATH ?? "a").replace(
/^\/+|\/+$/g,
"",
);
posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, {
api_host:
import.meta.env.VITE_PUBLIC_POSTHOG_HOST ?? `${window.location.origin}/api/${analyticsPath}`,
ui_host: "https://us.posthog.com",
defaults: "2025-05-24",
person_profiles: "identified_only",
disable_session_recording: false,
session_recording: {
maskAllInputs: true,
maskTextSelector: "[data-ph-mask]",
blockSelector: "[data-ph-block]",
},
});
}
// The MCP-Apps shell is browser-only — it imports `@tailwindcss/browser`, which
// touches `document` at import scope. A static import here would put it in this
// SSR app's server graph and 500 every document request, so it is registered as
// a dynamic import the artifact page resolves in the browser. Module scope keeps
// the loader identity stable, so the lazy component behind it never remounts.
const artifactRendererLoader = () => import("@executor-js/mcp-apps-shell/shell/artifact-renderer");
const analyticsClient: AnalyticsClient | undefined =
typeof window !== "undefined" && import.meta.env.VITE_PUBLIC_POSTHOG_KEY
? (name, properties) => posthog.capture(name, properties)
: undefined;
// Shared with the desktop renderer: the factory normalizes the reported value
// to a real Error (handed an Effect Cause, Sentry has no message to title or
// group on) and owns the executor.ui tags. Only the transport differs.
const captureFrontendError = createSentryFrontendErrorReporter((error, applyScope) => {
Sentry.captureException(error, (scope) => {
applyScope(scope);
return scope;
});
});
function NotFoundPage() {
return (
<main className="flex min-h-screen items-center justify-center bg-background px-6 py-10">
<section className="w-full max-w-md text-center">
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">404</p>
<h1 className="mt-2 text-xl font-semibold text-foreground">Page not found</h1>
<p className="mt-2 text-sm leading-6 text-muted-foreground">
There's nothing at this address.
</p>
<a
href="/"
className="mt-6 inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 transition-colors"
>
Go home
</a>
</section>
</main>
);
}
export const Route = createRootRoute({
notFoundComponent: NotFoundPage,
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "Executor Cloud" },
],
links: [
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
{ rel: "icon", type: "image/png", sizes: "32x32", href: "/favicon-32.png" },
{ rel: "icon", type: "image/png", sizes: "192x192", href: "/favicon-192.png" },
{ rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" },
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
{ rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" },
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;700&display=swap",
},
{ rel: "stylesheet", href: appCss },
],
}),
component: RootComponent,
shellComponent: RootDocument,
});
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
);
}
function RootComponent() {
// SPA mode: no per-request server render, so nothing is dehydrated. Auth
// seeds from the client-readable hint cookie one frame after mount
// (AuthProvider's own fallback), and origin-derived UI reads the
// window-derived global.
return (
<PostHogProvider client={posthog}>
<AnalyticsProvider client={analyticsClient}>
<AuthProvider>
<AuthGate />
</AuthProvider>
</AnalyticsProvider>
</PostHogProvider>
);
}
// Neutral, layout-free placeholder for the moments no UI is correct yet: a
// redirect in flight, or the (post-gate, near-impossible) hint-less verified
// load. Never the app shell's silhouette — that bet is the bug this file's
// gate exists to prevent.
function BlankScreen() {
return <div className="h-screen bg-background" />;
}
function ShellErrorFallback() {
return (
<main className="flex min-h-screen items-center justify-center bg-background px-6 py-10">
<section className="w-full max-w-md text-center">
<div className="mx-auto mb-5 flex size-11 items-center justify-center rounded-full border border-border bg-muted">
<span className="text-lg font-semibold text-muted-foreground">!</span>
</div>
<h1 className="text-xl font-semibold text-foreground">Something went wrong</h1>
<p className="mt-2 text-sm leading-6 text-muted-foreground">
We've tracked it. Give refreshing a try, and get in touch if support is needed.
</p>
<p className="mt-6 text-xs font-medium uppercase tracking-wide text-muted-foreground">
Get support
</p>
<div className="mt-3">
<SupportOptions />
</div>
</section>
</main>
);
}
function AuthGate() {
const auth = useAuth();
const location = useLocation();
const navigate = useNavigate();
const isOnboardingRoute = ONBOARDING_PATHS.has(location.pathname);
const isPublicRoute = PUBLIC_PATHS.has(location.pathname);
// The org the URL names (the `{-$orgSlug}` segment), if any. `/account/me`
// is scoped to it, so `auth.organization` IS this org when the caller is a
// member — and `null` when the URL names an org they can't access.
const urlOrgSlug = (useParams({ strict: false }) as { orgSlug?: string }).orgSlug;
// The same slug derived from the PATHNAME instead of the route params: the
// params resolve asynchronously (a fresh load renders once with no orgSlug,
// then again with it), and anything keyed on them remounts on that flap.
// The pathname is synchronously correct on the very first render, and it is
// exactly what the request header derives from (getActiveOrgSlug), so the
// registry scope below can never disagree with the header scope.
const firstSegment = location.pathname.split("/")[1] ?? "";
const pathnameOrgSlug = isValidOrgSlug(firstSegment) ? firstSegment : null;
// The SSR gate already bounced fresh org-less document requests to
// /create-org; this catches the MID-SESSION transitions (org deleted,
// membership revoked → /account/me now reports no org). Only for BARE paths:
// an org-less result on a slugged URL is a wrong address (404 below), not a
// reason to send the user to onboarding.
const needsOrgRedirect =
auth.status === "authenticated" &&
auth.organization == null &&
!urlOrgSlug &&
!isOnboardingRoute &&
!isPublicRoute;
React.useEffect(() => {
if (needsOrgRedirect) {
void navigate({ to: "/create-org", replace: true });
}
}, [needsOrgRedirect, navigate]);
// The signed-out safety net behind the SSR gate: if a session dies while
// the SPA is already loaded (logout elsewhere, expiry), go to /login the
// same way a fresh document request would — keeping where they were.
const needsLoginRedirect = auth.status === "unauthenticated" && !isPublicRoute;
React.useEffect(() => {
if (needsLoginRedirect) {
window.location.assign(loginPath(`${location.pathname}${location.searchStr}`));
}
}, [needsLoginRedirect, location.pathname, location.searchStr]);
if (isPublicRoute) {
return <Outlet />;
}
// Every state that isn't "authenticated with an org, on a page that wants
// the shell" is a moment between redirects, or the one frame between mount
// and the hint cookie seeding (SPA mode reads it in an effect). Neutral
// blank — the one placeholder that's correct whatever happens next. The
// app-shell skeleton this file used to render here is exactly the
// wrong-UI flash the document gate + hint exist to prevent.
if (auth.status === "loading" || auth.status === "unauthenticated") {
return <BlankScreen />;
}
if (isOnboardingRoute) {
return <Outlet />;
}
if (auth.organization == null) {
// A URL naming an org this session can't access (`/account/me` returned no
// org for its slug) is a wrong address → the route 404, framed by nothing
// (the user isn't "in" any org here). A bare path with no org is a new
// user — the redirect effect above is taking them to onboarding.
return urlOrgSlug ? <NotFoundPage /> : <BlankScreen />;
}
// The authenticated answer must NAME the org the URL names before any shell
// is built from it. `auth.organization` is the auth-hint cookie until
// `/account/me` lands, and the hint always names the session's OWN org — so
// on a foreign slug it is an answer about a different organization, and
// rendering the shell from it puts the user in a workspace the URL never
// named. `/account/me` is scoped by the URL's slug (getActiveOrgSlug), so
// once it resolves this can only agree or be null; a disagreement is
// therefore always an unresolved answer, never a verdict. Blank, not
// not-found: the 404 above is the only thing entitled to declare a wrong
// address, and it waits for the server.
//
// The legitimate cold load is untouched: the hint names the slug in the URL,
// so this matches on the very first paint and the shell renders with no
// round trip. Only a slug the hint does not name pays the wait — a foreign
// slug (which then 404s) and the frame after an org switch (which then
// renders the org the URL asked for, instead of flashing the previous one).
if (pathnameOrgSlug != null && auth.organization.slug !== pathnameOrgSlug) {
return <BlankScreen />;
}
const activeSlug = auth.organization.slug;
// The org context's slug feeds the connect card's `/<slug>/mcp` install URL.
// Source it from the URL, which is the actual request scope and is correct on
// the very first paint. The gate above has already made the two agree
// whenever the URL names a slug at all, so this is the same value stated in
// the terms the rest of the tree is keyed on. VALIDATED (pathnameOrgSlug, not
// the raw route param): the `{-$orgSlug}` param also captures reserved
// console roots ("/integrations" → orgSlug "integrations"), which are not
// org scopes. Falls back to the auth org on a bare/reserved URL (which
// OrgSlugGate canonicalizes onto it below).
const scopeSlug = pathnameOrgSlug ?? activeSlug;
const billingHeaders = scopeSlug ? { [EXECUTOR_ORG_HEADER]: scopeSlug } : undefined;
return (
<AutumnProvider pathPrefix="/api/billing" headers={billingHeaders}>
<Sentry.ErrorBoundary fallback={<ShellErrorFallback />} showDialog={false}>
{/* scopeKey ties the atom registry to the URL's org: cached query
results can never survive an org change, and the bare → slugged
canonicalization remounts the registry so anything fetched
header-less on first paint (rejected server-side) is refetched
with the org header. */}
<ExecutorProvider scopeKey={pathnameOrgSlug} onHandledError={captureFrontendError}>
<React.Suspense fallback={<BlankScreen />}>
<ExecutorPluginsProvider plugins={clientPlugins}>
<OrganizationProvider
organizationId={auth.organization.id}
organizationSlug={scopeSlug}
>
{/* Canonicalize onto the URL's org, not the auth org: on first
paint `auth.organization` is the SSR hint (the COOKIE's
org), and canonicalizing onto that would rewrite a
multi-org user's /<orgB> URL to /<orgA> during the hint
window. `scopeSlug` prefers the URL slug, so a slugged URL
is already canonical (a foreign slug 404'd above) and only
a bare URL gets rewritten — onto the auth org, the one
thing it can mean. */}
<OrgSlugGate activeSlug={scopeSlug}>
<ArtifactRendererProvider loader={artifactRendererLoader}>
<Shell />
</ArtifactRendererProvider>
<Toaster />
</OrgSlugGate>
</OrganizationProvider>
</ExecutorPluginsProvider>
</React.Suspense>
</ExecutorProvider>
</Sentry.ErrorBoundary>
</AutumnProvider>
);
}