CMS API Reference
Complete API reference for fetching content from any CMS backend using Makerkit's unified content interface.
The CMS API provides a unified interface for fetching content regardless of your CMS backend. Call createCmsClient() to get a client configured for your environment, then use getContentItems() for lists or getContentItemBySlug() for single items. The same code works with Keystatic, WordPress, or custom implementations - swap backends by changing an environment variable.
The CMS API is the programmatic interface for fetching, filtering, and paginating content from any configured CMS backend.
This page is part of the CMS Integration documentation.
Creating a CMS Client
The client is configured automatically based on the CMS_CLIENT environment variable:
import { createCmsClient } from '@kit/cms';const client = await createCmsClient();The returned client implements the CmsClient interface with methods for content, categories, and tags.
Fetching Content Lists
Use getContentItems() to fetch paginated lists of content:
import { cache } from 'react';import { createCmsClient } from '@kit/cms';const getPostsPage = cache(async (page: number, language?: string) => { const client = await createCmsClient(); const limit = 10; const offset = (page - 1) * limit; const { items, total } = await client.getContentItems({ collection: 'posts', limit, offset, language, sortBy: 'publishedAt', sortDirection: 'desc', }); return { posts: items, totalPages: Math.ceil(total / limit), };});getContentItems Options
| Parameter | Type | Description |
|---|---|---|
collection | string | Collection name: posts, documentation, changelog, or custom |
limit | number | Maximum items to return |
offset | number | Number of items to skip (for pagination) |
language | string | Filter by language code (en, de, etc.) |
sortBy | string | Field to sort by (publishedAt, title, etc.) |
sortDirection | 'asc' | 'desc' | Sort order |
status | string | Content status: published, draft, pending, review |
content | boolean | Whether to include full content (default: false for lists) |
Fetching Single Items
Use getContentItemBySlug() to fetch a single content item:
import { createCmsClient } from '@kit/cms';import { notFound } from 'next/navigation';async function BlogPostPage(props: { params: Promise<{ slug: string }> }) { const { slug } = await props.params; const client = await createCmsClient(); const post = await client.getContentItemBySlug({ slug, collection: 'posts', }); if (!post) { notFound(); } return ( <article> <h1>{post.title}</h1> <div>{post.content}</div> </article> );}getContentItemBySlug Options
| Parameter | Type | Description |
|---|---|---|
slug | string | URL slug of the content item |
collection | string | Collection name |
status | string | Content status (default: published) |
Content Item Structure
Both methods return content items with this structure:
interface ContentItem { id: string; slug: string; title: string; description?: string; content: string; // Rendered HTML or MDX publishedAt: string; // ISO date string updatedAt?: string; author?: { name: string; avatar?: string; }; image?: string; // Featured image URL categories?: Category[]; tags?: Tag[];}Fetching Categories and Tags
const client = await createCmsClient();// Get all categoriesconst categories = await client.getCategories();// Get a specific categoryconst category = await client.getCategoryBySlug('tutorials');// Get all tagsconst tags = await client.getTags();// Get a specific tagconst tag = await client.getTagBySlug('nextjs');Caching with React Server Components
Wrap CMS fetches with React's cache() to deduplicate requests within a single render:
import { cache } from 'react';import { createCmsClient } from '@kit/cms';export const getPost = cache(async (slug: string) => { const client = await createCmsClient(); return client.getContentItemBySlug({ slug, collection: 'posts', });});For page-level caching, use Next.js ISR:
// In your page componentexport const revalidate = 3600; // Revalidate every hourError Handling
import { createCmsClient } from '@kit/cms';async function fetchPosts() { try { const client = await createCmsClient(); const { items, total } = await client.getContentItems({ collection: 'posts', limit: 10, }); return { items, total }; } catch (error) { console.error('Failed to fetch posts:', error); // Return empty state or throw to error boundary return { items: [], total: 0 }; }}Common Pitfalls
- Missing
cache()wrapper: Withoutcache(), the same content might be fetched multiple times in a single render. Wrap reusable fetch functions. - Forgetting to check for null:
getContentItemBySlug()returnsundefinedif the item doesn't exist. Always check and handle the 404 case. - Fetching content in client components: The CMS client is server-only. Fetch content in Server Components or Server Actions, not in client components.
- Ignoring the
contentparameter: When listing items, setcontent: falseto skip fetching full content. This significantly improves performance for index pages. - Not handling pagination:
getContentItems()returnstotalfor building pagination. Don't fetch all items at once - uselimitandoffset.
Frequently Asked Questions
How do I fetch draft content for preview?
Can I filter by multiple categories?
How do I get related posts?
Is content automatically cached?
How do I search content?
Next: Custom CMS Client →