Розробка сайту на CMS Contentful
Contentful — одна з перших і найбільш зрілих headless CMS на ринку. Повністю SaaS: зберігання контенту, CDN, API у хмарі Contentful. Контентна модель створюється через GUI або API. REST API (Content Delivery API, Content Management API) та GraphQL з коробки.
Архітектура
Contentful Studio (Web)
↕ CMA (Content Management API)
Content Lake (Contentful)
↕ CDA (Content Delivery API) / GraphQL
Next.js / Nuxt / Remix / Mobile App
↕ Contentful Image API (CDN)
Установка
npm install contentful
// lib/contentful.ts
import { createClient } from 'contentful'
export const contentfulClient = createClient({
space: process.env.CONTENTFUL_SPACE_ID!,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
environment: 'master',
})
Інтеграція Next.js
// app/blog/[slug]/page.tsx
import { contentfulClient } from '@/lib/contentful'
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'
import { notFound } from 'next/navigation'
export default async function BlogPostPage({ params }: { params: { slug: string } }) {
const entries = await contentfulClient.getEntries({
content_type: 'blogPost',
'fields.slug': params.slug,
limit: 1,
})
const post = entries.items[0]
if (!post) notFound()
return (
<article>
<h1>{post.fields.title}</h1>
<div>{documentToReactComponents(post.fields.content)}</div>
</article>
)
}
export async function generateStaticParams() {
const entries = await contentfulClient.getEntries({
content_type: 'blogPost',
select: ['fields.slug'],
limit: 1000,
})
return entries.items.map(entry => ({ slug: entry.fields.slug }))
}
export const revalidate = 3600
GraphQL API
const POSTS_QUERY = `
query GetPosts($limit: Int) {
blogPostCollection(limit: $limit, order: publishedAt_DESC) {
items { title, slug, excerpt, publishedAt }
}
}
`
const response = await fetch(`https://graphql.contentful.com/content/v1/spaces/${SPACE_ID}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${ACCESS_TOKEN}`,
},
body: JSON.stringify({ query: POSTS_QUERY }),
})
const { data } = await response.json()
Вебхуки для ISR
У Contentful: Settings → Webhooks → Add Webhook:
// app/api/revalidate/contentful/route.ts
export async function POST(req: Request) {
const secret = req.headers.get('x-contentful-webhook-secret')
if (secret !== process.env.CONTENTFUL_WEBHOOK_SECRET) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await req.json()
revalidateTag('contentful')
return Response.json({ revalidated: true })
}
Порівняння
| Критерій | Contentful | Sanity | Strapi | Directus |
|---|---|---|---|---|
| Hosting | Тільки SaaS | Тільки SaaS | Self-hosted / Cloud | Self-hosted / Cloud |
| Rich text | Contentful RT | Portable Text | Markdown | JSON |
| Real-time | Ні | Так | Ні | Так |
Терміни
Базовий сайт з 3–5 типами контенту та Next.js — 1,5–2 тижні. Складний мультимовний проект з Preview Mode та GraphQL — 3–4 тижні.







