
Посібник із Sanity CMS: як ми публікуємо контент у 10 мовах
Ми опублікували понад 400 матеріалів на 4 вебсайтах у 10 мовах через Sanity CMS. Ось чому ми навчилися: від проектування схеми до автоматизованої багатомовної публікації.
Sanity CMS — це headless-платформа для контенту, побудована навколо структурованого контенту, Content Lake у реальному часі та налаштовуваного редактора на базі React під назвою Sanity Studio. Вона використовує GROQ для запитів, Portable Text для багатого контенту та підхід «схема як код» для моделювання контенту. Цей посібник охоплює налаштування, проектування схеми, GROQ, Portable Text, багатомовну архітектуру та ціноутворення.
Що таке Sanity CMS?
Sanity — це платформа для структурованого контенту, яку команда Sanity.io називає «операційною системою для контенту». На відміну від традиційних CMS, які зберігають HTML-блоки в базі даних, Sanity зберігає кожен елемент контенту як структурований JSON у керованому бекенді під назвою Content Lake. Ви запитуєте його за допомогою GROQ або GraphQL і відображаєте контент у будь-якому фронтенді: Next.js, React Native, Svelte, мобільному додатку, CLI-інструменті — у чому завгодно.
Компанії, які використовують цю платформу, охоплюють весь спектр. Nike, Figma, Puma та Cloudflare використовують Sanity в масштабах підприємства. Стартапи обирають її, тому що безкоштовний тариф дійсно придатний для використання (про ціни пізніше). Ми використовуємо її, тому що ніщо інше не дало нам гнучкості для створення повністю автоматизованого пайплайну публікації в 10 мовах.
Архітектура Content Lake
Content Lake — це керований бекенд Sanity. Уявіть його як хостингове сховище документів, яке синхронізується в реальному часі між усіма підключеними клієнтами. Коли редактор змінює абзац у Sanity Studio, інший редактор бачить це миттєво: без кнопки збереження, без конфліктів злиття, без міграцій бази даних.
«Під капотом» документи зберігаються як структурований JSON із типізованими полями. Кожна зміна відстежується через журнал транзакцій, тому ви отримуєте повну історію версій за замовчуванням. Синхронізація в реальному часі використовує архітектуру на основі слухачів (описану в документації архітектури Sanity на GitHub), яка надсилає зміни всім підписникам через спостерігачі RxJS.
Чим це відрізняється, скажімо, від бази даних PostgreSQL із REST API? Content Lake обробляє моделювання контенту, контроль доступу, кешування CDN, трансформацію зображень та співпрацю в реальному часі як єдиний керований сервіс. Вам не потрібно виконувати міграції. Вам не потрібно керувати репліками. Ви просто визначаєте схеми та запитуєте контент.
Sanity Studio: ваш налаштовуваний редактор
Sanity Studio — це open-source додаток на React, який слугує вашим інтерфейсом для редагування. Це не хостингова адмін-панель, а React-додаток, який живе у вашій кодовій базі. Ви можете налаштувати кожен його аспект: власні компоненти введення, умовні поля, дії з документами, патерни Structure Builder та плагіни.
Співпраця в реальному часі вбудована. Кілька редакторів можуть одночасно працювати над одним документом із індикаторами присутності та оновленнями в прямому ефірі. Якщо ви користувалися Google Docs, досвід буде схожим: ви бачите курсори та зміни інших людей в реальному часі.
Ми розгортаємо нашу Studio за допомогою npx sanity deploy, що розміщує її на CDN Sanity на власному субдомені. Ви також можете розмістити її самостійно, оскільки це просто React-додаток. Ми високо оцінили Sanity у нашому порівнянні headless CMS значною мірою через гнучкість Studio.
Як налаштувати проєкт Sanity
Щоб налаштувати Sanity CMS, встановіть CLI за допомогою npm create sanity@latest, виберіть шаблон проєкту, налаштуйте файли схеми та запустіть npx sanity dev, щоб локально запустити Studio. Весь процес займає менше 5 хвилин.
Передумови та встановлення
Вам потрібен Node.js 18+ і npm (або pnpm). Це все. Виконайте команду ініціалізації:
npm create sanity@latest
# You'll be prompted for:
# - Login method (Google, GitHub, email)
# - Project name
# - Dataset name (default: "production")
# - Project template (blog, ecommerce, clean)
# - TypeScript? (recommended: yes)CLI створює каркас проєкту з усім необхідним. Ось як виглядає структура проєкту:
Пояснення структури проєкту
my-sanity-project/
├── schemas/ # Your content schemas (this is where you'll spend time)
│ ├── index.ts # Schema registry -- imports and exports all types
│ ├── post.ts # Document type definitions
│ └── blockContent.ts # Rich text / Portable Text config
├── sanity.config.ts # Main config -- plugins, Studio structure, dataset
├── sanity.cli.ts # CLI config -- project ID, dataset
├── package.json
└── tsconfig.jsonФайл sanity.config.ts є вашою точкою входу. Ось мінімальний приклад:
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './schemas'
export default defineConfig({
name: 'default',
title: 'My Blog',
projectId: 'your-project-id',
dataset: 'production',
plugins: [structureTool(), visionTool()],
schema: { types: schemaTypes },
})Плагін visionTool() надає вам майданчик для тестування GROQ прямо в Studio, ви будете постійно використовувати його під час розробки.
Розгортання вашої Studio
Запустіть локально за допомогою npx sanity dev (працює на localhost:3333). Коли ви готові поділитися ним з редакторами, розгорніть на CDN Sanity:
npx sanity deploy
# Prompts for a hostname, e.g., "my-blog"
# Deploys to https://my-blog.sanity.studioПрофесійна порада: запускайте npx sanity@latest schema deploy після будь-якої зміни схеми. Це завантажує вашу схему в API Sanity, що вмикає такі функції, як GraphQL API та інструменти, свідомі до схеми (включно з MCP-сервером, про який ми поговоримо пізніше).
Проектування схеми в Sanity CMS
Схеми Sanity визначаються як об'єкти JavaScript або TypeScript у вашій кодовій базі. Кожна схема визначає тип документа з полями, правилами валідації та власними компонентами введення. Зміни в схемах відбуваються миттєво, міграції бази даних не потрібні. Це підхід «схема як код», і саме він переконав нас обрати Sanity замість Contentful.
Типи полів та валідація
Sanity постачається з багатим набором типів полів. Ось ті, які ми використовуємо найчастіше:
| Тип поля | Варіант використання | Приклад |
|---|---|---|
string | Короткий текст, заголовки, слаги | Заголовок допису, ім'я автора |
text | Багаторядковий звичайний текст | Уривки, описи |
number | Цілі числа, числа з плаваючою комою | Час читання, порядок сортування |
boolean | Перемикачі | Прапорець «Обране», статус чернетки |
array | Списки, багатий текст (Portable Text) | Вміст тіла, теги |
reference | Посилання на інші документи | Автор, категорія |
image | Зображення з метаданими | Зображення обкладинки з alt-текстом |
slug | Рядки, дружні до URL | Автогенерація з заголовка |
object | Вкладені групи полів | SEO-поля (metaTitle + metaDescription) |
date / datetime | Дати | Дата публікації |
Кожне поле підтримує валідацію через зворотний виклик validation. Ви можете забезпечити обов'язкові поля, мінімальні/максимальні значення, шаблони регулярних виразів та власні правила:
defineField({
name: 'seoDescription',
title: 'Meta Description',
type: 'string',
validation: (Rule) =>
Rule.required()
.min(145)
.max(160)
.warning('Meta description should be 145-160 characters'),
})Власні типи блоків (наші приклади з продакшену)
Ось де Sanity стає цікавою, і де 0 із 6 конкуруючих посібників показують будь-який код. У нашій продакшен-схемі ми визначаємо п'ять власних типів блоків всередині масиву body: block (стандартний текст), table, codeBlock, chartBlock та inlineImage.
Ось наше визначення codeBlock:
// schemas/objects/codeBlock.ts
import { defineType } from 'sanity'
export const codeBlock = defineType({
name: 'codeBlock',
title: 'Code Block',
type: 'object',
fields: [
{
name: 'language',
title: 'Language',
type: 'string',
options: {
list: [
{ title: 'JavaScript', value: 'javascript' },
{ title: 'TypeScript', value: 'typescript' },
{ title: 'Python', value: 'python' },
{ title: 'Bash', value: 'bash' },
{ title: 'JSON', value: 'json' },
{ title: 'GROQ', value: 'groq' },
],
},
},
{
name: 'code',
title: 'Code',
type: 'text',
},
],
})А ось як поле body посилається на всі наші власні типи разом:
// schemas/fields/body.ts
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [
{ type: 'block' }, // Standard Portable Text (paragraphs, headings, lists)
{ type: 'table' }, // @sanity/table plugin
{ type: 'codeBlock' }, // Our custom code block
{ type: 'chartBlock' }, // Data visualization (bar, line, pie)
{ type: 'inlineImage' }, // Images with alt text and captions
],
})Це дає нашим редакторам багатий набір інструментів для контенту, зберігаючи кожен елемент типізованим і доступним для запитів. chartBlock — це не просто непрозорий HTML-ембед, це структуровані дані з полями chartType, title, dataPoints та dataLabels. Це важливо, коли ви намагаєтеся відобразити той самий контент у вебі, електронній пошті та на мобільних пристроях.
Найкращі практики організації схем
Зберігайте схеми модульними. Ми розділили їх на файли за типом: schemas/documents/post.ts, schemas/objects/codeBlock.ts, schemas/objects/chartBlock.ts. Імпортуємо їх усі в schemas/index.ts:
// schemas/index.ts
import { post } from './documents/post'
import { codeBlock } from './objects/codeBlock'
import { chartBlock } from './objects/chartBlock'
import { inlineImage } from './objects/inlineImage'
export const schemaTypes = [post, codeBlock, chartBlock, inlineImage]Ключовий висновок, який ми отримали, працюючи зі структурованим контентом: ваша схема Є вашою моделлю контенту. Якщо ви думаєте про неї як про контекстну інженерію для вашої команди контенту, ви прийматимете кращі проектні рішення. Кожне додане поле повинно служити певній меті: або для редакторів, або для відображення, або для запитів.
GROQ: мова запитів Sanity
GROQ (Graph-Relational Object Queries) — це open-source мова запитів Sanity для фільтрації, об'єднання та проекції JSON-документів. Базовий синтаксис: *[filter]{projection}, виберіть усі документи, що відповідають фільтру, а потім сформуйте вивід. Для запитів, специфічних для Sanity, вона лаконічніша за GraphQL і, за нашим досвідом, швидше вивчається.
Базові запити: фільтрація та проекція
Найпростіший запит отримує всі документи певного типу:
// Fetch all posts -- just title and slug
*[_type == "post"]{
title,
"slug": slug.current
}
// Filter by language, expand author reference
*[_type == "post" && language == "en"]{
title,
"slug": slug.current,
"authorName": author->name,
"authorImage": author->image,
"categoryTitle": category->title,
publishedAt
}Оператор -> слідує за посиланнями. author->name означає «слідуйте за посиланням на автора та поверніть поле name». Ніяких окремих запитів, жодних проблем N+1, жодних JOIN — все це один вираз.
Об'єднання, сортування та пагінація
Для наших сторінок індексу блогу нам потрібні впорядковані, посторінкові дописи з розгорнутими посиланнями:
// Paginated posts with full metadata
*[_type == "post" && language == "en"] | order(publishedAt desc) [0...10] {
title,
"slug": slug.current,
excerpt,
publishedAt,
readTime,
"author": author->{name, image},
"category": category->{title, "slug": slug.current},
"coverImage": coverImage{
"src": asset->url,
alt
}
}[0...10] дає вам перші 10 результатів (індексація з 0, кінець виключено). | order(publishedAt desc) сортує від нових до старих. Проекція формує вивід так, щоб включати саме те, що потрібно вашому фронтенду, і нічого більше.
Ви можете тестувати всі ці запити інтерактивно за допомогою плагіна Vision у Sanity Studio. Він незамінний під час розробки. Для додаткових патернів перегляньте шпаргалку GROQ.
GROQ проти GraphQL
Sanity підтримує як GROQ, так і GraphQL. Коли що використовувати?
GROQ — це рідна мова Sanity. Вона обробляє об'єднання, проекції та обчислювані поля в одному рядку запиту. Саме для цього оптимізовано Content Lake.
GraphQL доступний після розгортання вашої схеми (npx sanity@latest schema deploy). Використовуйте його, коли вам потрібні стандартизовані інструменти, наприклад, якщо ваш фронтенд уже використовує Apollo Client або якщо ваша команда знає GraphQL, але не GROQ.
Ми використовуємо виключно GROQ. Він більш виразний для даних Sanity, а плагін Vision робить налагодження запитів тривіальним.
Portable Text: правильний підхід до багатого контенту
Portable Text — це специфікація Sanity для структурованого багатого тексту. Замість зберігання контенту як HTML-рядків, він зберігає масив типізованих блоків: абзаци, заголовки, зображення, фрагменти коду, таблиці — кожен як JSON-об'єкт. Це робить контент придатним для відображення в будь-якому фреймворку, на будь-якій платформі, у будь-якому форматі.
Структура даних
Ось як абзац і блок коду виглядають як JSON Portable Text:
[
{
"_type": "block",
"_key": "a1b2c3",
"style": "normal",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "d4e5f6",
"text": "Here's an example of our pipeline config:",
"marks": []
}
]
},
{
"_type": "codeBlock",
"_key": "g7h8i9",
"language": "typescript",
"code": "export default defineConfig({ ... })"
}
]Кожен блок має _type та _key. Стандартні текстові блоки використовують "block" із дочірніми spans (які підтримують позначки, такі як жирний шрифт, курсив та посилання). Власні блоки, такі як наші codeBlock, chartBlock, table та inlineImage, використовують свій власний _type і містять структуровані поля.
Чому це важливо? Тому що HTML — це формат відображення, а не зберігання. Якщо ви зберігаєте <h2>Title</h2><p>Some <strong>text</strong></p> у своїй базі даних, ви прив'язали себе до веб-відображення. Ви не можете чисто витягти це для мобільного додатка, інформаційного бюлетеня електронною поштою, PDF або контекстного вікна ШІ-агента. Portable Text відокремлює контент від презентації. Специфікація Portable Text є open-source, це не прив'язка до Sanity.
Власні блоки у продакшені
Наш пайплайн конвертує Markdown у Portable Text за допомогою скрипта Python (scripts/md_to_portable_text.py). Конвертер обробляє стандартні блоки плюс наші чотири власні типи:
table, використовує схему плагіна@sanity/table. Рядки та комірки зберігаються як структуровані дані.codeBlock, мова та код як окремі поля, що дозволяє підсвічування синтаксису при відображенні.chartBlock, тип діаграми, заголовок, мітки осей, назви серій та точки даних як структурований JSON. Фронтенд відображає їх за допомогою Chart.js.inlineImage, alt-текст, джерело та необов'язковий підпис як окремі поля.
Ця структура означає, що ми можемо запитувати всі приклади коду в нашому блозі (*[body[]._type == "codeBlock"]), знаходити дописи з діаграмами або вилучати всі зображення з відсутнім alt-текстом — все це через GROQ.
Відображення Portable Text
На фронтенді використовуйте @portabletext/react (або еквіваленти для Svelte/Vue). Ви реєструєте власні компоненти для кожного типу блоку:
import { PortableText } from '@portabletext/react'
const components = {
types: {
codeBlock: ({ value }) => (
<pre className={`language-${value.language}`}>
<code>{value.code}</code>
</pre>
),
chartBlock: ({ value }) => <Chart data={value} />,
inlineImage: ({ value }) => (
<figure>
<img src={value.src} alt={value.alt} />
{value.caption && <figcaption>{value.caption}</figcaption>}
</figure>
),
},
}
// In your component:
<PortableText value={post.body} components={components} />Це весь пайплайн відображення. Компонент PortableText автоматично обробляє стандартні блоки (абзаци, заголовки, списки, позначки). Ви визначаєте власні компоненти лише для своїх власних типів.
Багатомовний контент із Sanity CMS
Sanity підтримує багатомовний контент через локалізацію на рівні документів (окремі документи для кожної мови, пов'язані канонічним посиланням) або локалізацію на рівні полів (перекладені поля в одному документі). Локалізація на рівні документів краще підходить для SEO та публікації у великих масштабах, саме це ми використовуємо в нашому 10-мовному пайплайні.
Локалізація на рівні документів проти рівня полів
| Аспект | На рівні документів | На рівні полів |
|---|---|---|
| Підхід | Окремий документ для кожної мови | Усі переклади в одному документі |
| SEO | Кожен документ має власний URL/слаг | Один URL, складніше подавати сторінки для кожної мови |
| Складність запиту | Прості фільтри: language == "de" | Доступ до вкладених полів: title.de |
| Розмір контенту | Малі, зосереджені документи | Один великий документ з усіма мовами |
| Найкраще для | Дописи в блозі, сторінки, контент для SEO | Невеликі рядки UI, мітки, метадані |
| Наш вердикт | Ми використовуємо це для всього | Тільки для спільних рядків UI |
Ми обрали локалізацію на рівні документів, тому що кожен переклад отримує власний слаг, власний URL та власні метадані. Турецька версія допису про порівняння Supabase та Firebase отримує слаг supabase-firebase-karsilastirma, правильну турецьку, а не хак із параметром URL.
Архітектура нашого 10-мовного пайплайну
Ось як працює наш автоматизований пайплайн: ми пишемо допис англійською, а потім перекладаємо його на 9 додаткових мов (німецьку, французьку, нідерландську, іспанську, турецьку, італійську, шведську, норвезьку, арабську). Кожен переклад проходить через конвертацію Markdown, генерацію Portable Text та публікацію через API Sanity.
Архітектура виглядає так:
- Написання, англійський Markdown із YAML frontmatter
- Переклад, ШІ-переклад на 9 мов (перевірено на повноту та діакритичні знаки)
- Конвертація, скрипт Python конвертує кожен файл
.mdу JSON Portable Text - Публікація, API-виклики до Sanity: створення документа, завантаження зображень, патчинг посилань
Кожен документ має поле language та посилання canonicalPost, яке вказує на оригінал англійською. Ось запит GROQ для отримання допису та всіх його перекладів:
// Fetch a post and all its translations
*[_type == "post" && slug.current == "sanity-cms-guide" && language == "en"][0]{
title,
language,
"translations": *[
_type == "post" &&
canonicalPost._ref == ^._id
]{
title,
language,
"slug": slug.current
}
}Частина схеми проста: поле language з переліком підтримуваних мов:
defineField({
name: 'language',
title: 'Language',
type: 'string',
options: {
list: [
{ title: 'English', value: 'en' },
{ title: 'German', value: 'de' },
{ title: 'French', value: 'fr' },
{ title: 'Dutch', value: 'nl' },
{ title: 'Spanish', value: 'es' },
{ title: 'Turkish', value: 'tr' },
{ title: 'Italian', value: 'it' },
{ title: 'Swedish', value: 'sv' },
{ title: 'Norwegian', value: 'no' },
{ title: 'Arabic', value: 'ar' },
],
},
validation: (Rule) => Rule.required(),
})Один нюанс, який ми засвоїли важким шляхом: спочатку опублікуйте англомовний документ, а потім виправте посилання canonicalPost у перекладах, використовуючи опублікований ID документа, а не префікс drafts.. Sanity внутрішньо розглядає чернетки та опубліковані документи як окремі сутності.
Для отримання додаткової інформації про те, як цей пайплайн підключається до Model Context Protocol, див. наступний розділ.
Функції ШІ в Sanity: MCP, Canvas та контекст агентів
Sanity позиціонує себе як операційна система для контенту в епоху ШІ. Ключові функції ШІ включають MCP-сервер для читання та запису контенту ШІ-агентами, Canvas для редагування за допомогою ШІ всередині Studio та Agent Context для продакшен-ШІ-агентів, щоб запитувати структурований контент із усвідомленням схеми.
Інтеграція MCP-сервера
MCP-сервер Sanity дозволяє ШІ-агентам, таким як Claude Code, Cursor, Windsurf та іншим, програмно взаємодіяти з вашим робочим простором Sanity. Агенти можуть читати схеми, виконувати запити GROQ, створювати документи та керувати контентом без власних API-обгорток.
Ми щодня використовуємо MCP-сервер Sanity у нашому контент-пайплайні. Наші ШІ-агенти запитують схему, щоб зрозуміти структуру документів, отримують наявні дописи для пошуку можливостей для внутрішнього лінкінгу та публікують нові документи. Протокол MCP надає агентам усвідомлення схеми: вони знають, які поля існують, які типи очікуються та які правила валідації застосовуються. Якщо ви будуєте ШІ-агенти для бізнесу робочі процеси, це потужний патерн.
Agent Context для продакшен-ШІ
Agent Context — це окрема функція для інтеграцій ШІ продакшен-рівня. На відміну від MCP-сервера (який призначений для інструментів розробників), Agent Context надає доступ тільки для читання з обмеженою областю дії для ШІ-агентів, яким потрібно запитувати ваш контент під час виконання, наприклад, чат-боти, системи рекомендацій або системи персоналізації контенту.
Різниця важлива: MCP призначений для робочих процесів часу збірки та редакційних робіт (інструменти розробки, свідомі до схеми), тоді як Agent Context призначений для доступу до контенту під час виконання з належною автентифікацією та обмеженням частоти запитів.
Структурований контент Sanity дає йому реальну перевагу тут. Сайт WordPress зберігає контент як HTML-блоки, ШІ-агенту доводиться парсити HTML, щоб зрозуміти контент. Sanity зберігає типізовані JSON-документи з визначеними схемами. Агент може зробити запит *[_type == "product" && category == "electronics"]{name, price, features} і отримати чисті, структуровані дані. Без скрапінгу, без парсингу, без здогадок.
Як ми використовуємо Sanity в Techsy
Це не гіпотетичний розділ. Ми використовуємо Sanity CMS на 4 продакшен-сайтах, публікуючи контент у 10 мовах за допомогою автоматизованого пайплайну, який ми створили за останній рік. Ось архітектура.
Архітектура нашого контент-пайплайну
Пайплайн проходить від дослідження до опублікованого допису на всіх 10 мовах:
- Дослідження, аналіз ключових слів, виявлення прогалин конкурентів, патерни SERP
- Бриф, структурована специфікація написання з рекомендаціями щодо розділів, кількістю слів, внутрішніми посиланнями
- Написання, створення англійського Markdown із YAML frontmatter
- Конвертація, скрипт Python трансформує Markdown у JSON Portable Text із нашими 5 власними типами блоків
- Публікація, API-виклики до Sanity:
createOrReplaceдокумент, завантаження зображень на CDN Sanity, патчинг посилань на автора/категорію - Переклад, ШІ-переклад на 9 мов, перевірено на повноту
- Публікація перекладів, той самий потік конвертації/публікації для кожної мови, із посиланням
canonicalPost, що вказує на англійський оригінал
Власна схема підтримує типи block, table, codeBlock, chartBlock та inlineImage, усі визначені як об'єкти продакшен-схеми Sanity з правилами валідації. Серед ШІ-інструментів для стартапів, які ми тестували, цей пайплайн на базі Sanity був найбільш надійним для структурованого контенту в масштабі.
Уроки з 400+ опублікованих матеріалів
Кілька речей, про які ми хотіли б, щоб хтось сказав нам раніше:
Порядок патчингу посилань має значення. Посилання Sanity не можуть вказувати на документи, яких ще не існує. Спочатку опублікуйте англомовний допис, потім створіть переклади з canonicalPost, що вказує на опублікований ID англомовного документа. Кілька разів на початку ми ламали це.
Розгортання схеми відбувається для кожного робочого простору. Якщо ви запускаєте кілька проєктів Sanity (ми запускаємо 4), вам потрібно розгортати схеми в кожному окремо: npx sanity@latest schema deploy для кожної конфігурації проєкту.
Безкоштовний тариф реальний. Ми запустили два з наших чотирьох сайтів на безкоштовному плані протягом місяців. 20 користувачів, 500 тис. API-запитів/місяць, 100 тис. CDN-запитів — цього достатньо для реального продакшен-сайту, а не просто іграшкового проєкту.
Конвертація Portable Text є вузьким місцем. Перетворення Markdown на Portable Text не є тривіальним. Вкладені списки, таблиці всередині блокових цитат, блоки коду зі спеціальними символами — крайні випадки всюди. Ми місяцями вдосконалювали наш скрипт конвертера.
Потрібна допомога з налаштуванням Sanity для вашого проєкту? Ми створили багатомовні контент-пайплайни для 4 продакшен-сайтів. Отримайте безкоштовну консультацію
Розбір цін на Sanity CMS
Sanity пропонує три плани: Free (20 користувачів, 500 тис. API-запитів/місяць), Growth ($15/користувач/місяць із розширеними ролями та запланованими чернетками) та Enterprise (індивідуальне ціноутворення з SLA та функціями відповідності). Безкоштовний тариф є найбільш щедрим на ринку headless CMS.
| Функція | Free | Growth ($15/користувач/міс) | Enterprise |
|---|---|---|---|
| Користувачі | 20 | 50 | Необмежено |
| API-запити | 500 тис./міс | 2,5 млн/міс | Індивідуально |
| CDN-запити | 100 тис./міс | 500 тис./міс | Індивідуально |
| Ролі | Тільки Admin | Admin, Developer, Editor, Contributor | Власні ролі |
| Співпраця | Редагування в реальному часі | + Запланована публікація, чернетки | + Робочі процеси |
| Підтримка | Спільнота | Електронна пошта | Виділена + SLA |
| Відповідність | , | , | SOC 2, HIPAA |
На безкоштовному тарифі ми запускаємо два наші сайти, не досягаючи лімітів. План Growth за $15/користувач/місяць додав доступ на основі ролей (важливо, коли у нас з'явилися нетехнічні редактори) та заплановану публікацію. Переглядачі безкоштовні на плані Growth, що є приємним бонусом: вас не штрафують за надання зацікавленим сторонам доступу лише для читання.
Як це порівнюється з конкурентами?
| Функція | Sanity Free | Contentful Free | Strapi Cloud Free | Payload Cloud |
|---|---|---|---|---|
| Користувачі | 20 | 1 | 1 | 1 |
| Типи контенту | Необмежено | 48 | Необмежено | Необмежено |
| API-виклики | 500 тис./міс | Включено | Включено | Включено |
| Власні типи | Так | Обмежено | Так | Так |
| Ціна для росту | $15/користувач/міс | $300/міс | $29/міс | $50/міс |
20-користувацький безкоштовний тариф Sanity є винятковим. Contentful обмежує вас 1 користувачем на безкоштовному плані та стрибає до $300/місяць за їхній план Team. Якщо ви стартап або невелика команда, безкоштовний план Sanity дозволяє вам запускати реальні продакшен-навантаження, не витрачаючи нічого.
Sanity також пропонує програму для стартапів, яка надає відповідним стартапам один рік безкоштовного доступу до Growth. Варто подати заявку, якщо ви підходите.
Поширені запитання
Що таке Sanity CMS і як вона працює?
Sanity CMS — це headless-платформа для контенту, яка зберігає структуровані JSON-документи в керованому бекенді під назвою Content Lake. Ви редагуєте контент через Sanity Studio (налаштовуваний додаток на React), запитуєте його за допомогою GROQ або GraphQL і відображаєте в будь-якому фронтенд-фреймворку. Контент синхронізується в реальному часі між усіма підключеними клієнтами.
Чи є Sanity CMS безкоштовною?
Так. Безкоштовний тариф Sanity включає 20 користувачів, 500 тис. API-запитів на місяць і 100 тис. CDN-запитів — найщедріший безкоштовний план серед headless CMS-платформ. План Growth коштує $15 за користувача на місяць і додає доступ на основі ролей, заплановану публікацію та вищі ліміти. Ціноутворення Enterprise є індивідуальним.
Яка різниця між Sanity та Contentful?
Sanity використовує schema-as-code (схеми живуть у вашій кодовій базі), GROQ для запитів та повністю налаштовувану open-source Studio. Contentful використовує GUI-моделювання контенту, GraphQL та хостинговий редактор із меншою можливістю налаштування. Безкоштовний тариф Sanity включає 20 користувачів проти 1 у Contentful. Contentful має більший ринок плагінів.
Чи підходить Sanity CMS для початківців?
Sanity Studio інтуїтивно зрозуміла для редакторів контенту, досвід редагування не вимагає технічних знань. Однак налаштування схем вимагає знань JavaScript або TypeScript. Sanity надає чудову документацію, шаблони проєктів та активну підтримку в Slack-спільноті. Почніть з npm create sanity@latest та шаблону блогу.
Чи можу я розмістити Sanity самостійно?
Sanity Studio повністю придатна для самостійного розміщення, оскільки це open-source додаток на React. Ви можете розгорнути її на Vercel, Netlify або будь-якому хостинг-провайдері статичних сайтів. Бекенд Content Lake є керованим сервісом, варіанту самостійного розміщення для шару даних немає. Це компроміс: ви отримуєте нульове управління інфраструктурою, але не маєте контролю над даними on-premises.
Яку базу даних використовує Sanity?
Content Lake Sanity не є традиційною SQL або NoSQL базою даних. Це кероване сховище документів, яке зберігає контент як структурований JSON із шаром запитів GROQ поверх нього. Ви не взаємодієте з основною базою даних безпосередньо, ви взаємодієте через API Sanity. Документи мають повну історію версій та вбудовану синхронізацію в реальному часі.
Чи є Sanity CMS open-source?
Sanity Studio є open-source під ліцензією MIT, ви можете форкнути її, налаштувати та розмістити самостійно. Бекенд Content Lake є пропрієтарним SaaS. Специфікація мови запитів GROQ також є open-source, опублікована на GitHub. Специфікація Portable Text також є open-source, її підтримують на portabletext.org.
Що таке Portable Text у Sanity?
Portable Text — це специфікація Sanity для структурованого багатого тексту. Замість зберігання контенту як HTML-рядків, він представляє абзаци, заголовки, зображення та власні блоки як типізовані JSON-об'єкти в масиві. Це робить контент портативним між фреймворками та платформами. Ви можете визначати власні типи блоків, такі як фрагменти коду, діаграми та таблиці, з їхніми власними структурованими полями.
Що таке GROQ і чим він відрізняється від GraphQL?
GROQ (Graph-Relational Object Queries) — це рідна мова запитів Sanity. Її синтаксис, *[filter]{projection}, є більш лаконічним, ніж GraphQL, для даних Sanity, із вбудованою підтримкою об'єднань через оператор -> та обчислюваних полів. GraphQL також доступний для команд, які віддають перевагу стандартизованим інструментам або вже використовують Apollo Client.
Як Sanity обробляє багатомовний контент?
Sanity підтримує локалізацію на рівні документів (окремі документи для кожної мови, пов'язані канонічними посиланнями) та локалізацію на рівні полів (перекладені поля в одному документі). Локалізація на рівні документів краще підходить для SEO, оскільки кожен переклад отримує власний URL та метадані. Ми використовуємо локалізацію на рівні документів для публікації в 10 мовах за допомогою автоматизованих пайплайнів перекладу та публікації.