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.
Parameters
Section titled “Parameters”Layout props
children
Section titled “children”ReactNode
The page content from [[...slug]]/page.tsx
config
Section titled “config”The resolved VexCMS config from vex.config.ts (raw)
organization?
Section titled “organization?”Record<string, unknown>
Current user for the admin shell
Returns
Section titled “Returns”Promise<Element>
The rendered admin shell, wrapping children in the sanitized-config
client boundary (NextAdminLayoutClient).
Example
Section titled “Example”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> );}