Skip to main content
StormyCMS

GraphQL Queries

Queries fetch data from your StormyCMS site. Content queries (pages, layouts, media) authenticate with your site credentials. User and site-team queries additionally need a user JWT (see API Reference → Authentication).

Authentication

Include your site credentials in every request:

headers: {
'Content-Type': 'application/json',
'x-client-id': 'YOUR_CLIENT_ID',
'x-client-secret': 'YOUR_CLIENT_SECRET'
}

Page Queries

Get a Page by Slug

The most common query when rendering a site — look up the page for the current URL:

query GetPageBySlug($slug: String!) {
pageBySlug(slug: $slug) {
id
name
slug
metadata {
title
description
keywords
}
layoutId
components {
id
order
name
attrs {
name
value
}
props {
name
value
}
parentComponentId
childComponents {
id
order
name
attrs {
name
value
}
props {
name
value
}
parentComponentId
}
}
}
}
{ "slug": "home" }

Returns null (not an error) when no page matches the slug — useful for 404 handling.

Component depth: GraphQL has no recursive fragments, so expand childComponents to the nesting depth your content uses. The official client expands three levels and handles deeper trees client-side.

Get a Page by ID

query GetPage($id: ID!) {
page(id: $id) {
id
slug
metadata {
title
description
}
layoutId
updatedAt
}
}

List Pages

query GetPages($limit: Int, $offset: Int) {
pages(limit: $limit, offset: $offset) {
id
slug
metadata {
title
}
updatedAt
}
}
{ "limit": 10, "offset": 0 }

limit defaults to 20 and offset to 0.

Fetch a Page with Its Layouts

Pages also expose the site's layouts so a renderer can assemble the full layout chain in one request:

query GetPageForRender($slug: String!) {
pageBySlug(slug: $slug) {
id
slug
metadata {
title
description
keywords
}
layoutId
components {
id
order
name
props {
name
value
}
attrs {
name
value
}
parentComponentId
childComponents {
id
order
name
props {
name
value
}
parentComponentId
}
}
layouts {
id
name
isDefault
outletId
parentLayoutId
childLayoutId
components {
id
order
name
props {
name
value
}
parentComponentId
}
}
}
}

Layout Queries

Get All Layouts

query GetLayouts {
layouts {
id
name
isDefault
outletId
parentLayoutId
childLayoutId
components {
id
name
props {
name
value
}
}
}
}

Layouts chain via parentLayoutId/childLayoutId; the component named Outlet (referenced by outletId) marks where nested content renders. @stormycms/react provides buildLayoutTree to assemble the chain.

Get a Specific Layout

query GetLayout($id: ID!) {
layout(id: $id) {
id
name
isDefault
components {
id
name
props {
name
value
}
}
}
}

Site Queries

Get the Current Site

query CurrentSite {
getCurrentSite {
id
name
clientId
redirectUrls
createdAt
}
}

Identified by your client credentials — no arguments needed.

Media Queries

Media is a site-scoped resource, so authenticate with your site credentials (x-client-id / x-client-secret) the same way you do for pages and layouts. No user JWT is required.

query GetMediaItems($limit: Int, $offset: Int) {
mediaItems(limit: $limit, offset: $offset) {
id
type
url
name
metadata
createdAt
}
}
query GetMedia($id: ID!) {
media(id: $id) {
id
type
url
name
metadata
}
}

Using the Typed Client

All of the above are wrapped by StormyCMSClient in @stormycms/core:

import { StormyCMSClient } from '@stormycms/core';
const client = new StormyCMSClient();
const pages = await client.getPages({ limit: 10, offset: 0 });
const page = await client.getPageBySlug({ slug: 'home' });
const layouts = await client.getLayouts();
const site = await client.getCurrentSite();

Next Steps

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

StormyCMSThe headless CMS where you own the management panel
Community
StormyCMS