Skip to content

Commit 9dff9d8

Browse files
jorgemoyaclaude
andcommitted
fix(makeswift): move MakeswiftProvider into locale layout, pass locale
Addresses review feedback on #2991: `MakeswiftProvider` needs the active `locale` (per Makeswift ReactRuntimeProvider docs), so move the provider into `app/[locale]/layout.tsx` where `locale` is available and forward it through. Root `app/layout.tsx` stays as canary's pass-through. The 404 page (`app/not-found.tsx`) wraps its own tree with `MakeswiftProvider` + `<SiteTheme />` explicitly so the branded theme still applies outside `[locale]`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent fd1a8d4 commit 9dff9d8

4 files changed

Lines changed: 79 additions & 66 deletions

File tree

core/app/[locale]/layout.tsx

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getSiteVersion } from '@makeswift/runtime/next/server';
12
import { Analytics } from '@vercel/analytics/react';
23
import { SpeedInsights } from '@vercel/speed-insights/next';
34
import { clsx } from 'clsx';
@@ -23,8 +24,12 @@ import { ScriptsFragment } from '~/components/consent-manager/scripts-fragment';
2324
import { ContainerQueryPolyfill } from '~/components/polyfills/container-query';
2425
import { scriptsTransformer } from '~/data-transformers/scripts-transformer';
2526
import { routing } from '~/i18n/routing';
27+
import { SiteTheme } from '~/lib/makeswift/components/site-theme';
28+
import { MakeswiftProvider } from '~/lib/makeswift/provider';
2629
import { getToastNotification } from '~/lib/server-toast';
2730

