In this page you will learn how to create an application in your CMS and fetch content from Graph
-
Go to your CMS → Settings → API Keys
-
Under Render Content, copy the "Single Key"
-
Edit your
.envfile in the root and add the following line:OPTIMIZELY_GRAPH_SINGLE_KEY=<the value you copied>
Locate the file src/app/layout.tsx or create it if it doesn't exist. Put the following content:
import { ArticleContentType } from '@/components/Article';
import { initContentTypeRegistry } from '@optimizely/cms-sdk';
initContentTypeRegistry([ArticleContentType]);
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}Create a file src/app/[...slug]/page.tsx. Your file structure should look like this:
.
├── src/
│ ├── app/
│ │ ├── [...slug]/
│ │ │ └── page.tsx
│ │ └── layout.tsx
│ └── components/
│ └── Article.tsx
├── public
├── .env
├── package.json
└── ...
Put the following content in page.tsx
import { GraphClient } from '@optimizely/cms-sdk';
import React from 'react';
type Props = {
params: Promise<{
slug: string[];
}>;
};
export default async function Page({ params }: Props) {
const { slug } = await params;
const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY!, {
graphUrl: process.env.OPTIMIZELY_GRAPH_GATEWAY,
});
const content = await client.getContentByPath(`/${slug.join('/')}/`);
return <pre>{JSON.stringify(content[0], null, 2)}</pre>;
}Start the application
npm run devGo to http://localhost:3000/en/
You should see the content you have created as JSON
Now you are ready to render the content that you just fetched.
The GraphClient provides multiple methods for fetching content from Optimizely CMS.
Fetches content based on URL path. Returns an array of all items matching the path and options.
// Fetch content by path
const content = await client.getContentByPath('/blog/my-article');
// With variation options
const content = await client.getContentByPath('/blog/my-article', {
variation: { include: 'SOME', value: ['variation-id'] },
host: 'https://example.com'
});Parameters:
path(string): URL path to the contentoptions(optional):variation: Filter by experience variationshost: Override default host for multi-site scenarios
Returns: Array of content items (empty array if not found)
New in this version! Unified content fetching method using GraphReference. Provides flexible content retrieval with support for key-based queries, locale filtering, and version selection.
// Fetch by key only (latest published)
const content = await client.getContent({ key: 'abc123' });
// Fetch latest draft in specific locale
const content = await client.getContent({
key: 'abc123',
locale: 'en'
});
// Fetch specific version (version has priority)
const content = await client.getContent({
key: 'abc123',
version: '1.0'
});
// Using string format
const content = await client.getContent('graph://cms/Page/abc123?loc=en&ver=1.0');
// With preview token
const content = await client.getContent(
{ key: 'abc123', version: '1.0' },
'preview-token'
);Parameters:
reference(GraphReference | string): Content reference (object or graph:// string)previewToken(optional): Preview token for draft content
GraphReference format:
key(required): Content GUID/keylocale(optional): Content locale (e.g., 'en', 'sv')version(optional): Specific version (takes priority over locale)type(optional): Content type namesource(optional): Source identifier (unused for now)
String format: graph://[source]/[type]/key?loc=locale&ver=version
Priority rules:
- If
versionis specified, it takes priority (ignores locale-based filtering) - If only
localeis specified, fetches latest draft in that locale - If neither specified, fetches latest published version
Returns: Content item or null if not found
Fetches the breadcrumb path (ancestor pages) for a given page. Now supports both URL paths and GraphReference.
// Using URL path
const path = await client.getPath('/blog/my-article');
// Using GraphReference object
const path = await client.getPath({
key: 'abc123',
locale: 'en'
});
// Using graph:// string format
const path = await client.getPath('graph://Page/abc123?loc=en');
// With locales filter
const path = await client.getPath(
{ key: 'abc123' },
{ locales: ['en', 'sv'] }
);Parameters:
input(string | GraphReference): URL path or GraphReferenceoptions(optional):host: Override default host (only for path strings)locales: Array of locales to filter
Returns: Array of ancestor page metadata (sorted from top to current) or null if page doesn't exist
Fetches child pages for a given parent page. Now supports both URL paths and GraphReference.
// Using URL path
const items = await client.getItems('/blog');
// Using GraphReference object
const items = await client.getItems({
key: 'abc123',
locale: 'en'
});
// Using graph:// string format
const items = await client.getItems('graph://Page/abc123?loc=en');
// With locales filter
const items = await client.getItems(
{ key: 'abc123' },
{ locales: ['en', 'sv'] }
);Parameters:
input(string | GraphReference): URL path or GraphReferenceoptions(optional):host: Override default host (only for path strings)locales: Array of locales to filter
Returns: Array of child page metadata or null if parent doesn't exist
The GraphClient constructor accepts the following options:
The Content Graph endpoint URL.
- Default:
https://cg.optimizely.com/content/v2 - Example:
https://cg.staging.optimizely.com/content/v2
The Graph Client uses the production Content Graph endpoint by default (https://cg.optimizely.com/content/v2). If you want to use a different URL, configure it by passing the graphUrl as option. For example:
const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY, {
graphUrl: 'https://cg.staging.optimizely.com/content/v2',
});Default application host for path filtering. Useful when multiple sites share the same CMS instance - ensures content is retrieved only from the specified domain.
- Default:
undefined - Example:
https://example.com - Can be overridden: Yes, per-request via
getContentByPath,getPath, andgetItemsoptions
const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY, {
graphUrl: process.env.OPTIMIZELY_GRAPH_GATEWAY,
host: 'https://example.com',
});
// Uses default host from client
await client.getContentByPath('/about');
// Override for specific request
await client.getContentByPath('/contact', {
host: 'https://other-site.com',
});Maximum number of GraphQL fragments before logging performance warnings. Prevents overly complex queries from unrestricted content types that could breach GraphQL limits or degrade performance.
- Default:
100 - Example:
150
const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY, {
graphUrl: process.env.OPTIMIZELY_GRAPH_GATEWAY,
maxFragmentThreshold: 150,
});When this threshold is exceeded, you'll see a warning like:
⚠️ [optimizely-cms-sdk] Fragment "MyContentType" generated 200 inner fragments (limit: 150).
→ Consider narrowing it using allowedTypes and restrictedTypes or reviewing schema references to reduce complexity.