Skip to main content
StormyCMS

@stormycms/core

Framework-agnostic client, types, and utilities for talking to the StormyCMS API. Everything else (react, next) builds on this package.

Terminal window
pnpm add @stormycms/core

StormyCMSClient

The typed client. By default it reads configuration from environment variables:

import { StormyCMSClient } from '@stormycms/core';
// Uses STORMY_CMS_CLIENT_ID, STORMY_CMS_CLIENT_SECRET, NEXT_PUBLIC_SITE_URL
const client = new StormyCMSClient();
// Or configure explicitly:
const client2 = new StormyCMSClient({
siteUrl: 'https://example.com',
clientId: process.env.STORMY_CMS_CLIENT_ID!,
clientSecret: process.env.STORMY_CMS_CLIENT_SECRET!,
callbackUrl: 'https://admin.example.com/api/auth/stormy', // optional OAuth callback
});

The constructor throws if credentials are missing, so misconfiguration fails fast at startup.

Content methods (site credentials)

MethodReturnsNotes
getPages({ limit?, offset? })GqlPage[]Defaults: limit 20, offset 0
getPage({ id })GqlPageThrows if not found
getPageBySlug({ slug })GqlPage | nullReturns null when missing — use for 404s
getLayouts()GqlLayout[]
getLayout({ id })GqlLayout
getCurrentSite()SiteDataThe site your credentials identify

Editor methods (require a JWT)

These take a jwt as the first argument:

MethodNotes
createPage(jwt, { slug, metadata, components, layoutId, createdAt, updatedAt })
updatePage(jwt, { id, slug, metadata, components, layoutId, updatedAt })Replaces the component tree
deletePage(jwt, { id })
createLayout(jwt, { name, components, createdAt, updatedAt })
updateLayout(jwt, { id, name, components, parentLayoutId?, updatedAt })
deleteLayout(jwt, { id })
getMediaItems(jwt, { limit?, offset? }) / getMedia(jwt, id)
createMedia(jwt, { type, url, name, metadata })Record an uploaded file
updateMedia(jwt, { id, ... }) / deleteMedia(jwt, { id })
updateUser(jwt, { id, username?, displayName?, email?, ... })

Auth & session methods

MethodPurpose
signIn(provider?, options?, hooks?) / signUp(...)Build the OAuth redirect to the Stormy auth service (github or google). Framework-agnostic via redirect/setCookie hooks.
exchangeTokenForJWT(code)Exchange an OAuth auth code for a session token + user
mintJwt(sessionToken)Mint a short-lived JWT ({ jwt, expiresIn })
getJWTToken(cookieHeader?)Convenience: parse the stormy_session_token cookie and mint a JWT; returns null when signed out
getSession(sessionToken?, cookieHeader?){ user, jwt } for the current session (never throws)
getUser(cookieHeader, userId?)The signed-in user (or another visible user)

Site & team methods (session-authenticated)

getSites, getSite, updateSite, resetClientId, resetClientSecret, getSiteWithUsers, inviteUser, resendInvite. Most teams manage sites and members through the account portal; these exist for programmatic workflows.

Escape hatch: raw GraphQL

const result = await client.graphql<MyResult>(
`query { getCurrentSite { id name } }`,
undefined, // variables
cookieHeader, // optional: authenticates as the session user
);
// result: { data, errors, message? } — errors normalized to { code, message }

Data Mapping Helpers

The GraphQL API represents props and attrs as name/value pairs. The map helpers convert to ergonomic shapes used by the React renderer and editor:

FunctionConverts
mapPageData(gqlPage)GqlPageCMSPageData (props become plain records, metadata normalized)
mapLayoutData(gqlLayout)GqlLayoutCMSLayoutData
mapComponentDataToInput(data)CMSComponentDatacomponentInput for mutations

ImageAsset

image fields use the ImageAsset type:

type ImageAsset = {
src: string;
alt?: string;
mediaId?: string;
name?: string;
tags?: string[];
};

The boilerplate admin's media picker stores the public URL as src, the media record ID as mediaId, and any alt text/tags as alt/tags so components can render them directly or look up the full media record later.

Storage Helpers (S3)

Utilities for media storage against any S3-compatible service, used by the boilerplate admin's media routes:

  • uploadToS3(...), deleteFromS3(key, config), listObjects(...)
  • getPresignedUploadUrl(...), getPresignedDownloadUrl(...)
  • S3StorageClient — class wrapper over the same operations
  • Types: S3Config, UploadResult

Configure via S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_REGION.

Types

Two families of types are exported:

  • Gql* — raw GraphQL shapes: GqlPage, GqlLayout, GqlComponent, GqlMetadata, plus inputs (GqlComponentInput, GqlMetadataInput) and response/param types
  • CMS* — editor/renderer-friendly shapes: CMSPageData, CMSLayoutData, CMSComponentData, CMSField, CMSFieldType, CMSFieldValue

Plus SessionUser, SiteData, Site, SiteWithUsers, User, MediaItem, ImageAsset, and type guards (isImageValue, isImageField, isCheckboxField, isInputField, isStringArray, ...).

See Components & Schema for how CMSField drives the editor UI.

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

StormyCMSThe headless CMS where you own the management panel
Community
StormyCMS