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 reads the consolidated vex-admin cookie’s sidebarOpen field server-side (Decision 51; previously a dedicated sidebar_state cookie) so the sidebar’s open/closed state is correct on first paint, with no client flash, and passes it, plus authPromise/ children, to the client leaf NextAdminLayoutClient. Config no longer crosses this boundary at all — the admin panel’s client tree gets its config from the app’s own root VexConfigProvider mount (components/providers/client.tsx), not from a prop threaded through this layout.

Does not await authPromise itself (perf fix, Decision 44/streaming) — only cookies() (fast, no network). The sidebar resolves authPromise inside its OWN <Suspense> boundary (AdminLayout, @vexcms/react), so a slow getUserOrg() round trip only delays the sidebar nav, never children or this layout’s own static chrome.

Render it from your admin layout.tsx. Because this is a server component, your layout.tsx may itself call server-only auth helpers to build authPromise (e.g. getUserOrg() from ~/auth/server) — started, not awaited, so layout.tsx itself stays synchronous and streams immediately.

Layout props.

Promise<VexApiAuth>

The in-flight { user, organization } fetch (Decision 44), optional — omit it entirely when config.access is absent/disabled.

ReactNode

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

Promise<Element>

The rendered admin shell, wrapping children in the client boundary (NextAdminLayoutClient) with the server-read sidebar cookie state.

app/admin/layout.tsx
import { NextAdminLayout } from "@vexcms/next/client";
import { getUserOrg } from "~/auth/server";
export default function AdminLayout({ children }: { children: ReactNode }) {
return (
<NextAdminLayout authPromise={getUserOrg()}>
{children}
</NextAdminLayout>
);
}