Headless CMS is a content management system without a frontend. It provides an API for fetching content, and you build your UI on React.
Why it matters: Headless CMS separates content management from content presentation. Content editors manage blog posts, product pages, and marketing content in a user-friendly dashboard, while developers build fast, custom React frontends. This decoupling means you can change the frontend without affecting content and vice versa.
How the integration works:
Example with Contentful:
1import { createClient } from "contentful";23// Client4const client = createClient({5 space: process.env.CONTENTFUL_SPACE_ID,6 accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,7});89// Server component (Next.js)10async function BlogPost({ slug }) {11 const entries = await client.getEntries({12 content_type: "blogPost",13 "fields.slug": slug,14 });1516 const post = entries.items[0].fields;1718 return (19 <article>20 <h1>{post.title}</h1>21 <time>{new Date(post.date).toLocaleDateString()}</time>22 <div>{post.content}</div>23 </article>24 );25}
Example with Strapi (self-hosted):
1// Custom hook for Strapi API2function useStrapi(collection, params = {}) {3 const query = new URLSearchParams(params).toString();4 const { data, isLoading, error } = useQuery({5 queryKey: [collection, params],6 queryFn: () =>7 fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/${collection}?${query}`)8 .then(res => res.json()),9 });10 return { data: data?.data, isLoading, error };11}1213// Usage14function Articles() {15 const { data: articles, isLoading } = useStrapi("articles", {16 "populate": "*",17 "sort": "createdAt:desc",18 });1920 if (isLoading) return <Spinner />;21 return articles.map(a => <ArticleCard key={a.id} article={a} />);22}
Key considerations:
Popular headless CMS: