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
childComponentsto 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
- GraphQL Mutations - Create and modify content
- API Reference - Full type and operation reference
- Examples - Complete rendering examples
Last updated: 7/9/26, 6:42 AM