Nexus CMS

Next.js adapter

Wire content fetching, the handshake, SEO and force-update.

Enable the compiler

next.config.mjs
import { withNexus } from "@nexus-cms/nextjs/config";
export default withNexus({ reactStrictMode: true });

Fetch content (no-flash) + render the provider

app/layout.tsx
import { fetchPageContent, getEditSession, buildMetadata } from "@nexus-cms/nextjs";
import { NexusProvider } from "@nexus-cms/nextjs/client";
import schema from "../.nexus/cms-schema.json";

const BACKEND = process.env.NEXT_PUBLIC_NEXUS_API_URL!;

export async function generateMetadata() {
  const content = await fetchPageContent("/", { baseUrl: BACKEND });
  return buildMetadata(schema as never, "/", content);
}

export default async function Layout({ children }) {
  const { editMode, token } = await getEditSession();
  const content = await fetchPageContent("/", { baseUrl: BACKEND, token, draft: editMode });
  return (
    <html><body>
      <NexusProvider schema={schema as never} page="/" baseUrl={BACKEND}
        token={token} editMode={editMode} initialContent={content}>
        {children}
      </NexusProvider>
    </body></html>
  );
}

fetchPageContent tags the request per page with a ~10 minute revalidate window.

SEO priority

buildMetadata(schema, page, content) merges:

  1. Schema defaults from cms-schema.jsonpages[route].seo
  2. CMS overrides win for any field the editor saved (title, description, ogImage, …)

If you also set Next.js metadata / generateMetadata in the route, spread Nexus last so overrides reach <head>:

export async function generateMetadata() {
  const content = await fetchPageContent("/", { baseUrl: BACKEND });
  return {
    ...yourStaticBits,
    ...buildMetadata(schema as never, "/", content),
  };
}

If you never call buildMetadata, the SEO panel only updates in-memory overrides (dogfood/memory demos) and does not change the live document head.

Handshake + force-update routes

app/api/nexus/edit/route.ts
export { createEnterEditRoute as GET } from "@nexus-cms/nextjs";
app/api/nexus/revalidate/route.ts
import { createRevalidateRoute } from "@nexus-cms/nextjs";
export const POST = createRevalidateRoute({ secret: process.env.NEXUS_WEBHOOK_SECRET });

Filament opens /api/nexus/edit?token=…&to=/pricing to enter edit mode, and POSTs to /api/nexus/revalidate on publish so visitors see changes instantly.

On this page