Skip to main content
StormyCMS

@stormycms/core

Server-side API client, content types, data mapping, and S3 helpers.

Terminal window
pnpm add @stormycms/core

StormyCMSClient

import { StormyCMSClient } from '@stormycms/core';
const client = new StormyCMSClient();
const page = await client.getPageBySlug({ slug: 'about' });

Configuration defaults to STORMY_CMS_CLIENT_ID, STORMY_CMS_CLIENT_SECRET, and NEXT_PUBLIC_SITE_URL. Constructor overrides are clientId, clientSecret, siteUrl, and redirectUrl for the OAuth callback.

Content reads

MethodResult
getPages({ limit?, offset? })GqlPage[], default limit 20 and offset 0
getPage({ id })GqlPage
getPageBySlug({ slug })GqlPage or null when no data returns
getLayouts()GqlLayout[]
getLayout({ id })GqlLayout
getCurrentSite()SiteData

Writes and media

These methods take a JWT first, then a parameter object:

MethodParameters
createPageslug, metadata, components, layoutId, createdAt, updatedAt
updatePageid, slug, metadata, components, layoutId, updatedAt
deletePageid
createLayoutname, components, createdAt, updatedAt
updateLayoutid, name, components, parentLayoutId?, updatedAt
deleteLayoutid
getMediaItemslimit?, offset?
createMediatype, url, name, metadata
updateMediaid, type?, url?, name?, metadata?
deleteMediaid
updateUserid, username?, displayName?, email?, githubId?, googleId?

getMedia(jwt, id) takes an ID string. Media helpers accept a JWT even though the media API authorizes site credentials.

Sessions

MethodResult
getJWTToken(cookieHeader?)JWT or null, with per-client caching until near expiry
getSession(sessionToken?, cookieHeader?){ user, jwt }, nullable when unavailable
exchangeTokenForJWT(code)Session token and user from an OAuth code
mintJwt(sessionToken){ jwt, expiresIn }
getUser(cookieHeader)Signed-in user
getSites(cookieHeader?)Accessible sites

signIn and signUp take a provider, optional auth options, and redirect/cookie hooks. Next.js helpers supply the hooks.

Raw GraphQL

graphql<T>(query, variables?, options?) returns { data, errors, message? }. Options include cookieHeader, jwt, autoGenerateJwt, and timeoutMs.

const result = await client.graphql<{ getCurrentSite: { id: string } }>('query { getCurrentSite { id } }', undefined, {
cookieHeader,
});
if (result.errors.length) throw new Error(result.errors[0]?.message);

Use the account portal or GraphQL for site creation and credential resets. Client mismatches affect createSite, getSite, resetClientId, and ID-based getUser calls.

Data mapping

FunctionConversion
mapPageData(page)GqlPage to CMSPageData
mapLayoutData(layout)GqlLayout to CMSLayoutData
mapComponentDataToInput(component)CMSComponentData to GqlComponentInput

Mapping converts between name/value arrays and records. It does not fetch data.

Fields

Every CMSField has label, prop, and field, with optional required and defaultValue.

fieldControl or configuration
input, textareaSingle-line or multiline text
markdownMarkdown authoring
checkboxBoolean
dateTimeDate and time
select, radioChoice from required options: string[]
imageMedia picker, returns ImageAsset
textList, numberList, checkboxList, textareaListRepeated values
keyValueListKey/value entries
listTyped items specified by fieldTypes: CMSFieldType[]
complexListNested fields specified by subFields?: CMSField[]
noopFunction value supplied by fn

The starter implements text, Markdown, checkbox, choice, image, and key/value controls. Other schema types need custom editor controls.

ImageAsset has a required src: string and optional alt, mediaId, name, and tags: string[].

Storage

S3 helpers take an explicit S3Config with endpoint, bucket, accessKeyId, secretAccessKey, and optional region.

  • uploadToS3(file, key, config, contentType?, isPublic?)
  • deleteFromS3(key, config)
  • listObjects(config, prefix?, maxKeys?)
  • getPresignedUploadUrl(key, config, expiresInSeconds?, contentType?)
  • getPresignedDownloadUrl(key, config, expiresInSeconds?)

S3StorageClient(config) wraps these as upload, delete, list, getPresignedUrl, and getDownloadUrl. getPublicUrl(key) constructs a URL without changing object permissions.

The starter's admin has its own storage adapter. See Media storage for setup.

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

StormyCMS

The headless CMS where you own the editor.