31+
import '~/lib/makeswift/components';
32+
2833
const RootLayoutMetadataQuery = graphql(
2934
`
3035
query RootLayoutMetadataQuery {
@@ -125,6 +130,7 @@ export default async function RootLayout({ params, children }: Props) {
125130

126131
const rootData = await fetchRootLayoutMetadata();
127132
const toastNotificationCookieData = await getToastNotification();
133+
const siteVersion = await getSiteVersion();
128134

129135
if (!routing.locales.includes(locale)) {
130136
notFound();
@@ -140,34 +146,39 @@ export default async function RootLayout({ params, children }: Props) {
140146
const privacyPolicyUrl = rootData.data.site.settings?.privacy?.privacyPolicyUrl;
141147

142148
return (
143-
<html className={clsx(fonts.map((f) => f.variable))} lang={locale}>
144-
<body className="flex min-h-screen flex-col">
145-
<NextIntlClientProvider>
146-
<ConsentManager
147-
isCookieConsentEnabled={isCookieConsentEnabled}
148-
privacyPolicyUrl={privacyPolicyUrl}
149-
scripts={scripts}
150-
>
151-
<NuqsAdapter>
152-
<AnalyticsProvider
153-
channelId={rootData.data.channel.entityId}
154-
isCookieConsentEnabled={isCookieConsentEnabled}
155-
settings={rootData.data.site.settings}
156-
>
157-
<Providers>
158-
{toastNotificationCookieData && (
159-
<CookieNotifications {...toastNotificationCookieData} />
160-
)}
161-
{children}
162-
</Providers>
163-
</AnalyticsProvider>
164-
</NuqsAdapter>
165-
</ConsentManager>
166-
</NextIntlClientProvider>
167-
<VercelComponents />
168-
<ContainerQueryPolyfill />
169-
</body>
170-
</html>
149+
<MakeswiftProvider locale={locale} siteVersion={siteVersion}>
150+
<html className={clsx(fonts.map((f) => f.variable))} lang={locale}>
151+
<head>
152+
<SiteTheme />
153+
</head>
154+
<body className="flex min-h-screen flex-col">
155+
<NextIntlClientProvider>
156+
<ConsentManager
157+
isCookieConsentEnabled={isCookieConsentEnabled}
158+
privacyPolicyUrl={privacyPolicyUrl}
159+
scripts={scripts}
160+
>
161+
<NuqsAdapter>
162+
<AnalyticsProvider
163+
channelId={rootData.data.channel.entityId}
164+
isCookieConsentEnabled={isCookieConsentEnabled}
165+
settings={rootData.data.site.settings}
166+
>
167+
<Providers>
168+
{toastNotificationCookieData && (
169+
<CookieNotifications {...toastNotificationCookieData} />
170+
)}
171+
{children}
172+
</Providers>
173+
</AnalyticsProvider>
174+
</NuqsAdapter>
175+
</ConsentManager>
176+
</NextIntlClientProvider>
177+
<VercelComponents />
178+
<ContainerQueryPolyfill />
179+
</body>
180+
</html>
181+
</MakeswiftProvider>
171182
);
172183
}
173184

core/app/layout.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
import { getSiteVersion } from '@makeswift/runtime/next/server';
21
import { PropsWithChildren } from 'react';
32

4-
import { SiteTheme } from '~/lib/makeswift/components/site-theme';
5-
import { MakeswiftProvider } from '~/lib/makeswift/provider';
6-
7-
import '~/lib/makeswift/components';
8-
93
// Since we have a `not-found.tsx` at the root, a layout file is required even if
104
// it just passes children through. Ownership of <html>/<body> lives in
115
// app/[locale]/layout.tsx (to set lang={locale}) and app/not-found.tsx (for
126
// non-localized 404s). See: https://next-intl.dev/docs/environments/error-files
137
// TODO: Move <html>/<body> back here and set lang via Next.js `rootParams`
148
// once it is available on Native Hosting (Next.js 16.2+).
15-
export default async function RootLayout({ children }: PropsWithChildren) {
16-
const siteVersion = await getSiteVersion();
17-
18-
return (
19-
<MakeswiftProvider siteVersion={siteVersion}>
20-
<SiteTheme />
21-
{children}
22-
</MakeswiftProvider>
23-
);
9+
export default function RootLayout({ children }: PropsWithChildren) {
10+
return children;
2411
}

core/app/not-found.tsx

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,47 @@
1+
import { getSiteVersion } from '@makeswift/runtime/next/server';
12
import { clsx } from 'clsx';
23

34
import '../globals.css';
45

56
import { fonts } from '~/app/fonts';
7+
import { SiteTheme } from '~/lib/makeswift/components/site-theme';
8+
import { MakeswiftProvider } from '~/lib/makeswift/provider';
9+
10+
import '~/lib/makeswift/components';
611

712
// Renders for non-localized requests that don't match any route (e.g. /unknown.txt)
813
// or when app/[locale]/layout.tsx calls notFound() for an invalid locale. Since
914
// app/layout.tsx is a passthrough, this page must own its own <html>/<body>.
10-
export default function RootNotFound() {
15+
export default async function RootNotFound() {
16+
const siteVersion = await getSiteVersion();
17+
1118
return (
12-
<html className={clsx(fonts.map((f) => f.variable))} lang="en">
13-
<body className="flex min-h-screen flex-col">
14-
<main className="flex flex-1 items-center justify-center font-[family-name:var(--not-found-font-family,var(--font-family-body))]">
15-
<div className="mx-auto w-full max-w-screen-2xl px-3 py-10 @container @xl:px-6 @4xl:px-20">
16-
<header className="text-center">
17-
<h1 className="mb-3 font-[family-name:var(--not-found-title-font-family,var(--font-family-heading))] text-3xl font-medium leading-none text-[var(--not-found-title,hsl(var(--foreground)))] @xl:text-4xl @4xl:text-5xl">
18-
Not found
19-
</h1>
20-
<p className="mb-4 text-lg text-[var(--not-found-subtitle,hsl(var(--contrast-500)))]">
21-
The page you are looking for could not be found.
22-
</p>
23-
<a
24-
className="relative z-0 inline-flex min-h-14 select-none items-center justify-center gap-x-3 overflow-hidden rounded-full border border-[var(--button-primary-border,hsl(var(--primary)))] bg-[var(--button-primary-background,hsl(var(--primary)))] px-6 py-4 text-center font-[family-name:var(--button-font-family)] text-base font-semibold leading-normal text-[var(--button-primary-text)] after:absolute after:inset-0 after:-z-10 after:-translate-x-[105%] after:rounded-full after:bg-[var(--button-primary-background-hover,color-mix(in_oklab,hsl(var(--primary)),white_75%))] after:transition-[opacity,transform] after:duration-300 after:[animation-timing-function:cubic-bezier(0,0.25,0,1)] hover:after:translate-x-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--button-focus,hsl(var(--primary)))] focus-visible:ring-offset-2"
25-
href="/"
26-
>
27-
<span>Go to homepage</span>
28-
</a>
29-
</header>
30-
</div>
31-
</main>
32-
</body>
33-
</html>
19+
<MakeswiftProvider siteVersion={siteVersion}>
20+
<html className={clsx(fonts.map((f) => f.variable))} lang="en">
21+
<head>
22+
<SiteTheme />
23+
</head>
24+
<body className="flex min-h-screen flex-col">
25+
<main className="flex flex-1 items-center justify-center font-[family-name:var(--not-found-font-family,var(--font-family-body))]">
26+
<div className="mx-auto w-full max-w-screen-2xl px-3 py-10 @container @xl:px-6 @4xl:px-20">
27+
<header className="text-center">
28+
<h1 className="mb-3 font-[family-name:var(--not-found-title-font-family,var(--font-family-heading))] text-3xl font-medium leading-none text-[var(--not-found-title,hsl(var(--foreground)))] @xl:text-4xl @4xl:text-5xl">
29+
Not found
30+
</h1>
31+
<p className="mb-4 text-lg text-[var(--not-found-subtitle,hsl(var(--contrast-500)))]">
32+
The page you are looking for could not be found.
33+
</p>
34+
<a
35+
className="relative z-0 inline-flex min-h-14 select-none items-center justify-center gap-x-3 overflow-hidden rounded-full border border-[var(--button-primary-border,hsl(var(--primary)))] bg-[var(--button-primary-background,hsl(var(--primary)))] px-6 py-4 text-center font-[family-name:var(--button-font-family)] text-base font-semibold leading-normal text-[var(--button-primary-text)] after:absolute after:inset-0 after:-z-10 after:-translate-x-[105%] after:rounded-full after:bg-[var(--button-primary-background-hover,color-mix(in_oklab,hsl(var(--primary)),white_75%))] after:transition-[opacity,transform] after:duration-300 after:[animation-timing-function:cubic-bezier(0,0.25,0,1)] hover:after:translate-x-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--button-focus,hsl(var(--primary)))] focus-visible:ring-offset-2"
36+
href="/"
37+
>
38+
<span>Go to homepage</span>
39+
</a>
40+
</header>
41+
</div>
42+
</main>
43+
</body>
44+
</html>
45+
</MakeswiftProvider>
3446
);
3547
}

core/lib/makeswift/provider.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ import '~/lib/makeswift/components';
77

88
export function MakeswiftProvider({
99
children,
10+
locale,
1011
siteVersion,
1112
}: {
1213
children: React.ReactNode;
14+
locale?: string;
1315
siteVersion: SiteVersion | null;
1416
}) {
1517
return (
1618
<ReactRuntimeProvider
1719
apiOrigin={process.env.NEXT_PUBLIC_MAKESWIFT_API_ORIGIN}
1820
appOrigin={process.env.NEXT_PUBLIC_MAKESWIFT_APP_ORIGIN}
21+
locale={locale}
1922
runtime={runtime}
2023
siteVersion={siteVersion}
2124
>

0 commit comments

Comments
 (0)