Інтеграція CMS Contentful для управління контентом

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція CMS Contentful для управління контентом
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція CMS Contentful для управління контентом

Contentful — хмарна headless CMS з потужною екосистемою SDK, розвинутим API та вбудованою багатомовною підтримкою. Контент зберігається в інфраструктурі Contentful, доступ через Delivery API (публічний, кешований) та Management API (запис, приватний).

Структура Contentful

  • Space — робочий простір, аналог проекту
  • Environment — середовища всередину Space (master, staging, sandbox)
  • Content Type — схема типу запису: поля, валідації
  • Entry — конкретна запис певного Content Type
  • Asset — медіафайл (зображення, відео, PDF)

Кожна Entry та Asset має унікальний ID, незалежний від мови. Локалізовані поля зберігаються як словник {locale: value} всередину однієї записи.

Створення Content Type через API

import Contentful from 'contentful-management';

const client = Contentful.createClient({ accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN });
const space = await client.getSpace(process.env.CONTENTFUL_SPACE_ID);
const env = await space.getEnvironment('master');

const contentType = await env.createContentTypeWithId('article', {
    name: 'Article',
    displayField: 'title',
    fields: [
        { id: 'title',       name: 'Title',        type: 'Symbol',   required: true, localized: true },
        { id: 'slug',        name: 'Slug',         type: 'Symbol',   required: true, localized: false },
        { id: 'body',        name: 'Body',         type: 'RichText', required: false, localized: true },
        { id: 'cover',       name: 'Cover Image',  type: 'Link', linkType: 'Asset' },
        { id: 'author',      name: 'Author',       type: 'Link', linkType: 'Entry',
          validations: [{ linkContentType: ['author'] }] },
        { id: 'tags',        name: 'Tags',         type: 'Array',    items: { type: 'Symbol' } },
        { id: 'publishedAt', name: 'Published At', type: 'Date' },
    ],
});

await contentType.publish();

Delivery API (читання контенту)

import { createClient } from 'contentful';

const client = createClient({
    space:        process.env.CONTENTFUL_SPACE_ID!,
    accessToken:  process.env.CONTENTFUL_ACCESS_TOKEN!,  // Delivery API token
    environment:  'master',
});

// Отримати список статей
const response = await client.getEntries<ArticleFields>({
    content_type: 'article',
    'fields.publishedAt[lte]': new Date().toISOString(),
    order: ['-fields.publishedAt'],
    limit: 10,
    locale: 'uk',
    include: 2,  // глибина populate (автор, обкладинка)
});

response.items.forEach(entry => {
    console.log(entry.fields.title);           // string
    console.log(entry.fields.cover?.fields);   // Asset fields
});

// Конкретна запис за slug
const entries = await client.getEntries({
    content_type: 'article',
    'fields.slug': 'my-article',
    locale: 'uk',
    limit: 1,
});
const article = entries.items[0];

TypeScript-типи з Content Types

npx @contentful/cli@latest content-type export \
    --space-id $CONTENTFUL_SPACE_ID \
    --output-file src/types/contentful.d.ts

Або через cf-content-types-generator:

npx cf-content-types-generator -s $SPACE_ID -t $ACCESS_TOKEN -o src/types/

Rich Text рендеринг

Contentful Rich Text зберігається як JSON AST, не HTML. Для рендеринга:

import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
import { BLOCKS, INLINES } from '@contentful/rich-text-types';

const options = {
    renderNode: {
        [BLOCKS.EMBEDDED_ASSET]: (node) => {
            const { url, title } = node.data.target.fields.file;
            return <img src={`https:${url}`} alt={title} />;
        },
        [INLINES.HYPERLINK]: (node, children) => (
            <a href={node.data.uri} target="_blank" rel="noopener noreferrer">
                {children}
            </a>
        ),
        [BLOCKS.EMBEDDED_ENTRY]: (node) => {
            const entry = node.data.target;
            if (entry.sys.contentType.sys.id === 'codeBlock') {
                return <pre><code>{entry.fields.code}</code></pre>;
            }
        },
    },
};

<div>{documentToReactComponents(article.fields.body, options)}</div>

Content Preview API

Для попереду чорновиків використовується Preview API з окремим токеном:

const previewClient = createClient({
    space:       process.env.CONTENTFUL_SPACE_ID!,
    accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,  // Preview API token
    host:        'preview.contentful.com',               // не cdn.contentful.com
});

Webhooks для ISR

Space Settings → Webhooks → Add Webhook
Name: Next.js Revalidation
URL: https://example.com/api/revalidate
Events: Entry.publish, Entry.unpublish, Asset.publish
// app/api/revalidate/route.ts
export async function POST(req: Request) {
    const body = await req.json();
    const contentType = body.sys?.contentType?.sys?.id;

    if (contentType === 'article') {
        await revalidatePath('/blog');
        await revalidatePath(`/blog/${body.fields?.slug?.['en-US']}`);
    }

    return Response.json({ revalidated: true });
}

Багатомовність

Contentful підтримує локалізацію на рівні полів. Поле localized: true в схемі → при запиті до API додати locale=uk, locale=en.

// Отримати запис для всіх локалей одночасно
const entry = await client.getEntry(entryId, { locale: '*' });
// entry.fields.title = { 'ru': 'Заголовок', 'en': 'Title', 'de': 'Titel' }

Обмеження та вартість

Безплатний тариф Contentful (Community): 1 Space, до 25 000 записів, 2 ролі, 2 мови. Для production з командою та кількома середовищами (staging + production) потрібен платний тариф.

Альтернатива при бюджетних обмеженнях: Directus (self-hosted) або Sanity (щедріший free tier).

Терміни

Настройка Space, Content Types, SDK, інтеграція з Next.js, webhooks для ISR — 3–5 робочих днів. Багатомовність, Preview Mode, CI/CD з міграціями схеми — +2–3 дня.