The root layout fed the entire ~254 KB message catalogue to NextIntlClientProvider, which serializes it into the RSC payload of every page. A public page only reads ~59 KB of it; the ~195 KB difference is staff tool copy that only /admin, /admin-next and /mod ever render. The root provider now installs the reduced catalogue and each staff route group re-installs the full one, since a nested NextIntlClientProvider replaces the parent message set rather than merging into it. pages.admin.actions stays public because the shared useServerAction hook runs on public pages too. Measured: 253 KB -> 59 KB of messages per public page (raw JSON). Guard tests cover all three halves: the root keeps using the reduced catalogue, every staff layout installs its own full provider, and no public tree reads a staff-only namespace.
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { notFound } from "next/navigation";
|
|
import { NextIntlClientProvider } from "next-intl";
|
|
import { getLocale, getMessages } from "next-intl/server";
|
|
import type { ReactNode } from "react";
|
|
import { env } from "@/env";
|
|
import { isHousekeepingPreviewEnabled } from "@/features/housekeeping/foundation/preview-gate";
|
|
import { getHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/server-capability-context";
|
|
import { PERMS } from "@/lib/permission-slugs";
|
|
|
|
export default async function AdminNextLayout({
|
|
children,
|
|
}: {
|
|
children: ReactNode;
|
|
}) {
|
|
const hasProductionAccess =
|
|
env.NODE_ENV === "production" && env.HOUSEKEEPING_NEXT_PREVIEW_ENABLED
|
|
? (await getHousekeepingCapabilityContext()).has(
|
|
PERMS.HOUSEKEEPING_PREVIEW_ACCESS,
|
|
)
|
|
: false;
|
|
|
|
if (
|
|
!isHousekeepingPreviewEnabled({
|
|
nodeEnv: env.NODE_ENV,
|
|
flag: env.HOUSEKEEPING_NEXT_PREVIEW_ENABLED,
|
|
hasProductionAccess,
|
|
})
|
|
) {
|
|
notFound();
|
|
}
|
|
|
|
// Staff tree: re-install the full catalogue the root layout scopes down to
|
|
// the public subset (nested providers replace the parent set).
|
|
const [locale, messages] = await Promise.all([getLocale(), getMessages()]);
|
|
|
|
return (
|
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
|
{children}
|
|
</NextIntlClientProvider>
|
|
);
|
|
}
|