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
| CMS | Best For | Data Storage | Setup Complexity |
|---|---|---|---|
| Keystatic | Solo developers, Git workflows | Local files or GitHub | Minimal |
| WordPress | Teams with existing WP content | WordPress database | Moderate |
| Custom Client | Any headless CMS | Your API | Variable |
Quick Start
The CMS client is configured via environment variable:
# Default - Keystatic with local storageCMS_CLIENT=keystatic# Or use WordPressCMS_CLIENT=wordpressFetch 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 APITopics
- Keystatic - File-based CMS with GitHub sync
- WordPress - Traditional CMS via REST API
- CMS API Reference - Full API documentation
- 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, andchangelogto 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
revalidatein 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?
How do I switch from Keystatic to WordPress?
Does the CMS support multiple languages?
Can I use the CMS for custom content types?
Is content cached automatically?
Next: Keystatic →