Розробка веб-сайту на Strapi CMS
Strapi — це Node.js headless CMS з автоматичною генерацією REST та GraphQL API з конфігурації content-type. Типи контенту описуються за допомогою JSON-схеми (у src/api/*/content-types/*.json), а зміни схеми через GUI зберігаються у коді. Придатна для проектів з частково технічними командами: розробники визначають структуру, редактори заповнюють контент.
Архітектура
Браузер / Мобільний додаток / Next.js
↕ REST API / GraphQL
Strapi (Node.js)
↕
PostgreSQL / MySQL / SQLite
↕
Cloudinary / S3 (медіа)
Strapi працює як окремий процес. Немає монолітної інтеграції з Next.js — лише HTTP-запити.
Встановлення
npx create-strapi-app@latest my-project --quickstart
# Quickstart: SQLite, без налаштування
# Або з PostgreSQL
npx create-strapi-app@latest my-project \
--dbclient=postgres \
--dbhost=localhost \
--dbport=5432 \
--dbname=strapi_db \
--dbusername=strapi \
--dbpassword=pass
cd my-project
npm run develop # режим розробки з гарячою перезавантаженням
# Admin: http://localhost:1337/admin
Типи контенту
Типи контенту створюються через Content-Type Builder в адміні або вручну через JSON:
// src/api/article/content-types/article/schema.json
{
"kind": "collectionType",
"collectionName": "articles",
"info": {
"singularName": "article",
"pluralName": "articles",
"displayName": "Стаття"
},
"attributes": {
"title": { "type": "string", "required": true },
"slug": { "type": "uid", "targetField": "title" },
"content": { "type": "richtext" },
"excerpt": { "type": "text", "maxLength": 500 },
"publishedAt": { "type": "datetime" },
"cover": { "type": "media", "multiple": false, "required": false, "allowedTypes": ["images"] },
"category": { "type": "relation", "relation": "manyToOne", "target": "api::category.category" },
"tags": { "type": "relation", "relation": "manyToMany", "target": "api::tag.tag" },
"author": { "type": "relation", "relation": "manyToOne", "target": "plugin::users-permissions.user" }
}
}
Типовий стек проекту
| Шар | Технологія |
|---|---|
| CMS | Strapi 5.x |
| Фронтенд | Next.js 14 / Nuxt 3 |
| База даних | PostgreSQL |
| Медіа | Cloudinary / AWS S3 |
| Деплой CMS | Railway / Render / VPS |
| Деплой фронту | Vercel / Netlify |
| Кеш | Redis (для production) |
REST API з коробки
# Отримати список статей (публічний, якщо налаштовані дозволи)
GET http://localhost:1337/api/articles?populate=cover,category,author
# Фільтрація
GET /api/articles?filters[category][slug][$eq]=tech&sort=publishedAt:desc&pagination[pageSize]=10
# Конкретний запис
GET /api/articles/123?populate=deep
# Пошук
GET /api/articles?filters[title][$containsi]=javascript
Інтеграція з Next.js
// lib/strapi.ts
const STRAPI_URL = process.env.STRAPI_URL || 'http://localhost:1337'
const API_TOKEN = process.env.STRAPI_API_TOKEN
export async function fetchStrapi<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`${STRAPI_URL}/api${endpoint}`, {
headers: {
Authorization: `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
next: { tags: [endpoint.split('/')[1]] }, // ISR тег
...options,
})
if (!response.ok) {
throw new Error(`Strapi API error: ${response.status}`)
}
const data = await response.json()
return data
}
// Використання
const { data: articles } = await fetchStrapi<{ data: Article[] }>(
'/articles?populate=cover,category&sort=publishedAt:desc&pagination[pageSize]=10'
)
Вебхуки для ISR
// app/api/revalidate/strapi/route.ts
import { revalidateTag } from 'next/cache'
import { NextRequest, NextResponse } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.json()
// Strapi відправляє: { event, uid, model, entry }
const { model } = body
// Інвалідувати кеш за моделлю
revalidateTag(model)
return NextResponse.json({ revalidated: true })
}
У Strapi адміні: Settings → Webhooks → Add new webhook → URL вашого Next.js ендпоінту.
Особливості розробки
Формат відповіді Strapi: усі дані обгортаються в { data: { id, attributes: {...} } }. У Strapi 5 це змінилося — дані повертаються плоско.
Populate: за замовчуванням зв'язки не заповнюються. Ви повинні явно указати ?populate=* або ?populate[category][populate][0]=icon.
Чорновики: вбудована система Draft/Publish. ?publicationState=live — тільки опубліковані, ?publicationState=preview + API токен — чорновики.
Терміни
Базовий веб-сайт з 4–6 типами контенту, налаштуванням дозволів та інтеграцією Next.js займає 2–3 тижні. Складні проекти з користувацькими контролерами, плагінами та багатомовною підтримкою займають 4–6 тижнів.







