Skip to main content
StormyCMS

@stormycms/react

React components and hooks for rendering CMS-driven pages and managing session state.

Terminal window
pnpm add @stormycms/react

The package is organized into subpath exports:

ImportContents
@stormycms/reactRe-exported types (SessionUser, SiteData)
@stormycms/react/cmsRendering & registration: withCMS, ComponentTree, LayoutTree, Layout, Outlet, buildLayoutTree, findComponent
@stormycms/react/cms/clientEditor state providers: CMSPageProvider, CMSLayoutProvider, useCMSPage, useCMSLayout
@stormycms/react/stormySession context: StormyProvider, useStormy (client components)
@stormycms/react/pluginThe React framework plugin for stormy generate

@stormycms/react/cms

withCMS(cmsProps, Component)

Wraps a React component with CMS metadata (label, fields, placement rules) so the editor can offer and edit it. Covered in depth in Components & Schema.

ComponentTree

Renders a stored component tree using your export map:

import { ComponentTree } from '@stormycms/react/cms';
import cmsExports from 'components';
<ComponentTree components={page.components} cmsExports={cmsExports} />;

Props:

  • components: CMSComponentData[] — the tree (use mapPageData from core to convert raw GraphQL data)
  • cmsExports: CMSExportsMap — your export map
  • slotContent?: ReactNode — rendered wherever an Outlet component appears

Components whose name isn't in the export map are skipped.

LayoutTree and buildLayoutTree

Layouts chain parent → child, with page content rendered at the innermost Outlet:

import { LayoutTree, ComponentTree, buildLayoutTree } from '@stormycms/react/cms';
const layout = buildLayoutTree(page.layouts, page.layoutId);
<LayoutTree layout={layout} cmsExports={cmsExports}>
<ComponentTree components={page.components!} cmsExports={cmsExports} />
</LayoutTree>;
  • buildLayoutTree(layouts, parentLayoutId?) — assembles a nested CMSLayoutData chain from the flat layout list. Pass the page's layoutId to build the chain for that page; returns null when there's no layout (and LayoutTree then renders children directly).
  • LayoutTree — recursively renders the chain.

Outlet and Layout

Built-in, layout-only CMS components. Outlet marks the content slot; Layout is the internal wrapper LayoutTree uses. Include Outlet in your export map so layouts can place it.

findComponent(components, id)

Depth-first search for a component by ID in a tree — useful in editor UIs.

@stormycms/react/cms/client

Client-side providers that hold the editor state for a page or layout:

import { CMSPageProvider, useCMSPage } from '@stormycms/react/cms/client';
<CMSPageProvider page={{ id: page.id, components: page.components, initialData: { name, slug, layoutId } }}>
<PageEditor />
</CMSPageProvider>;
  • CMSPageProvider / useCMSPage — editable page state, including components, setComponents, addComponent, removeComponent, updateComponent, layoutId, and initialData.
  • CMSLayoutProvider / useCMSLayout — editable layout state, including parentLayoutId and the same component editing helpers.

The boilerplate admin wraps these providers around its PageEditor and LayoutEditor components so the editor can mutate the component tree before saving it back to the API.

@stormycms/react/stormy

Client-side session context. In Next.js apps prefer StormyServerProvider which wraps this with server-fetched initial data.

StormyProvider

'use client';
import { StormyProvider } from '@stormycms/react/stormy';
<StormyProvider loginUrl="/login">{children}</StormyProvider>;

Key props (all optional):

PropDefaultPurpose
authUrl/api/auth/stormy?action=sessionEndpoint polled for session status
siteUrl / sitesUrl...action=site / ...action=sitesEndpoints for current site / site list
loginUrl/loginRedirect target when the session expires
guardtrueWatch the session and redirect on expiry
checkThrottleMs60000Minimum delay between activity-driven session checks
onSessionExpiredCallback instead of redirecting
initialUser / initialSite / initialSitesServer-fetched initial state (skips client fetch)

Session checks are driven by user activity and tab focus rather than a background interval, so an abandoned tab doesn't defeat idle timeouts.

useStormy()

const { user, site, sites, isLoading, isAuthenticated, refresh } = useStormy();

Throws if used outside a StormyProvider.

@stormycms/react/plugin

The React plugin for the CLI's schema generation — parses React component files and infers CMS fields from their props. You normally don't import this directly; the CLI loads it automatically when React is detected.

Last updated: 7/9/26, 6:42 AM

StormyCMSThe headless CMS where you own the management panel
Community
StormyCMS