
Ghid Sanity CMS: Cum îl folosim pentru a publica în 10 limbi
Am publicat peste 400 de piese de conținut pe 4 site-uri web și în 10 limbi prin intermediul Sanity CMS. Iată ce am învățat, de la proiectarea schemei până la publicarea automatizată multilingvă.
Sanity CMS este o platformă de conținut headless construită în jurul conținutului structurat, un Content Lake în timp real și un editor personalizabil bazat pe React, numit Sanity Studio. Folosește GROQ pentru interogări, Portable Text pentru conținut bogat și schema-as-code pentru modelarea conținutului. Acest ghid acoperă configurarea, proiectarea schemei, GROQ, Portable Text, arhitectura multilingvă și prețurile.
Ce este Sanity CMS?
Sanity este o platformă de conținut structurat, ceea ce echipa de la Sanity.io numește un „sistem de operare pentru conținut”. Spre deosebire de CMS-urile tradiționale care stochează blob-uri HTML într-o bază de date, Sanity stochează fiecare piesă de conținut ca JSON structurat într-un backend gestionat numit Content Lake. Îl interogați cu GROQ sau GraphQL și redați conținutul în orice frontend doriți: Next.js, React Native, Svelte, o aplicație mobilă, un instrument CLI, orice.
Companiile care îl utilizează acoperă întregul spectru. Nike, Figma, Puma și Cloudflare rulează Sanity la scară enterprise. Startup-urile îl folosesc deoarece nivelul gratuit este cu adevărat utilizabil (mai multe despre prețuri mai târziu). Noi îl folosim deoarece nimic altceva nu ne-a oferit flexibilitatea de a construi un pipeline de publicare complet automatizat în 10 limbi.
Arhitectura Content Lake
Content Lake este backend-ul gestionat de Sanity. Gândiți-vă la el ca la un magazin de documente găzduit care se sincronizează în timp real între toți clienții conectați. Când un editor modifică un paragraf în Sanity Studio, un alt editor îl vede instantaneu, fără buton de salvare, fără conflicte de îmbinare, fără migrări de baze de date.
În spate, documentele sunt stocate ca JSON structurat cu câmpuri tipizate. Fiecare mutație este urmărită printr-un jurnal de tranzacții, astfel încât obțineți implicit un istoric complet al versiunilor. Sincronizarea în timp real folosește o arhitectură bazată pe listeneri (descrisă în documentația de arhitectură GitHub a Sanity) care împinge modificările către toți abonații prin observabile RxJS.
Ce face acest lucru diferit de, să zicem, o bază de date PostgreSQL cu un API REST? Content Lake gestionează modelarea conținutului, controlul accesului, cache-ul CDN, transformările imaginilor și colaborarea în timp real ca un singur serviciu gestionat. Nu rulați migrări. Nu gestionați replici. Doar definiți schemele și interogați conținutul.
Sanity Studio: Editorul tău personalizabil
Sanity Studio este o aplicație React open-source care servește drept interfață de editare. Nu este un panou de administrare găzduit, ci o aplicație React care trăiește în baza ta de cod. Poți personaliza fiecare aspect al său: componente de input personalizate, câmpuri condiționate, acțiuni pentru documente, modele de structură builder și plugin-uri.
Colaborarea în timp real este integrată. Mai mulți editori pot lucra simultan la același document, cu indicatori de prezență și actualizări live. Dacă ați folosit Google Docs, experiența este similară; vedeți cursoarele și modificările celorlalți în timp real.
Ne implementăm Studio-ul cu npx sanity deploy, care îl găzduiește pe CDN-ul Sanity la un subdomeniu personalizat. Îl puteți găzdui și pe cont propriu, deoarece este doar o aplicație React. Am clasat Sanity foarte bine în compararea noastră de CMS headless în mare parte datorită flexibilității Studio-ului.
Cum să configurezi un proiect Sanity
Pentru a configura Sanity CMS, instalați CLI-ul cu npm create sanity@latest, alegeți un șablon de proiect, configurați fișierele schemei și rulați npx sanity dev pentru a lansa Studio local. Întregul proces durează sub 5 minute.
Cerințe preliminare și instalare
Aveți nevoie de Node.js 18+ și npm (sau pnpm). Asta e tot. Rulați comanda de inițializare:
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-ul scheletizează un proiect cu tot ce aveți nevoie. Iată cum arată structura proiectului:
Explicarea structurii proiectului
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.jsonFișierul sanity.config.ts este punctul tău de intrare. Iată unul minimal:
// 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 },
})Plugin-ul visionTool() vă oferă un loc de joacă GROQ în interiorul Studio-ului; îl veți folosi constant în timpul dezvoltării.
Implementarea Studio-ului tău
Lansați local cu npx sanity dev (rulează pe localhost:3333). Când sunteți gata să partajați cu editorii, implementați pe CDN-ul Sanity:
npx sanity deploy
# Prompts for a hostname, e.g., "my-blog"
# Deploys to https://my-blog.sanity.studioSfat pro: rulați npx sanity@latest schema deploy după orice modificare a schemei. Aceasta încarcă schema dvs. în API-ul Sanity, ceea ce activează funcționalități precum API-ul GraphQL și instrumentele conștiente de schemă (inclusiv serverul MCP pe care îl vom aborda mai târziu).
Proiectarea schemei în Sanity CMS
Schemele Sanity sunt definite ca obiecte JavaScript sau TypeScript în baza dvs. de cod. Fiecare schemă specifică un tip de document cu câmpuri, reguli de validare și componente de input personalizate. Modificările la scheme sunt instantanee, fără migrări de baze de date necesare. Aceasta este abordarea „schema-as-code”, iar acesta este lucrul care ne-a convins să alegem Sanity în detrimentul Contentful.
Tipuri de câmpuri și validare
Sanity vine cu un set bogat de tipuri de câmpuri. Iată cele pe care le folosim cel mai des:
| Tip câmp | Caz de utilizare | Exemplu |
|---|---|---|
string | Text scurt, titluri, slug-uri | Titlu postare, nume autor |
text | Text simplu pe mai multe linii | Extrase, descrieri |
number | Numere întregi, flotante | Timp de citire, ordine de sortare |
boolean | Comutatoare | Steag „Featured”, statut draft |
array | Liste, text bogat (Portable Text) | Conținut corp, etichete |
reference | Link-uri către alte documente | Autor, categorie |
image | Imagini cu metadate | Imagine de copertă cu text alternativ |
slug | Șiruri prietenoase URL | Generat automat din titlu |
object | Grupuri de câmpuri imbricate | Câmpuri SEO (metaTitle + metaDescription) |
date / datetime | Date | Data publicării |
Fiecare câmp suportă validarea printr-un callback validation. Puteți impune câmpuri obligatorii, valori minime/maxime, modele regex și reguli personalizate:
defineField({
name: 'seoDescription',
title: 'Meta Description',
type: 'string',
validation: (Rule) =>
Rule.required()
.min(145)
.max(160)
.warning('Meta description should be 145-160 characters'),
})Tipuri de blocuri personalizate (Exemplele noastre din producție)
Aici devine interesant Sanity și unde 0 din 6 ghiduri concurente arată vreun cod. În schema noastră de producție, definim cinci tipuri de blocuri personalizate în interiorul array-ului body: block (text standard), table, codeBlock, chartBlock și inlineImage.
Iată definiția noastră pentru 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',
},
],
})Și iată cum câmpul body face referire la toate tipurile noastre personalizate împreună:
// 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
],
})Acest lucru le oferă editorilor noștri un kit de instrumente rich content, menținând în același timp fiecare element tipizat și interogabil. Un chartBlock nu este doar un embed HTML opac, ci date structurate cu câmpuri chartType, title, dataPoints și dataLabels. Acest lucru contează când încercați să redați același conținut pe web, email și mobil.
Cele mai bune practici pentru organizarea schemei
Mențineți schemele modulare. Noi le împărțim în fișiere pe tipuri: schemas/documents/post.ts, schemas/objects/codeBlock.ts, schemas/objects/chartBlock.ts. Importați-le pe toate în 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]Ideea cheie pe care am dobândit-o lucrând cu conținut structurat: schema TA ESTE modelul tău de conținut. Dacă vă gândiți la ea ca la context engineering pentru echipa dvs. de conținut, veți lua decizii de design mai bune. Fiecare câmp pe care îl adăugați ar trebui să servească unui scop, fie pentru editori, fie pentru redare, fie pentru interogare.
GROQ: Limbajul de interogare al Sanity
GROQ (Graph-Relational Object Queries) este limbajul de interogare open-source al Sanity pentru filtrarea, join-ul și proiecția documentelor JSON. Sintaxa de bază este *[filter]{projection}, selectați toate documentele care corespund unui filtru, apoi modelați ieșirea. Este mai concis decât GraphQL pentru interogările specifice Sanity și, din experiența noastră, mai rapid de învățat.
Interogări de bază: Filtrare și Proiecție
Cea mai simplă interogare preia toate documentele de un anumit tip:
// 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
}Operatorul -> urmează referințele. author->name înseamnă „urmărește referința autorului și returnează câmpul name”. Fără interogări separate, fără probleme N+1, fără JOIN-uri, totul este o singură expresie.
Join-uri, Ordonare și Paginare
Pentru paginile noastre de index ale blogului, avem nevoie de postări ordonate, paginate, cu referințe expandate:
// 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] vă oferă primele 10 rezultate (indexat de la 0, sfârșit exclusiv). | order(publishedAt desc) sortează cele mai noi primele. Proiecția modelează ieșirea pentru a include exact ceea ce are nevoie frontend-ul dvs., nimic mai mult.
Puteți testa toate aceste interogări interactiv folosind plugin-ul Vision în interiorul Sanity Studio. Este de neprețuit în timpul dezvoltării. Pentru mai multe modele, consultați foaia de cheatsheet GROQ.
GROQ vs GraphQL
Sanity suportă atât GROQ, cât și GraphQL. Când ar trebui să le folosiți pe fiecare?
GROQ este limbajul nativ al Sanity. Gestionează join-urile, proiecțiile și câmpurile calculate într-un singur șir de interogare. Este ceea ce este optimizat pentru Content Lake.
GraphQL este disponibil după ce vă implementați schema (npx sanity@latest schema deploy). Folosiți-l când aveți nevoie de instrumente standardizate, de exemplu, dacă frontend-ul dvs. folosește deja Apollo Client sau dacă echipa dvs. cunoaște GraphQL, dar nu GROQ.
Noi folosim exclusiv GROQ. Este mai expresiv pentru datele Sanity, iar plugin-ul Vision face depanarea interogărilor trivială.
Portable Text: Conținut bogat făcut corect
Portable Text este specificația Sanity pentru text bogat structurat. În loc să stocheze conținutul ca șiruri HTML, stochează un array de blocuri tipizate, paragrafe, titluri, imagini, snippet-uri de cod, tabele, fiecare ca un obiect JSON. Acest lucru face conținutul randabil în orice framework, orice platformă, orice format.
Structura datelor
Iată cum arată un paragraf și un bloc de cod ca 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({ ... })"
}
]Fiecare bloc are un _type și un _key. Blocurile de text standard folosesc "block" cu children spans (care suportă marcaje precum bold, italic și link-uri). Blocurile personalizate, precum codeBlock, chartBlock, table și inlineImage, folosesc propriul lor _type și poartă câmpuri structurate.
De ce contează acest lucru? Deoarece HTML este un format de redare, nu un format de stocare. Dacă stocați <h2>Titlu</h2><p>Un <strong>text</strong></p> în baza de date, v-ați limitat la redarea web. Nu puteți extrage curat acel conținut pentru o aplicație mobilă, un newsletter prin email, un PDF sau fereastra de context a unui agent AI. Portable Text separă conținutul de prezentare. Specificația Portable Text este open source, nu este o limitare la Sanity.
Blocuri personalizate în producție
Pipeline-ul nostru convertește Markdown în Portable Text folosind un script Python (scripts/md_to_portable_text.py). Convertorul gestionează blocurile standard, plus cele patru tipuri personalizate ale noastre:
table, folosește schema plugin-ului@sanity/table. Rândurile și celulele sunt stocate ca date structurate.codeBlock, limba și codul ca câmpuri separate, permițând evidențierea sintaxei la redare.chartBlock, tipul graficului, titlul, etichetele axelor, numele seriilor și punctele de date ca JSON structurat. Frontend-ul le randează cu Chart.js.inlineImage, text alternativ, sursă și legendă opțională ca câmpuri separate.
Această structură înseamnă că putem interoga toate exemplele de cod din blogul nostru (*[body[]._type == "codeBlock"]), găsi postări cu grafice sau extrage toate imaginile cu text alternativ lipsă, totul prin GROQ.
Redarea Portable Text
Pe frontend, utilizați @portabletext/react (sau echivalentele pentru Svelte/Vue). Înregistrați componente personalizate pentru fiecare tip de bloc:
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} />Acesta este întregul pipeline de redare. Componenta PortableText gestionează automat blocurile standard (paragrafe, titluri, liste, marcaje). Trebuie doar să definiți componente personalizate pentru tipurile dvs. personalizate.
Conținut multilingv cu Sanity CMS
Sanity suportă conținutul multilingv prin localizare la nivel de document (documente separate per limbă legate printr-o referință canonică) sau localizare la nivel de câmp (câmpuri traduse într-un singur document). Localizarea la nivel de document funcționează mai bine pentru SEO și publicarea la scară largă; asta este ceea ce folosim în pipeline-ul nostru în 10 limbi.
Localizare la nivel de document vs. la nivel de câmp
| Aspect | Nivel Document | Nivel Câmp |
|---|---|---|
| Abordare | Document separat per limbă | Toate traducerile într-un singur document |
| SEO | Fiecare document are propriul URL/slug | URL unic, mai greu de servit pagini per limbă |
| Complexitate interogare | Filtre simple: language == "de" | Acces câmp imbricat: title.de |
| Dimensiune conținut | Documente mici, focalizate | Un document mare cu toate limbile |
| Cel mai bun pentru | Postări blog, pagini, conținut orientat SEO | Șiruri UI mici, etichete, metadate |
| Verdictul nostru | Folosim asta pentru totul | Doar pentru șiruri UI partajate |
Am ales localizarea la nivel de document deoarece fiecare traducere primește propriul slug, propriul URL și propriile metadate. Versiunea turcă a unei postări despre Supabase vs Firebase primește slug-ul supabase-firebase-karsilastirma, turcă corectă, nu un hack cu parametri URL.
Arhitectura pipeline-ului nostru în 10 limbi
Iată cum funcționează pipeline-ul nostru automatizat: scriem o postare în engleză, apoi o traducem în alte 9 limbi (germană, franceză, olandeză, spaniolă, turcă, italiană, suedeză, norvegiană, arabă). Fiecare traducere trece prin conversia Markdown, generarea Portable Text și publicarea API Sanity.
Arhitectura arată astfel:
- Scriere, Markdown în engleză cu frontmatter YAML
- Traducere, traducere AI în 9 limbi (verificată pentru completitudine și diacritice)
- Conversie, script Python convertește fiecare fișier
.mdîn JSON Portable Text - Publicare, apeluri API către Sanity: creare document, încărcare imagini, patch referințe
Fiecare document are un câmp language și o referință canonicalPost care indică spre originalul în engleză. Iată interogarea GROQ pentru a prelua o postare și toate traducerile sale:
// 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
}
}Partea de schemă este simplă, un câmp language cu un enum de limbi suportate:
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(),
})O capcană pe care am învățat-o pe pielea noastră: publicați mai întâi documentul în engleză, apoi patch-uiți referințele canonicalPost pe traduceri folosind ID-ul documentului publicat, nu prefixul drafts.. Sanity tratează documentele draft și cele publicate ca entități separate intern.
Pentru mai multe detalii despre cum se conectează acest pipeline la Model Context Protocol, vedeți secțiunea următoare.
Funcționalități AI Sanity: MCP, Canvas și Agent Context
Sanity se poziționează ca sistemul de operare pentru conținut al erei AI. Principalele funcționalități AI includ un server MCP pentru ca agenții AI să citească și să scrie conținut, Canvas pentru editarea asistată de AI în interiorul Studio-ului și Agent Context pentru ca agenții AI de producție să interogheze conținut structurat cu conștientizare a schemei.
Integrarea Serverului MCP
Serverul Sanity MCP permite agenților AI, Claude Code, Cursor, Windsurf și altora, să interacționeze programatic cu spațiul de lucru Sanity. Agenții pot citi scheme, executa interogări GROQ, crea documente și gestiona conținutul fără wrapper-e API personalizate.
Folosim serverul Sanity MCP zilnic în pipeline-ul nostru de conținut. Agenții noștri AI interoghează schema pentru a înțelege structura documentului, preiau postările existente pentru a găsi oportunități de link-building intern și publică documente noi. Protocolul MCP oferă agenților conștientizare a schemei; ei știu ce câmpuri există, ce tipuri se așteaptă și ce reguli de validare se aplică. Dacă construiți fluxuri de lucru agenți AI pentru afaceri, acesta este un model puternic.
Agent Context pentru AI de producție
Agent Context este o funcționalitate separată pentru integrări AI de grad de producție. Spre deosebire de serverul MCP (care este conceput pentru instrumente de dezvoltare), Agent Context oferă acces read-only, delimitat, pentru agenții AI care trebuie să interogheze conținutul dvs. la runtime, gândiți-vă la chatboți, motoare de recomandare sau sisteme de personalizare a conținutului.
Diferența contează: MCP este pentru fluxurile de lucru de build-time și editoriale (instrumente de dezvoltare conștiente de schemă), în timp ce Agent Context este pentru accesul la conținut la runtime cu autentificare adecvată și limitare a ratei.
Conținutul structurat al Sanity îi oferă un avantaj real aici. Un site WordPress stochează conținutul ca blob-uri HTML, un agent AI trebuie să parseze HTML-ul pentru a înțelege conținutul. Sanity stochează documente JSON tipizate cu scheme definite. Un agent poate interoga *[_type == "product" && category == "electronics"]{name, price, features} și poate primi înapoi date curate, structurate. Fără scraping, fără parsing, fără ghicit.
Cum folosim Sanity la Techsy
Aceasta nu este o secțiune ipotetică. Rulează Sanity CMS pe 4 site-uri de producție, publicând în 10 limbi cu un pipeline automatizat pe care l-am construit în ultimul an. Iată arhitectura.
Arhitectura pipeline-ului nostru de conținut
Pipeline-ul merge de la cercetare la postarea publicată în toate cele 10 limbi:
- Cercetare, analiză keyword, identificarea golurilor competitorilor, modele SERP
- Brief, specificație de scriere structurată cu ghidaj pe secțiuni, număr de cuvinte, link-uri interne
- Scriere, producere Markdown în engleză cu frontmatter YAML
- Conversie, script Python transformă Markdown în JSON Portable Text cu cele 5 tipuri de blocuri personalizate ale noastre
- Publicare, apeluri API către Sanity: document
createOrReplace, încărcare imagini pe CDN Sanity, patch referințe autor/categorie - Traducere, traducere AI în 9 limbi, verificată pentru completitudine
- Publicare traduceri, același flux de conversie/publicare per limbă, cu referința
canonicalPostpatch-uită la originalul în engleză
Schema personalizată suportă tipurile block, table, codeBlock, chartBlock și inlineImage, toate definite ca obiecte de schemă Sanity de producție cu reguli de validare. Printre instrumentele AI pentru startup-uri pe care le-am testat, acest pipeline bazat pe Sanity a fost cel mai fiabil pentru conținut structurat la scară.
Lecții din peste 400 de piese publicate
Câteva lucruri pe care ne-am fi dorit să ni le fi spus cineva:
Ordinea patch-uirii referințelor contează. Referințele Sanity nu pot indica documente care nu există încă. Publicați mai întâi postarea în engleză, apoi creați traducerile cu canonicalPost indicând spre ID-ul publicat al documentului în engleză. Am stricat acest lucru de câteva ori la început.
Implementarea schemei este per spațiu de lucru. Dacă rulați multiple proiecte Sanity (noi rulăm 4), trebuie să implementați schemele în fiecare separat: npx sanity@latest schema deploy per configurație de proiect.
Nivelul gratuit este real. Am rulat două dintre cele patru site-uri ale noastre pe planul gratuit timp de luni. 20 de utilizatori, 500K cereri API/lună, 100K cereri CDN, este suficient pentru un site de producție real, nu doar un proiect de jucărie.
Conversia Portable Text este gâtul de sticlă. Markdown în Portable Text nu este trivial. Liste imbricate, tabele în interiorul blockquote-urilor, blocuri de cod cu caractere speciale, cazuri marginale peste tot. Am iterat asupra scriptului nostru de conversie timp de luni.
Aveți nevoie de ajutor pentru a configura Sanity pentru proiectul dvs.? Am construit pipeline-uri de conținut multilingve pentru 4 site-uri de producție. Obțineți o consultație gratuită
Detalierea prețurilor Sanity CMS
Sanity oferă trei planuri: Free (20 de utilizatori, 500K cereri API/lună), Growth (15$/utilizator/lună cu roluri avansate și draft-uri programate) și Enterprise (prețuri personalizate cu SLA și funcționalități de conformitate). Nivelul gratuit este cel mai generos de pe piața CMS headless.
| Funcționalitate | Free | Growth (15$/utilizator/lună) | Enterprise |
|---|---|---|---|
| Utilizatori | 20 | 50 | Nelimitat |
| Cereri API | 500K/lună | 2.5M/lună | Personalizat |
| Cereri CDN | 100K/lună | 500K/lună | Personalizat |
| Roluri | Doar Admin | Admin, Developer, Editor, Contributor | Roluri personalizate |
| Colaborare | Editare în timp real | + Publicare programată, draft-uri | + Fluxuri de lucru |
| Suport | Comunitate | Dedicat + SLA | |
| Conformitate | , | , | SOC 2, HIPAA |
Pe nivelul gratuit, rulăm două dintre site-urile noastre fără a atinge limitele. Planul Growth la 15$/utilizator/lună a adăugat acces bazat pe roluri (important odată ce am avut editori non-tehnici) și publicare programată. Vizualizatorii sunt gratuiti pe Growth, ceea ce este un detaliu plăcut; nu sunteți penalizați pentru a oferi părților interesate acces de citire.
Cum se compară acest lucru cu competitorii?
| Funcționalitate | Sanity Free | Contentful Free | Strapi Cloud Free | Payload Cloud |
|---|---|---|---|---|
| Utilizatori | 20 | 1 | 1 | 1 |
| Tipuri de conținut | Nelimitat | 48 | Nelimitat | Nelimitat |
| Apeluri API | 500K/lună | Inclus | Inclus | Inclus |
| Tipuri personalizate | Da | Limitat | Da | Da |
| Preț pentru creștere | 15$/utilizator/lună | 300$/lună | 29$/lună | 50$/lună |
Nivelul gratuit cu 20 de utilizatori al Sanity este excepțional. Contentful vă limitează la 1 utilizator pe gratuit și sare la 300$/lună pentru planul lor Team. Dacă sunteți un startup sau o echipă mică, planul gratuit al Sanity vă permite să rulați sarcini de lucru reale de producție fără a cheltui nimic.
Sanity oferă, de asemenea, un program pentru startup-uri care oferă startup-urilor eligibile un an de acces gratuit la Growth. Merită să aplicați dacă vă calificați.
Întrebări frecvente
Ce este Sanity CMS și cum funcționează?
Sanity CMS este o platformă de conținut headless care stochează documente JSON structurate într-un backend gestionat numit Content Lake. Editați conținutul prin Sanity Studio (o aplicație React personalizabilă), îl interogați cu GROQ sau GraphQL și îl redați în orice framework frontend. Conținutul se sincronizează în timp real între toți clienții conectați.
Este Sanity CMS gratuit?
Da. Nivelul gratuit al Sanity include 20 de utilizatori, 500K cereri API pe lună și 100K cereri CDN, cel mai generos plan gratuit printre platformele CMS headless. Planul Growth costă 15$ per utilizator pe lună și adaugă acces bazat pe roluri, publicare programată și limite mai mari. Prețurile Enterprise sunt personalizate.
Care este diferența dintre Sanity și Contentful?
Sanity folosește schema-as-code (schemele trăiesc în baza ta de cod), GROQ pentru interogări și un Studio open-source complet personalizabil. Contentful folosește modelarea conținutului bazată pe GUI, GraphQL și un editor găzduit cu mai puțină personalizare. Nivelul gratuit al Sanity include 20 de utilizatori față de 1 la Contentful. Contentful are o piață de plugin-uri mai mare.
Este Sanity CMS bun pentru începători?
Sanity Studio este intuitiv pentru editorii de conținut, experiența de editare nu necesită cunoștințe tehnice. Cu toate acestea, configurarea schemelor necesită proficiență în JavaScript sau TypeScript. Sanity oferă documentație excelentă, șabloane de proiect și un Slack comunitar cu suport activ. Începeți cu npm create sanity@latest și un șablon de blog.
Pot să găzduiesc singur Sanity?
Sanity Studio este complet auto-găzduibil deoarece este o aplicație React open-source. Îl puteți implementa pe Vercel, Netlify sau orice provider de găzduire statică. Backend-ul Content Lake este un serviciu gestionat, nu există o opțiune de auto-găzduire pentru stratul de date. Acesta este un compromis: obțineți zero management de infrastructură, dar niciun control on-premises asupra datelor.
Ce tip de bază de date folosește Sanity?
Content Lake al Sanity nu este o bază de date SQL sau NoSQL tradițională. Este un magazin de documente gestionat care stochează conținutul ca JSON structurat cu un strat de interogare GROQ deasupra. Nu interacționați direct cu baza de date subiacentă, interacționați prin API-urile Sanity. Documentele au istoric complet al versiunilor și sincronizare în timp real integrate.
Este Sanity CMS open source?
Sanity Studio este open source sub licența MIT; îl puteți fork-ui, personaliza și auto-găzdui. Backend-ul Content Lake este SaaS proprietar. Specificația limbajului de interogare GROQ este, de asemenea, open source, publicată pe GitHub. Specificația Portable Text este, de asemenea, open source, menținută la portabletext.org.
Ce este Portable Text în Sanity?
Portable Text este specificația Sanity pentru text bogat structurat. În loc să stocheze conținutul ca șiruri HTML, reprezintă paragrafele, titlurile, imaginile și blocurile personalizate ca obiecte JSON tipizate într-un array. Acest lucru face conținutul portabil între framework-uri și platforme. Puteți defini tipuri de blocuri personalizate precum snippet-uri de cod, grafice și tabele cu propriile lor câmpuri structurate.
Ce este GROQ și cum diferă de GraphQL?
GROQ (Graph-Relational Object Queries) este limbajul nativ de interogare al Sanity. Sintaxa sa, *[filter]{projection}, este mai concisă decât GraphQL pentru datele Sanity, cu suport integrat pentru join-uri prin operatorul -> și câmpuri calculate. GraphQL este, de asemenea, disponibil pentru echipele care preferă instrumente standardizate sau folosesc deja Apollo Client.
Cum gestionează Sanity conținutul multilingv?
Sanity suportă localizarea la nivel de document (documente separate per limbă legate prin referințe canonice) și localizarea la nivel de câmp (câmpuri traduse într-un singur document). Nivelul de document este mai bun pentru SEO deoarece fiecare traducere primește propriul URL și metadate. Folosim localizarea la nivel de document pentru a publica în 10 limbi cu pipeline-uri automate de traducere și publicare.