CMS Integration

The CMS library in Makerkit abstracts content management from specific implementations. Use Keystatic, WordPress, or build your own CMS client.

Makerkit's CMS interface lets you fetch blog posts, documentation, and custom content from any backend - Keystatic, WordPress, or your own API - using a single, consistent API. Switch CMS providers without changing your application code. The abstraction handles collections, pagination, filtering, and content rendering while you focus on building features.

The CMS interface is a provider-agnostic abstraction layer that decouples content fetching from specific CMS implementations, enabling you to swap backends without modifying application code.

  • Use Keystatic when: you want file-based content with Git versioning, zero external dependencies, and a built-in admin UI.
  • Use WordPress when: you have existing WordPress content, need a familiar editing experience, or require advanced plugins.
  • Build a custom client when: you're using Sanity, Strapi, Payload CMS, or any headless CMS not included by default.

If unsure: start with Keystatic in local mode - it requires no setup and works immediately.

Available CMS Implementations

CMSBest ForData StorageSetup Complexity
KeystaticSolo developers, Git workflowsLocal files or GitHubMinimal
WordPressTeams with existing WP contentWordPress databaseModerate
Custom ClientAny headless CMSYour APIVariable

Quick Start

The CMS client is configured via environment variable:

# Default - Keystatic with local storage
CMS_CLIENT=keystatic
# Or use WordPress
CMS_CLIENT=wordpress

Fetch content using the unified API:

import { createCmsClient } from '@kit/cms';
async function BlogPage() {
const client = await createCmsClient();
const { items } = await client.getContentItems({
collection: 'posts',
limit: 10,
});
return (
<ul>
{items.map((post) => (
<li key={post.slug}>{post.title}</li>
))}
</ul>
);
}

The same code works regardless of which CMS backend you configure.

Architecture

┌─────────────────────────────────────────────────────┐
│ Your Application │
│ (Blog pages, Documentation, Custom content pages) │
└─────────────────────┬───────────────────────────────┘
│ createCmsClient()
┌─────────────────────────────────────────────────────┐
│ CMS Interface (@kit/cms) │
│ getContentItems() | getContentItemBySlug() │
│ getCategories() | getTags() │
└─────────────────────┬───────────────────────────────┘
│ CMS_CLIENT env var
┌───────────┼───────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Keystatic│ │WordPress│ │ Custom │
│ Client │ │ Client │ │ Client │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
▼ ▼ ▼
Local/GitHub WP REST API Your API

Topics

  1. Keystatic - File-based CMS with GitHub sync
  2. WordPress - Traditional CMS via REST API
  3. CMS API Reference - Full API documentation
  4. Custom CMS Client - Build your own integration

Common Pitfalls

  • Using local mode with edge rendering: Keystatic's local mode reads from the filesystem, which doesn't work on edge runtimes (Cloudflare Workers, Vercel Edge). Switch to GitHub mode or WordPress for edge deployments.
  • Forgetting to create collections: The CMS API expects collections like posts, documentation, and changelog to exist. Keystatic creates these automatically; WordPress requires manual category setup.
  • Caching content incorrectly: CMS content should be cached at the page level using Next.js ISR, not at the client level. Use revalidate in your page exports.
  • Mixing CMS implementations: Each deployment should use one CMS backend. Don't try to combine Keystatic and WordPress in the same environment.

Frequently Asked Questions

Can I use a different CMS like Sanity or Contentful?
Yes. Create a custom CMS client by extending the CmsClient abstract class. Implement the required methods to fetch content from your CMS API.
How do I switch from Keystatic to WordPress?
Change the CMS_CLIENT environment variable to 'wordpress', configure WORDPRESS_API_URL, and ensure your WordPress instance has matching content structure (posts, pages, categories).
Does the CMS support multiple languages?
Yes. Pass the language parameter to getContentItems(). Implementation varies by CMS - Keystatic uses folder structure, WordPress uses tags.
Can I use the CMS for custom content types?
Yes. Create custom collections in your CMS configuration. The API supports any collection name - not just posts and documentation.
Is content cached automatically?
The CMS client doesn't cache internally. Use React's cache() function or Next.js page-level caching (revalidate) to avoid redundant fetches.

Next: Keystatic →