Интеграция CMS Directus для управления контентом
Directus — headless CMS и Data Platform с открытым исходным кодом. Ключевое отличие от Strapi и других: Directus работает поверх существующей базы данных без изменения схемы. Если уже есть PostgreSQL с таблицами — Directus подключается к ней и сразу предоставляет API и admin-панель.
Принцип работы
Directus не создаёт свои таблицы для пользовательского контента — он читает структуру существующих таблиц через information_schema и строит поверх них:
- Административный интерфейс для CRUD-операций
- REST API (
/items/{collection}) - GraphQL API (
/graphql) - Систему прав доступа
- Систему вебхуков и автоматизаций (Flows)
Собственные таблицы Directus (с префиксом directus_) — только для метаданных системы: пользователи, роли, права, файлы, вебхуки.
Установка через Docker
# docker-compose.yml
services:
directus:
image: directus/directus:latest
ports:
- "8055:8055"
environment:
SECRET: "replace-with-random-string"
DB_CLIENT: "pg"
DB_HOST: "postgres"
DB_PORT: "5432"
DB_DATABASE: "directus"
DB_USER: "directus"
DB_PASSWORD: "directus"
ADMIN_EMAIL: "[email protected]"
ADMIN_PASSWORD: "strongpassword"
STORAGE_LOCATIONS: "local"
STORAGE_LOCAL_DRIVER: "local"
STORAGE_LOCAL_ROOT: "/directus/uploads"
volumes:
- directus-uploads:/directus/uploads
postgres:
image: postgres:16
environment:
POSTGRES_DB: directus
POSTGRES_USER: directus
POSTGRES_PASSWORD: directus
volumes:
- pgdata:/var/lib/postgresql/data
docker compose up -d
# Admin панель: http://localhost:8055
Создание коллекций
Через UI: Settings → Data Model → Create Collection. Directus создаёт соответствующую таблицу в БД.
Или программно через API:
# Создать коллекцию через API
curl -X POST http://localhost:8055/collections \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collection": "articles",
"fields": [
{ "field": "id", "type": "integer", "meta": { "hidden": true }, "schema": { "is_primary_key": true, "has_auto_increment": true } },
{ "field": "title", "type": "string", "meta": { "required": true } },
{ "field": "slug", "type": "string", "meta": { "unique": true } },
{ "field": "content", "type": "text", "meta": { "interface": "input-rich-text-html" } },
{ "field": "status", "type": "string", "meta": { "interface": "select-dropdown", "options": { "choices": [{"text":"Draft","value":"draft"},{"text":"Published","value":"published"}] } } },
{ "field": "date_published", "type": "timestamp" }
]
}'
REST API
# Получить список статей (только опубликованных)
GET /items/articles?filter[status][_eq]=published&sort[]=-date_published&limit=10
# С populate связанных полей
GET /items/articles?fields=*,author.name,cover.filename_disk
# Конкретная статья по slug
GET /items/articles?filter[slug][_eq]=my-article&fields=*,tags.*
Ответ консистентен для всех коллекций:
{
"data": [
{
"id": 1,
"title": "My Article",
"slug": "my-article",
"status": "published",
"author": { "name": "Ivan Petrov" }
}
]
}
GraphQL
query Articles($status: String!) {
articles(filter: { status: { _eq: $status } }, sort: ["-date_published"], limit: 10) {
id
title
slug
content
cover {
id
filename_disk
}
author {
first_name
last_name
}
}
}
Система прав (Access Control)
Directus работает с публичной ролью (анонимные запросы) и кастомными ролями:
Settings → Access Control → Public role
→ articles: Read (filter: status=published)
→ articles: No Create/Update/Delete
Settings → Access Control → Create role «Editor»
→ articles: Full CRUD
→ directus_users: Read (только свой профиль)
Политики на уровне строк задаются через фильтры в настройках роли: редактор видит только свои статьи (user_created = $CURRENT_USER).
Flows (автоматизации)
Flows — встроенный инструмент автоматизации без кода. Триггеры: создание/обновление записи, webhook, cron, ручной запуск. Действия: HTTP-запрос, email, скрипт, операции с базой.
Trigger: Items Created (articles)
→ Condition: status == "published"
→ Action: Webhook POST https://vercel.com/api/deploy-hook/xxx
(ребилд Next.js при публикации статьи)
Кастомные расширения
// extensions/hooks/article-slug/index.js
export default ({ action }) => {
action('items.create', ({ collection, payload }, { schema }) => {
if (collection === 'articles' && !payload.slug) {
payload.slug = slugify(payload.title);
}
});
};
Типы расширений: hooks, endpoints, modules (добавляют страницы в admin), displays (кастомные отображения полей), interfaces (кастомные редакторы полей).
Интеграция с фронтом
Directus SDK:
import { createDirectus, rest, readItems } from '@directus/sdk';
const client = createDirectus('https://cms.example.com').with(rest());
const articles = await client.request(
readItems('articles', {
filter: { status: { _eq: 'published' } },
sort: ['-date_published'],
fields: ['id', 'title', 'slug', 'cover.*'],
limit: 10,
})
);
Сроки
Установка, подключение к БД, настройка коллекций, API, права доступа, деплой — 3–5 рабочих дней. Кастомные расширения, Flows, интеграция с внешними сервисами — +3–5 дней.







