Монолітний WordPress гальмує при 5000 публікаціях? В адмінці кожен клік триває 3 секунди? Редактори втрачають терпіння, а PHP-шаблони не дають реалізувати сучасний дизайн. Вихід — headless-архітектура. Ми допомагаємо мігрувати сайти під ключ, зберігаючи SEO-позиції та скорочуючи Time to Market. На фронтенді використовуємо Next.js або Nuxt — SSR/SSG, ліниве завантаження, оптимізація Core Web Vitals. Контент-менеджери працюють у зручному інтерфейсі, а розробники вільні обирати стек.
Headless CMS відокремлює управління контентом від представлення. Міграція потребує ретельного планування: інвентаризації контенту, мапінгу типів записів, налаштування API та періоду паралельної роботи.
Оцінка до початку
Перед вибором цільової CMS проводимо аудит: інвентаризуємо кастомні типи записів, поля ACF, використовувані плагіни (WooCommerce, Events Calendar), рівень підготовки контент-команди, бюджет на ліцензії та вимоги до чернеток і preview. На основі цих даних обираємо платформу: Strapi для self-hosted, Contentful для SaaS з потужним редактором, Sanity для гнучкої схеми. Після міграції витрати на хостинг та ліцензії знижуються до 60% — середня економія складає від 2000$ до 5000$ на рік.
Як обрати Headless CMS?
Порівняємо популярні платформи:
| Критерій | Contentful | Sanity | Strapi | KeystoneJS |
|---|---|---|---|---|
| Хостинг | SaaS | SaaS/Self | Self | Self |
| Тариф | Enterprise | Стартовий | Open Source | Open Source |
| Редактор | Хороший | Відмінний | Базовий | Базовий |
| API | REST + GraphQL | GROQ + GraphQL | REST + GraphQL | GraphQL |
| Медіа | CDN включено | CDN включено | Своє сховище | Своє |
Strapi перевершує KeystoneJS за розміром спільноти в 3 рази та за кількістю готових плагінів. GraphQL API дозволяє обирати тільки потрібні поля, скорочуючи обсяг переданих даних у 2-3 рази порівняно з REST. Вартість ліцензій headless CMS в середньому в 2-3 рази нижча, ніж у корпоративних рішень. На Next.js з headless CMS LCP у 2-3 рази нижчий, ніж на класичному WordPress, що підтверджують виміри Core Web Vitals.
Етап 1: Аудит і мапінг контенту (1–2 тижні)
Інвентаризація існуючого контенту:
# Експорт з WordPress через WP-CLI
wp export --post_type=post,page,product --status=publish --path=/var/www/html
# Аналіз ACF-полів
wp acf field-group export --group_id=all --output=json > acf-fields.json
# Статистика за типами
wp post list --post_type=post --format=count
wp post list --post_type=page --format=count
Мапінг WordPress → цільова CMS:
# mapping.yaml
wordpress_types:
post:
target: blogPost
fields:
post_title: title
post_content: body (RichText)
post_excerpt: excerpt
post_date: publishedAt
_thumbnail_id: featuredImage (Asset)
categories: categories (Reference[])
tags: tags (Reference[])
acf.seo_title: seoTitle
acf.seo_description: seoDescription
product:
target: product
fields:
post_title: name
_regular_price: price (Number)
_stock_qty: stock (Number)
product_cat: categories
acf.gallery: gallery (Asset[])
Як перенести контент без втрат?
Для цього пишемо скрипти на TypeScript. Вони через WP REST API отримують записи, медіа та зв'язки, а потім відправляють їх у нову CMS через Management API. Код обробляє rate limiting, перетворює HTML на Markdown та завантажує зображення.
// scripts/migrate-from-wp.ts
import axios from 'axios';
import * as contentful from 'contentful-management';
import TurndownService from 'turndown';
const turndown = new TurndownService({ headingStyle: 'atx' });
const cmaClient = contentful.createClient({ accessToken: process.env.CMA_TOKEN! });
async function migratePosts() {
const space = await cmaClient.getSpace(process.env.SPACE_ID!);
const env = await space.getEnvironment('master');
let page = 1;
while (true) {
const { data: posts } = await axios.get(
`${WP_URL}/wp-json/wp/v2/posts?per_page=100&page=${page}&_embed`
);
if (!posts.length) break;
for (const wpPost of posts) {
await migratePost(env, wpPost);
await delay(200);
}
page++;
}
}
async function migratePost(env: any, wpPost: any) {
const featuredImageUrl = wpPost._embedded?.['wp:featuredmedia']?.[0]?.source_url;
let imageAsset;
if (featuredImageUrl) {
imageAsset = await uploadAsset(env, featuredImageUrl, wpPost.title.rendered);
}
const entry = await env.createEntry('blogPost', {
fields: {
title: { 'en-US': wpPost.title.rendered },
slug: { 'en-US': wpPost.slug },
body: { 'en-US': turndown.turndown(wpPost.content.rendered) },
excerpt: { 'en-US': wpPost.excerpt.rendered.replace(/<[^>]*>/g, '') },
publishedAt: { 'en-US': wpPost.date },
...(imageAsset && {
featuredImage: { 'en-US': { sys: { type: 'Link', linkType: 'Asset', id: imageAsset.sys.id } } },
}),
},
});
await entry.publish();
console.log(`Migrated: ${wpPost.title.rendered}`);
}
Етап 2: Налаштування нової CMS (1 тиждень)
Створення Content Types у цільовій CMS точно за мапінгом. Налаштування валідацій, локалізації, ролей. Цей етап робимо паралельно з аудитом.
Етап 3: Скрипт міграції (1–2 тижні)
Код вище — приклад для Contentful. Аналогічні скрипти пишемо для Strapi через його REST API або для Sanity через mutation API.
Етап 4: Міграція медіафайлів
// Завантажуємо та завантажуємо всі медіафайли WP
async function migrateMedia() {
const { data: media } = await axios.get(`${WP_URL}/wp-json/wp/v2/media?per_page=100`);
for (const item of media) {
const asset = await env.createAsset({
fields: {
title: { 'en-US': item.title.rendered },
description: { 'en-US': item.alt_text },
file: { 'en-US': {
contentType: item.mime_type,
fileName: path.basename(item.source_url),
upload: item.source_url,
}},
},
});
await asset.processForAllLocales();
await asset.publish();
mediaIdMap[item.id] = asset.sys.id;
}
}
Етап 5: Паралельний запуск та перемикання
- Запустити новий фронтенд на staging з реальними даними.
- Провести редизайн-рев'ю з контент-командою.
- Налаштувати автоматичну синхронізацію WordPress → нова CMS на період переходу.
- DNS-перемикання в low-traffic період.
- Відключити WordPress через 2–4 тижні після стабілізації.
Строки типової міграції
| Етап | Невеликий сайт (<500 записів) | Середній (500–5000) | Великий (5000+) |
|---|---|---|---|
| Аудит і мапінг | 1 тиждень | 1–2 тижні | 2–4 тижні |
| Налаштування CMS | 3–5 днів | 1 тиждень | 1–2 тижні |
| Скрипт міграції | 1 тиждень | 1–2 тижні | 2–4 тижні |
| Тестування | 3–5 днів | 1 тиждень | 2 тижні |
| Запуск | 1 день | 1–2 дні | 1 тиждень |
| Всього | 4–6 тижнів | 6–10 тижнів | 3–5 місяців |
Типові помилки при міграції
- Простій сайту через відсутність паралельної роботи.
- Втрата зв'язків між записами через некоректний мапінг.
- Падіння продуктивності через неоптимізовані GraphQL-запити.
- Некоректна обробка медіафайлів (дублікати, втрата alt-тегів).
Усі ці ризики ми закриваємо на етапі тестування.
Що входить у роботу?
- Аудит поточної архітектури та мапінг контенту.
- Налаштування цільової CMS (Content Types, ролі, локалізація).
- Скрипти міграції контенту та медіа.
- Налаштування автоматичної синхронізації на перехідний період.
- Розробка фронтенду на Next.js/Nuxt з урахуванням Core Web Vitals.
- DNS-перемикання та пост-міграційна підтримка.
- Документація та навчання контент-команди.
Гарантуємо збереження SEO-позицій за умови виконання наших рекомендацій. Оцінимо ваш проєкт за 2 дні. Зв'яжіться з нами для попереднього аудиту. Отримайте консультацію — ми підберемо оптимальну архітектуру та строки.







