Некоторое время назад в одной заметной на российском рынке публичной компании, в которой я работал, встал вопрос об использовании headless cms. Среди множества реализаций нужно было выбрать одну. Это рассказ о том, как я формировал критерии выбора, как анализировал cms-ки, и как этот анализ привел меня к мысли, что нужно писать свою. Обзор 14 headless cms под катом.
Хоть термин и не нов, почему-то эта тема в русскоязычном интернете освещена крайне мало. Итак, согласно википедии:
Другими словами headless cms — это концепция, этакий специальный тип cms-ок, согласно которой cms отвечает только за управление “чистым” контентом. Это позволяет отделить слой данных, который управляется в cms, от слоя отображения, который управляется клиентским приложением. Контент распространяется в универсальном формате, обычно в JSON, это и дает возможность управлять одновременно веб-сайтом, мобильным приложением и любыми устройствами подключенными к интернету.
Подробнее о плюсах и минусах такой концепции можно почитать в этой статье, или этой, или опять же в статье на википедии.
Чтобы определить критерии поиска и понять, какая headless cms лучше других, мне предстояло ответить на вопрос — лучшая в чем? Какие именно задачи она должна решать и как?
Чтобы продемонстрировать мой тогдашний ход мыслей, я придумал типовую задачу и решил ее при помощи одной из headless cms. И хоть в действительности все было чуть по другому, такой формат повествования лаконичней отражает суть и лучше раскрывает тему headless cms.
Итак, представим, что в разработку приходит задача. На сайте нужно реализовать новый раздел, на котором пользователи будут читать обзоры к фильмам.
Условия такие:
Это требования, которые поступили от внутреннего заказчика. Со стороны разработки есть свое техническое видение на реализацию, а именно:
Хорошо, с задачей все ясно. Перехожу к решению.
Буду использовать Any JSON CMS, это одна из headless cms. Отмечу, что на данный момент она не удовлетворяет всем требованиям описанным выше. Например, контент-менеджер не сможет посмотреть в тестовом окружении, как будут выглядеть правки. Однако, все достоинства и недостатки будут видны позже. Сейчас же я стремлюсь “пощупать” типовой сценарий работы с любой headless cms.
Первое, что нужно сделать — описать модели. Модель отвечает на вопрос, как должна выглядеть контентная сущность? Какая у нее структура? По сути это протокол взаимодействия между cms и клиентским приложением. В нашем случае — обзор к фильму — объект содержит:
В виде JSON Schema модель обзора выглядит так:
Также нужно реализовать feature toggle, модель в виде JSON Schema выглядит так:
Когда есть понимание, как должны выглядеть модели, можно создавать их в Any JSON CMS.
Тут же создаю контентные сущности, т.е. сам контент, на основе моделей. Один фиктивный обзор и feature toggle сущность.
Для интеграции клиентского приложения с cms потребуется API key. Генерирую его в соответствующем разделе cms.
Теперь все готово для реализации функционала в клиентском приложении и интеграции с cms. Клиентское приложение может быть любым — сайт или мобильное приложение, или и то, и другое, написанное на чем угодно. В качестве примера я реализую функционал на сайте SPA на React. По сути мы забираем данные с уже известной, фиксированной структурой из cms и отображаем ее так, как хотим.
Все. Теперь контент-менеджер может спокойно управлять обзорами, а еще появилась возможность включать и отключать функционал при помощи feature toggle.
Выводить обзоры к фильмам — это простой пример, я намеренно его привел, чтобы не утонуть в деталях, а лишь продемонстрировать принцип. В действительности же фичи могут быть на порядок сложнее. Это могут быть элементы интерфейса, каталоги товаров, сложные виджеты, лендинги, генераторы форм, посты и пр. Также, в этом примере cms только распространяет информацию, однако большинство headless cms предоставляют CRUD API, что дает возможность, например, обрабатывать формы, да и вообще манипулировать сущностями, как угодно. В общем, задумка headless cms как раз в том, чтобы предоставить свободу и удобство в реализации сколь угодно сложного протокола, чтобы передать управление в cms чего угодно и так, как требуется.
После того, как у меня появилось понимание, какие задачи будут решаться при помощи headless cms и как именно, я выделил критерии и начал изучать системы. Сейчас согласно сайту headlesscms.org существует 54 cms. Проанализировать их все — довольно трудоемкий процесс, поэтому я выделил 14 наиболее популярных, заметных и обсуждаемых систем: Any JSON CMS, Contentful, Strapi, GraphCMS, Squidex, Butter CMS, Cloud CMS, Сockpit, Cosmic JS, Directus, Kentico Cloud, Netlify CMS, Prismic, Ghost.
Результаты удобнее изучать в виде таблицы. Но продублирую и здесь.
По большому счёту от headless cms я ожидал увидеть две основные вещи: свободу в создании моделей, благодаря чему можно реализовать любой протокол, и git подобную систему контроля версий, чтобы можно было прозрачно управлять всеми изменениями.
И меня ждало легкое разочарование. Хотя с большинством из этих систем можно работать, они обладают рядом неприятных для меня недостатков. Это, конечно, не значит, что системы плохие, это лишь означает, что они не удовлетворили мои ожидания, а мои ожидания — это мои проблемы. Озвучу их:
К сожалению, когда я работал в той публичной компании, мы так и не смогли взять ни одну из этих систем. Лучше всего под наши потребности подходила Cloud CMS, но и цена на нее кусалась.
Вот так этот анализ и привел меня к мысли, что нужно писать свою headless cms. Вы ее уже видели, на ее примере была демонстрация решения задачи. Она называется Any JSON CMS.
Основная ее цель — предоставить свободу в создании сколь угодно сложных моделей и контролировать все изменения при помощи git подобной системы. Сейчас реализовано далеко не все, что хотелось бы, он основной “посыл” уже есть.
Что такое headless CMS?
Хоть термин и не нов, почему-то эта тема в русскоязычном интернете освещена крайне мало. Итак, согласно википедии:
A headless content management system, or headless CMS, is a back-end only content management system (CMS) built from the ground up as a content repository that makes content accessible via a RESTful API for display on any device.
Headless система управления контентом, или headless CMS — это серверная система управления контентом (CMS), которая изначально является хранилищем контента и предоставляет доступ к контенту через RESTful API для отображения на любом девайсе.
Другими словами headless cms — это концепция, этакий специальный тип cms-ок, согласно которой cms отвечает только за управление “чистым” контентом. Это позволяет отделить слой данных, который управляется в cms, от слоя отображения, который управляется клиентским приложением. Контент распространяется в универсальном формате, обычно в JSON, это и дает возможность управлять одновременно веб-сайтом, мобильным приложением и любыми устройствами подключенными к интернету.
Подробнее о плюсах и минусах такой концепции можно почитать в этой статье, или этой, или опять же в статье на википедии.
Погружение в контекст
Чтобы определить критерии поиска и понять, какая headless cms лучше других, мне предстояло ответить на вопрос — лучшая в чем? Какие именно задачи она должна решать и как?
Чтобы продемонстрировать мой тогдашний ход мыслей, я придумал типовую задачу и решил ее при помощи одной из headless cms. И хоть в действительности все было чуть по другому, такой формат повествования лаконичней отражает суть и лучше раскрывает тему headless cms.
Итак, представим, что в разработку приходит задача. На сайте нужно реализовать новый раздел, на котором пользователи будут читать обзоры к фильмам.
Условия такие:
- на данный момент нужно выводить только название фильма, постер, имя режиссера и текст обзора, но в будущем структура усложнится, появится информация о сборах, актерах и и т.д.;
- добавлять и изменять обзоры должен будет человек без технического бэкграунда — контент-менеджер, и для этого ресурс разработки задействоваться не должен;
- этот функционал должен быть отключаем, т.е. нужно реализовать feature toggle;
- перед публикацией контента, контент-менеджер должен иметь возможность посмотреть в тестовом окружении, как будут выглядеть правки.
Это требования, которые поступили от внутреннего заказчика. Со стороны разработки есть свое техническое видение на реализацию, а именно:
- заказчик не должен иметь возможность прострелить себе колено, т.е. контент-менеджер не должен ничего сломать, даже если захочет. Он должен редактировать только то, что предусмотрели разработчики;
- должна быть возможность управлять версиями и откатиться в случае чего;
- неизвестно, какой дополнительный функционал появится в будущем, а это означает, что усложнять или менять раздел должно быть легко;
- со стороны безопасности: система должна быть на нашем сервере, а не в чужом облаке, т.е. должна быть возможность развернуть on-premises.
Хорошо, с задачей все ясно. Перехожу к решению.
Буду использовать Any JSON CMS, это одна из headless cms. Отмечу, что на данный момент она не удовлетворяет всем требованиям описанным выше. Например, контент-менеджер не сможет посмотреть в тестовом окружении, как будут выглядеть правки. Однако, все достоинства и недостатки будут видны позже. Сейчас же я стремлюсь “пощупать” типовой сценарий работы с любой headless cms.
Первое, что нужно сделать — описать модели. Модель отвечает на вопрос, как должна выглядеть контентная сущность? Какая у нее структура? По сути это протокол взаимодействия между cms и клиентским приложением. В нашем случае — обзор к фильму — объект содержит:
- 3 обязательных свойства: название фильма, постер фильма, текст обзора;
- 1 необязательное свойство: объект “режиссер”, который в свою очередь содержит 2 обязательных свойства имя и фамилию.
В виде JSON Schema модель обзора выглядит так:
{
type: 'object',
required: ['movieName', 'moviePoster', 'reviewText'],
additionalProperties: false,
properties: {
movieName: {
type: 'string',
minLength: 1,
maxLength: 300,
},
moviePoster: {
type: 'string',
description: 'URL to file',
},
movieProducer: {
type: 'object',
required: ['name', 'surname'],
additionalProperties: false,
properties: {
name: { type: 'string', maxLength: 100, minLength: 1 },
surname: { type: 'string', maxLength: 100, minLength: 1 },
},
},
reviewText: {
type: 'string',
minLength: 1,
maxLength: 3000,
},
},
}
Также нужно реализовать feature toggle, модель в виде JSON Schema выглядит так:
{
type: 'object',
required: ['isFeatureActive', 'name'],
additionalProperties: false,
properties: {
isFeatureActive: { type: 'boolean' },
name: { type: 'string', enum: ['movieReviewFeatureToggle'] },
},
}
Когда есть понимание, как должны выглядеть модели, можно создавать их в Any JSON CMS.
Тут же создаю контентные сущности, т.е. сам контент, на основе моделей. Один фиктивный обзор и feature toggle сущность.
Для интеграции клиентского приложения с cms потребуется API key. Генерирую его в соответствующем разделе cms.
Теперь все готово для реализации функционала в клиентском приложении и интеграции с cms. Клиентское приложение может быть любым — сайт или мобильное приложение, или и то, и другое, написанное на чем угодно. В качестве примера я реализую функционал на сайте SPA на React. По сути мы забираем данные с уже известной, фиксированной структурой из cms и отображаем ее так, как хотим.
import React, { Component } from 'react'
import {
Accordion,
AccordionItem,
AccordionItemTitle,
AccordionItemBody,
} from 'react-accessible-accordion'
import 'react-accessible-accordion/dist/fancy-example.css'
const apiUrl = 'https://api.anyjsoncms.com'
// ApiKey безопаснее хранить на проксирующем бэкенде
const apiKey = '87414950dfd15648ea560bd89dd0ee02bfc8fcca'
class App extends Component {
constructor(props) {
super(props)
this.state = {
movies: null,
isFeatureActive: null,
loading: true,
}
}
componentDidMount() {
const options = { method: 'GET', headers: { ApiKey: apiKey } }
Promise.all([
fetch(`${apiUrl}/entries?apiId=featureToggle`, options).then(resp =>
resp.json()
),
fetch(`${apiUrl}/entries?apiId=movieReview`, options).then(resp =>
resp.json()
),
])
.then(([featureToggleResp, movieReviewResp]) => {
const featureToggle = featureToggleResp.find(
item => item.value.name === 'movieReviewFeatureToggle'
)
const isFeatureActive =
featureToggle &&
featureToggle.value &&
featureToggle.value.isFeatureActive
const movies = movieReviewResp.map(item => item.value)
this.setState({ movies, isFeatureActive, loading: false })
})
.catch(error => {
console.error(error)
})
}
render() {
const { movies, isFeatureActive, loading } = this.state
if (loading) return <div>Loading...</div>
if (!isFeatureActive)
return <div style={{ display: 'none' }}>Section is hidden</div>
return (
<div>
<Accordion>
{movies.map(
({ movieName, moviePoster, movieProducer, reviewText }, index) => (
<AccordionItem key={index}>
<AccordionItemTitle>
<h3>{movieName}</h3>
</AccordionItemTitle>
<AccordionItemBody>
<img src={`${apiUrl}${moviePoster}`} alt="" />
{!movieProducer ? null : (
<div>{`${movieProducer.name} ${
movieProducer.surname
}`}</div>
)}
<div>{reviewText}</div>
</AccordionItemBody>
</AccordionItem>
)
)}
</Accordion>
</div>
)
}
}
export default App
Все. Теперь контент-менеджер может спокойно управлять обзорами, а еще появилась возможность включать и отключать функционал при помощи feature toggle.
Выводить обзоры к фильмам — это простой пример, я намеренно его привел, чтобы не утонуть в деталях, а лишь продемонстрировать принцип. В действительности же фичи могут быть на порядок сложнее. Это могут быть элементы интерфейса, каталоги товаров, сложные виджеты, лендинги, генераторы форм, посты и пр. Также, в этом примере cms только распространяет информацию, однако большинство headless cms предоставляют CRUD API, что дает возможность, например, обрабатывать формы, да и вообще манипулировать сущностями, как угодно. В общем, задумка headless cms как раз в том, чтобы предоставить свободу и удобство в реализации сколь угодно сложного протокола, чтобы передать управление в cms чего угодно и так, как требуется.
Критерии выбора и анализ headless cms
После того, как у меня появилось понимание, какие задачи будут решаться при помощи headless cms и как именно, я выделил критерии и начал изучать системы. Сейчас согласно сайту headlesscms.org существует 54 cms. Проанализировать их все — довольно трудоемкий процесс, поэтому я выделил 14 наиболее популярных, заметных и обсуждаемых систем: Any JSON CMS, Contentful, Strapi, GraphCMS, Squidex, Butter CMS, Cloud CMS, Сockpit, Cosmic JS, Directus, Kentico Cloud, Netlify CMS, Prismic, Ghost.
Результаты удобнее изучать в виде таблицы. Но продублирую и здесь.
Any JSON CMS
Сайт | anyjsoncms.com |
Описание | Headless CMS that could help manage and deliver any JSON to any app |
Целевая аудитория | Digital teams |
Цена в месяц | Альфа версия, цены нет |
Возможность комерческой поддержки | нет |
Подписчиков в twitter | 0 тыс. |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | нет |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | да |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | да |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | нет |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | нет |
Система публикации: Draft/Publish | нет |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | нет |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | нет |
Управление пользователями | нет |
Управление доступами пользователей | нет |
Дополнительная информация | Доступна только альфа версия |
Contentful
Сайт | contentful.com |
Описание | Update once and publish everywhere, so teams build digital products faster. |
Предназначение | Content management in multi-channel world |
Целевая аудитория | Digital teams, enterprises |
Цена в месяц | cloud — free, 39$, 879$, hidden price for enterprise |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 33,6 тыс. |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | да |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | да |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | да |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | да |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | да |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Strapi
Сайт | strapi.io |
Описание | Manage your content. Distribute it anywhere. |
Предназначение | Build powerful content API with no effort |
Целевая аудитория | Profesional developers |
Цена в месяц | on-premiss — free |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 2,3 тыс. |
Github stars (если open source) | 11,1 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | нет |
GraphQL API | да |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | нет |
Поддержка API access tokens | нет |
Разграничение прав для доступа к API по API access token | да |
Система публикации: Draft/Publish | нет |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | нет |
Git подобная система версионирования | нет |
Управление проектами | нет, но можно развернуть отдельный экземпляр cms |
Управление изображениями | да |
Управление файлами | да |
Webhooks | нет, но можно реализовать через lifecycle callbacks |
Управление пользователями | да |
Управление доступами пользователей | да |
Дополнительная информация | Изучал альфа версию, были баги при сохранении модели |
GraphCMS
Сайт | graphcms.com |
Описание | Bring content to any platform |
Предназначение | Content infrastructure for your digital product |
Целевая аудитория | Profesional developers, agencies, enterprises |
Цена в месяц | cloud — free, 49$, 149$, 499$, hidden price for enterprise |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 2,4 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | да |
REST API | нет |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | да, либо не дает менять модель, либо изменение ведет к потере данных после подтверждения |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | да |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | нет |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Squidex
Сайт | squidex.io |
Описание | Squidex enables you to manage content in a central place and to use your tech stack for apps, websites and services. |
Предназначение | Our first priority is to deliver a state of the art, stable, fast and free content management hub to make the life for developers a little bit easier. |
Целевая аудитория | Profesional developers |
Цена в месяц | cloud — free, 19$, 49$, 99$; on-premises — free |
Возможность комерческой поддержки | не анонсирована |
Подписчиков в twitter | 0 тыс |
Github stars (если open source) | 0,5 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | да |
GraphQL API | да |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | можно указать single content или multiple content, конкретное кол-во указать нельзя |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | да |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | да |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Butter cms
Сайт | buttercms.com |
Описание | Add a blog or CMS to your site in minutes. Drop-in our Headless CMS and get back to more interesting problems. |
Предназначение | Drop our API-based CMS into any tech stack in minutes. |
Целевая аудитория | Startups, agencies, enterprises |
Цена в месяц | cloud — 24$, 83$, 166$, hidden price for enterprise |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 0,4 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | нет |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | нет |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | нет (и не требуется, т.к. есть только read) |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Cloud CMS
Сайт | cloudcms.com |
Описание | Easy for Content Editors + Powerful for Developers |
Предназначение | CMS for business critical applications |
Целевая аудитория | Enterprise |
Цена в месяц | 200$, 800$, 1200$ |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 0,3 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | да |
Cloud service | да |
GraphQL API | да |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | да |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | да |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | да |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | нет |
Система публикации: Draft/Publish | да, можно включить в настройках |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | да |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | да |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Дополнительная информация | Очень мощная, есть все фишки уровня enterprice, и даже больше. За счет обилия функционала, нужно чуть больше времени, чтобы в ней разобраться. |
Сockpit
Сайт | getcockpit.com |
Описание | Simple Content Platform to manage any structured content |
Предназначение | Add content management functionality to any site — plug & play / headless / api-first CMS |
Целевая аудитория | Digital teams |
Цена в месяц | on-premises — free |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 0,7 тыс |
Github stars (если open source) | 3,5 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | нет |
GraphQL API | нет, но реализуется через установку аддона |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | да, при помощи типа repeater |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | да |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | да, при помощи типа repeater |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет, возможно создавать только singleton модели |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | только read и update |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | да, через настройки collections permssions |
Система публикации: Draft/Publish | нет |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | нет, но можно развернуть отдельный экземпляр cms |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да, через конфигурацию групп |
Дополнительная информация | Достойное opensource решение. Некоторые настройки задаются через конфигурацию, а не через интерфейс. Например, чтобы настроить тип repeater, нужно изучить документацию и прописывать опции через JSON. Написан на PHP. |
Cosmic JS
Сайт | cosmicjs.com |
Описание | Modern Content Management Solution. The leading CMS for modern digital teams. |
Предназначение | The Cosmic JS Headless CMS gives your team everything you need to get the job done. |
Целевая аудитория | Digital teams, enterprice |
Цена в месяц | 44$, 179$, 449$, 359$, 719$ |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 2,8 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | да |
Cloud service | да |
GraphQL API | да |
REST API | да |
Контентная сущность создается на основе модели | да, но создатель контента может добавлять любые поля, даже если их нет в модели. Т.е. соответсвие модель -> контент не строгое. |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет, доступны только два варианта:
|
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | да |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | да |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | да, есть read токен и write токен |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | да |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Directus
Сайт | directus.io |
Описание | Premium Open-Source Software For Any Data-Driven Project |
Предназначение | Directus is an open-source suite of software that provides an instant API wrapper for SQL databases and an intuitive Admin App for non-technical users to manage that content. |
Целевая аудитория | Digital teams, enterprice |
Цена в месяц | on-premises — free |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 19,4 тыс |
Github stars (если open source) | 3,8 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | нет, но открыта пре-регистрация |
GraphQL API | нет |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет, есть тип поля group, но через интерфейс сгруппировать поля не удалось |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет, возможно создавать только singleton модели |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да |
CRUD API для моделей | да |
Поддержка API access tokens | да, привязываются к пользователю, настраивается через базу данных, а не интерфейс |
Разграничение прав для доступа к API по API access token | да, через настройку прав пользователя |
Система публикации: Draft/Publish | нет |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | нет, но можно развернуть отдельный экземпляр cms |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да, не через интерфейс, описываются на php |
Управление пользователями | да |
Управление доступами пользователей | да |
Дополнительная информация | При изменении модели появлялась ошибка «Something is wrong with this instance’s server or database.» И это блокирует любые манипуляции с типами и сущностями. Встречалось не однозначное поведение. Например есть сущность с текстовым полем и там есть значение длинной 10 символов. Меняем модель — устанавливаем максимальную длинну в 5 символов. Приложение делает вид, что сохранило изменения, но на деле нет. Это видно если повторно открыть настройки. Почему-то не сохраняет сущность если есть поле с русскими буквами. В целом произвело впечатление, что багов довольно много хотя это версия Directus Stable, и это удивило т.к. это зрелый продукт с большим сообществом. |
Kentico Cloud
Сайт | kenticocloud.com |
Описание | Stop Your Content Friction. Collaborate and deliver engaging omnichannel experiences with a CMS that's built for content strategists and developers. |
Предназначение | Create engaging personalized experiences across any device with a next-generation headless CMS. |
Целевая аудитория | Digital teams, agencies, enterprice |
Цена в месяц | cloud — 0$, 299$, 999$, hidden price for enterprise |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 1 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | нет |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | да |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет, подобный функционал реализуется через Content Type Snippets, по сути модель просто ссылается на подмодель, причем snippet не может содержать другой snippet |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | да, в professional тарифе |
CRUD API для моделей | да, только beta версия, в professional тарифе |
Поддержка API access tokens | да, в professional тарифе |
Разграничение прав для доступа к API по API access token | да, API token наследует права пользователья, который его сгенерировал |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | да |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Дополнительная информация | Довольно приятное впечатление, на равне с contentfull. Багов не было все четко и понятно. |
Netlify CMS
Сайт | netlifycms.org |
Описание | Open source content management for your Git workflow. Use Netlify CMS with any static site generator for a faster and more flexible web project |
Предназначение | Get the speed, security, and scalability of a static site, while still providing a convenient editing interface for content. |
Целевая аудитория | Profesional developers |
Цена в месяц | on-premises — free |
Возможность комерческой поддержки | не анонсирована |
Подписчиков в twitter | 3,6 тыс |
Github stars (если open source) | 7,4 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | нет |
GraphQL API | нет |
REST API | нет, сохраняет контент в файлы в git репозитории |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | нет, модели создаются через yml файл |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | да, но сущность с полем object не сохраняется в репозиторий, баг |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | нет |
Ceate, update, delete API для контентных сущностей | нет |
CRUD API для моделей | нет |
Поддержка API access tokens | нет |
Разграничение прав для доступа к API по API access token | нет |
Система публикации: Draft/Publish | да, если editorial_workflow on, поддерживается только на GitHub репозиториях |
Возможность отсроченной публикации | нет |
Фиксация версий моделей | да |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | да |
Управление проектами | нет, но можно развернуть отдельный экземпляр cms |
Управление изображениями | да, такой раздел есть, но файл не отправляется в репозиторий, баг |
Управление файлами | да, такой раздел есть, но файл не отправляется в репозиторий, баг |
Webhooks | нет |
Управление пользователями | нет, в самой cms нет, но можно управлять пользователями у провайдера git репозитория (в bitbucket, github, gitlab и пр.) |
Управление доступами пользователей | нет, но можно управлять у провайдера git репозитория |
Дополнительная информация | Изучал версию — 2.5.1. Эта CMS — оригинальное решение. Это фронтенд приложение, которое использует ваш git репозиторий в качестве бэкенда. |
Prismic
Сайт | prismic.io |
Описание | One CMS Backend for all your Websites & Apps |
Предназначение | CMS for apps, e-commerce, editorial websites, corporate websites. Enables marketing teams to create highly targeted acquisition campaigns. |
Целевая аудитория | Digital teams, enterprice |
Цена в месяц | cloud — 0$, 7$, 15$, 100$, 500$ |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 12,1 тыс |
Github stars (если open source) | не open source |
Open source решение | нет |
On-premises software | нет |
Cloud service | да |
GraphQL API | нет, только alpha версия |
REST API | да |
Контентная сущность создается на основе модели | да |
Есть возможность создавать свои модели | да |
Есть возможность создавать свои модели через UI | да |
Модель может содержать ссылку на другую модель | да |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | да |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет, можно группировать поля при помощи типа «group — a repeatable group of fields», этот тип больше похож на массив, причем group не может содержать другую group |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет, возможно создавать только singleton модели |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет возможности создать конфликт, т.к. нельзя задавать настройки валидации полей и указывать какие поля обязательные, а какие нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | нет |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | нет (и не требуется, т.к. есть только read) |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | да |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | да |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | да |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да, в Professional тарифе |
Ghost
Сайт | ghost.org |
Описание | Ghost is a fully open source, adaptable platform for building and running a modern online publication. We power blogs, magazines and journalists from Zappos to Sky News. |
Предназначение | Powerful platform for creating an online blog or publication |
Целевая аудитория | Professional bloggers, serious enterprise publishers |
Цена в месяц | on-premises — free; cloud — 29$, 79$, 199$ |
Возможность комерческой поддержки | да |
Подписчиков в twitter | 24,1 тыс |
Github stars (если open source) | 28,7 тыс |
Open source решение | да |
On-premises software | да |
Cloud service | да |
GraphQL API | нет |
REST API | да |
Контентная сущность создается на основе модели | нет |
Есть возможность создавать свои модели | нет |
Есть возможность создавать свои модели через UI | нет |
Модель может содержать ссылку на другую модель | нет |
Есть возможность комбинировать ссылки (например модель может ссылаться на любую из двух моделей) | нет |
Есть возможнсть создания вложенных моделей (например объект содержит другой объект) | нет |
Есть возможность комбинировать модели (например поле может быть или строкой, или числом) | нет |
Есть возможность указать сколько контентных сущностей может быть создано на основе конкретной модели | нет |
Управление обнаруженными конфликтами между моделью и контентной сущностью (например, если изменить модель так, чтобы уже существующая контентная сущность не удовлетворяла этим изменениям, умеет ли система решать такие ситуации?) | нет |
Read API для контентных сущностей | да |
Ceate, update, delete API для контентных сущностей | нет |
CRUD API для моделей | нет |
Поддержка API access tokens | да |
Разграничение прав для доступа к API по API access token | нет |
Система публикации: Draft/Publish | да |
Возможность отсроченной публикации | да |
Фиксация версий моделей | нет |
Фиксация версий контентных сущностей | нет |
Git подобная система версионирования | нет |
Управление проектами | да |
Управление изображениями | да |
Управление файлами | нет |
Webhooks | да |
Управление пользователями | да |
Управление доступами пользователей | да |
Дополнительная информация | Проект вырос из wordpress, мощный editing tool |
Выводы
По большому счёту от headless cms я ожидал увидеть две основные вещи: свободу в создании моделей, благодаря чему можно реализовать любой протокол, и git подобную систему контроля версий, чтобы можно было прозрачно управлять всеми изменениями.
И меня ждало легкое разочарование. Хотя с большинством из этих систем можно работать, они обладают рядом неприятных для меня недостатков. Это, конечно, не значит, что системы плохие, это лишь означает, что они не удовлетворили мои ожидания, а мои ожидания — это мои проблемы. Озвучу их:
- Большинство headless cms поддерживают вложенные структуры данных только через ссылки. Если нужен объект, внутри которого другой объект, то придется создавать две отдельные модели и связывать их через ссылку. Этот принцип оправдан, когда вложенный объект переиспользуется, но если нет, то в системе просто появляется лишняя модель, а за ней и лишние контентные сущности. Такой подход со временем заметно увеличивает и количество моделей, и количество контентных сущностей, что ведет к путанице. Плюс-минус полноценно вложенность поддерживается только в Cloud CMS, Cockpit и Cosmic JS.
- Иногда требуется комбинировать типы данных: нужно, чтобы свойство объекта было или строкой, или числом. Ну хорошо, в этой ситуации еще можно что-нибудь придумать, в зависимости от конкретного кейса — добавить валидацию при помощи регулярного выражения и нормализовать данные на клиенте. Но что делать, если нужно скомбинировать что-то посложнее, например так:
{ "oneOf": [ { "type": "number", "multipleOf": 5 }, { "type": "number", "multipleOf": 3 } ] }
Комбинировать типы данных умеет только Cockpit.
- Хотелось, чтобы система оповещала о конфликтах между моделью и контентными сущностями. Например, есть модель типа number, у этой модели есть контентная сущность со значением 100. Что произойдет если изменить модель, добавив туда валидацию maximum: 50? Оповестит ли система о конфликте? Такой функционал качественно реализует только GraphCMS.
- Git подобную систему контроля версий поддерживают только Cloud CMS и Netlify CMS.
К сожалению, когда я работал в той публичной компании, мы так и не смогли взять ни одну из этих систем. Лучше всего под наши потребности подходила Cloud CMS, но и цена на нее кусалась.
Заключение
Вот так этот анализ и привел меня к мысли, что нужно писать свою headless cms. Вы ее уже видели, на ее примере была демонстрация решения задачи. Она называется Any JSON CMS.
Основная ее цель — предоставить свободу в создании сколь угодно сложных моделей и контролировать все изменения при помощи git подобной системы. Сейчас реализовано далеко не все, что хотелось бы, он основной “посыл” уже есть.
a_dubovskoy
Еще же есть www.contentacms.org. Drupal8 по сути движется в сторону decoupled, www.acquia.com/drupal/decoupled-drupal — смотрите оф.блог Аквии (компании автора Друпала).
a_dubovskoy
Кстати прямо сейчас JSON:API закоммитили в ядро: dri.es/jsonapi-lands-in-drupal-core
BasilSnowman
Любопытно, почему не OpenAPI?
a_dubovskoy
Ну я думаю потому что разработчики проголосовали кодом:
www.drupal.org/project/openapi — 86 issues, 2,266 сайтов, последний коммит в прошлом году
www.drupal.org/project/jsonapi — 920 issues, 8,531 сайтов, последний коммит позавчера.