Skip to content

NextAdminLayout

NextAdminLayout(props): Promise<Element>

Defined in: packages/next/src/NextAdminLayout.tsx:52

Next.js admin layout shell for VexCMS.

A server component that sits on the server→client boundary for the admin panel. It sanitizes the resolved vex.config with sanitizeConfigForClient — stripping storage adapter class instances, functions, and React components — before the config is handed to the client leaf NextAdminLayoutClient.

This placement is the whole point: React serializes props when a server component renders a client component, so the sanitize must happen on the server side of that edge. Sanitizing inside the client component would run too late — the raw config would already have failed to serialize.

The client leaf handles everything that needs the browser (usePathname, NuqsAdapter, NextLink/NextImage); this wrapper does no client work.

Render it from your admin layout.tsx. Because this is a server component, your layout.tsx may itself be an async server component (e.g. to run auth checks) and pass the raw vex.config straight through — no sanitize needed on the application side.

Layout props

ReactNode

The page content from [[...slug]]/page.tsx

VexConfig

The resolved VexCMS config from vex.config.ts (raw)

Record<string, unknown>

AdminUser

Current user for the admin shell

Promise<Element>

The rendered admin shell, wrapping children in the sanitized-config client boundary (NextAdminLayoutClient).

app/admin/layout.tsx
import { NextAdminLayout } from "@vexcms/next/client";
import config from "~/vex.config";
import { getCurrentUser } from "~/auth/serverUtils";
export default async function AdminLayout({ children }: { children: ReactNode }) {
const user = await getCurrentUser();
return (
<NextAdminLayout config={config} user={user ?? undefined}>
{children}
</NextAdminLayout>
);
}