Skip to main content
StormyCMS

Render a CMS page

The starter already renders CMS pages. Use this pattern when adding a route to an existing Next.js app with Stormy credentials and a shared component export map.

In src/stormy-cms-client.ts:

import { StormyCMSClient } from '@stormycms/core';
export const stormyCMSClient = new StormyCMSClient();

In src/app/[...slug]/page.tsx:

import { notFound } from 'next/navigation';
import { mapPageData } from '@stormycms/core';
import { buildLayoutTree, ComponentTree, LayoutTree } from '@stormycms/react/cms';
import cmsExports from 'components';
import { stormyCMSClient } from '~/stormy-cms-client';
export const dynamic = 'force-dynamic';
export default async function Page({ params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params;
const result = await stormyCMSClient.getPageBySlug({ slug: slug.join('/') });
if (!result) notFound();
const page = mapPageData(result);
const layout = buildLayoutTree(page.layouts, page.layoutId);
return (
<LayoutTree layout={layout} cmsExports={cmsExports}>
<ComponentTree components={page.components ?? []} cmsExports={cmsExports} />
</LayoutTree>
);
}

Open a URL matching a saved page slug, such as /about. mapPageData converts GraphQL props and attrs into the records the renderer expects.

Each layout needs an Outlet to render its children. The catch-all route above handles non-root URLs.

For editing, use Components and schema and the Next.js auth helpers.

Last updated: 10/20/26, 1:09 AM

StormyCMS

The headless CMS where you own the editor.