
Guida a Sanity CMS: Come Pubblichiamo in 10 Lingue
Abbiamo pubblicato oltre 400 contenuti su 4 siti e 10 lingue tramite Sanity CMS. Ecco quello che abbiamo imparato — dal design dello schema alla pubblicazione multilingue automatizzata.
Sanity CMS è una piattaforma di contenuti headless costruita intorno a contenuti strutturati, un Content Lake in tempo reale e un editor basato su React personalizzabile chiamato Sanity Studio. Usa GROQ per le query, Portable Text per i contenuti ricchi e schema-as-code per la modellazione dei contenuti. Questa guida copre configurazione, design dello schema, GROQ, Portable Text, architettura multilingue e prezzi.
Cos'è Sanity CMS?
Sanity è una piattaforma di contenuti strutturati — quello che il team di Sanity.io chiama un "sistema operativo per i contenuti". A differenza dei CMS tradizionali che archiviano blob HTML in un database, Sanity archivia ogni contenuto come JSON strutturato in un backend gestito chiamato Content Lake. Lo interroghi con GROQ o GraphQL, e rendi il contenuto in qualsiasi frontend tu voglia: Next.js, React Native, Svelte, un'app mobile, uno strumento CLI — qualsiasi cosa.
Le aziende che lo usano coprono l'intero spettro. Nike, Figma, Puma e Cloudflare usano Sanity su scala enterprise. Le startup lo usano perché il piano gratuito è genuinamente utilizzabile (più avanti sui prezzi). Noi lo usiamo perché nient'altro ci ha dato la flessibilità per costruire una pipeline di pubblicazione completamente automatizzata in 10 lingue.
Architettura del Content Lake
Il Content Lake è il backend gestito di Sanity. Pensalo come un document store ospitato che si sincronizza in tempo reale su tutti i client connessi. Quando un editor cambia un paragrafo in Sanity Studio, un altro editor lo vede immediatamente — nessun pulsante di salvataggio, nessun conflitto di merge, nessuna migrazione del database.
Internamente, i documenti sono archiviati come JSON strutturato con campi tipizzati. Ogni mutazione viene tracciata tramite un log delle transazioni, quindi ottieni la cronologia completa delle versioni per impostazione predefinita. La sincronizzazione in tempo reale usa un'architettura basata su listener (descritta nella documentazione sull'architettura di Sanity su GitHub) che invia le modifiche a tutti gli abbonati tramite osservabili RxJS.
Cosa rende questo diverso da, diciamo, un database PostgreSQL con un'API REST? Il Content Lake gestisce modellazione dei contenuti, controllo degli accessi, caching CDN, trasformazioni delle immagini e collaborazione in tempo reale come servizio gestito unico. Non esegui migrazioni. Non gestisci repliche. Definisci solo schemi e interroghi i contenuti.
Sanity Studio: il Tuo Editor Personalizzabile
Sanity Studio è un'applicazione React open source che funge da interfaccia di editing. Non è un pannello di amministrazione ospitato — è un'app React che vive nel tuo codebase. Puoi personalizzare ogni aspetto: componenti di input personalizzati, campi condizionali, azioni sui documenti, pattern di structure builder e plugin.
La collaborazione in tempo reale è integrata. Più editor possono lavorare sullo stesso documento contemporaneamente con indicatori di presenza e aggiornamenti live. Se hai usato Google Docs, l'esperienza è simile — vedi i cursori e le modifiche degli altri in tempo reale.
Distribuiamo il nostro Studio con npx sanity deploy, che lo ospita sul CDN di Sanity a un sottodominio personalizzato. Puoi anche auto-ospitarlo dato che è solo un'app React. Abbiamo valutato Sanity molto in alto nel nostro confronto tra CMS headless soprattutto per la flessibilità di Studio.
Come Configurare un Progetto Sanity
Per configurare Sanity CMS, installa la CLI con npm create sanity@latest, scegli un template di progetto, configura i file dello schema ed esegui npx sanity dev per avviare Studio in locale. L'intero processo richiede meno di 5 minuti.
Prerequisiti e Installazione
Hai bisogno di Node.js 18+ e npm (o pnpm). Tutto qui. Esegui il comando di init:
npm create sanity@latest
# Ti verrà chiesto:
# - Metodo di login (Google, GitHub, email)
# - Nome del progetto
# - Nome del dataset (default: "production")
# - Template del progetto (blog, ecommerce, clean)
# - TypeScript? (consigliato: sì)La CLI crea un progetto con tutto il necessario. Ecco com'è strutturata la cartella del progetto:
Struttura del Progetto Spiegata
my-sanity-project/
├── schemas/ # I tuoi schemi di contenuto (qui passerai il tempo)
│ ├── index.ts # Registro degli schemi -- importa ed esporta tutti i tipi
│ ├── post.ts # Definizioni dei tipi di documento
│ └── blockContent.ts # Configurazione del testo ricco / Portable Text
├── sanity.config.ts # Config principale -- plugin, struttura Studio, dataset
├── sanity.cli.ts # Config CLI -- project ID, dataset
├── package.json
└── tsconfig.jsonIl file sanity.config.ts è il tuo punto di ingresso. Ecco uno minimale:
// 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 },
})Il plugin visionTool() ti dà un playground GROQ all'interno di Studio — lo userai costantemente durante lo sviluppo.
Distribuire il Tuo Studio
Avvia in locale con npx sanity dev (gira su localhost:3333). Quando sei pronto a condividerlo con gli editor, distribuiscilo sul CDN di Sanity:
npx sanity deploy
# Chiede un hostname, es. "my-blog"
# Distribuisce su https://my-blog.sanity.studioPro tip: esegui npx sanity@latest schema deploy dopo ogni modifica allo schema. Questo carica il tuo schema sull'API di Sanity, abilitando funzionalità come l'API GraphQL e gli strumenti schema-aware (incluso il server MCP che tratteremo più avanti).
Design dello Schema in Sanity CMS
Gli schemi di Sanity sono definiti come oggetti JavaScript o TypeScript nel tuo codebase. Ogni schema specifica un tipo di documento con campi, regole di validazione e componenti di input personalizzati. Le modifiche agli schemi sono immediate — nessuna migrazione del database richiesta. Questo è l'approccio "schema-as-code", ed è quello che ci ha convinto a scegliere Sanity rispetto a Contentful.
Tipi di Campo e Validazione
Sanity include un ricco set di tipi di campo. Ecco quelli che usiamo di più:
| Tipo di campo | Caso d'uso | Esempio |
|---|---|---|
string | Testo breve, titoli, slug | Titolo del post, nome dell'autore |
text | Testo semplice su più righe | Estratti, descrizioni |
number | Interi, float | Tempo di lettura, ordinamento |
boolean | Toggle | Flag in evidenza, stato bozza |
array | Liste, testo ricco (Portable Text) | Corpo del contenuto, tag |
reference | Link ad altri documenti | Autore, categoria |
image | Immagini con metadati | Immagine di copertina con testo alternativo |
slug | Stringhe URL-friendly | Generato automaticamente dal titolo |
object | Gruppi di campi annidati | Campi SEO (metaTitle + metaDescription) |
date / datetime | Date | Data di pubblicazione |
Ogni campo supporta la validazione tramite un callback validation. Puoi applicare campi obbligatori, valori min/max, pattern regex e regole personalizzate:
defineField({
name: 'seoDescription',
title: 'Meta Description',
type: 'string',
validation: (Rule) =>
Rule.required()
.min(145)
.max(160)
.warning('Meta description should be 145-160 characters'),
})Tipi di Blocco Personalizzati (i Nostri Esempi in Produzione)
Qui Sanity diventa interessante — e dove 0 su 6 guide concorrenti mostrano codice reale. Nel nostro schema in produzione, definiamo cinque tipi di blocco personalizzati all'interno dell'array body: block (testo standard), table, codeBlock, chartBlock e inlineImage.
Ecco la nostra definizione di 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',
},
],
})Ed ecco come il campo body fa riferimento a tutti i nostri tipi personalizzati insieme:
// schemas/fields/body.ts
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [
{ type: 'block' }, // Portable Text standard (paragrafi, titoli, liste)
{ type: 'table' }, // Plugin @sanity/table
{ type: 'codeBlock' }, // Il nostro blocco di codice personalizzato
{ type: 'chartBlock' }, // Visualizzazione dati (barre, linee, torta)
{ type: 'inlineImage' }, // Immagini con testo alternativo e didascalie
],
})Questo dà ai nostri editor un toolkit di contenuti ricco mantenendo ogni elemento tipizzato e interrogabile. Un chartBlock non è solo un embed HTML opaco — è un dato strutturato con campi chartType, title, dataPoints e dataLabels. Questo conta quando cerchi di rendere lo stesso contenuto su web, email e mobile.
Buone Pratiche nell'Organizzazione degli Schemi
Mantieni gli schemi modulari. Noi li dividiamo in file per tipo: schemas/documents/post.ts, schemas/objects/codeBlock.ts, schemas/objects/chartBlock.ts. Importali tutti in 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]L'intuizione chiave che abbiamo guadagnato lavorando con contenuti strutturati: il tuo schema È il tuo modello di contenuto. Se lo pensi come context engineering per il tuo team di contenuti, prenderai decisioni di design migliori. Ogni campo che aggiungi dovrebbe avere uno scopo — per gli editor, per il rendering o per le query.
GROQ: il Linguaggio di Query di Sanity
GROQ (Graph-Relational Object Queries) è il linguaggio di query open source di Sanity per filtrare, unire e proiettare documenti JSON. La sintassi di base è *[filter]{projection} — seleziona tutti i documenti che corrispondono a un filtro, poi modella l'output. È più conciso di GraphQL per le query specifiche di Sanity e, dalla nostra esperienza, più veloce da imparare.
Query di Base: Filtro e Proiezione
La query più semplice recupera tutti i documenti di un tipo:
// Recupera tutti i post -- solo titolo e slug
*[_type == "post"]{
title,
"slug": slug.current
}
// Filtra per lingua, espandi il riferimento all'autore
*[_type == "post" && language == "en"]{
title,
"slug": slug.current,
"authorName": author->name,
"authorImage": author->image,
"categoryTitle": category->title,
publishedAt
}L'operatore -> segue i riferimenti. author->name significa "segui il riferimento all'autore e restituisci il campo name". Nessuna query separata, nessun problema N+1, nessun JOIN — è tutto un'unica espressione.
Join, Ordinamento e Paginazione
Per le nostre pagine di indice del blog, abbiamo bisogno di post ordinati e paginati con riferimenti espansi:
// Post paginati con metadati completi
*[_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] restituisce i primi 10 risultati (indicizzazione 0, fine esclusiva). | order(publishedAt desc) ordina dal più recente. La proiezione modella l'output per includere esattamente quello di cui ha bisogno il tuo frontend — niente di più.
Puoi testare tutte queste query interattivamente usando il plugin Vision all'interno di Sanity Studio. È indispensabile durante lo sviluppo. Per altri pattern, consulta il cheat sheet GROQ.
GROQ vs GraphQL
Sanity supporta sia GROQ che GraphQL. Quando usare l'uno o l'altro?
GROQ è il linguaggio nativo di Sanity. Gestisce join, proiezioni e campi calcolati in una singola stringa di query. È quello per cui il Content Lake è ottimizzato.
GraphQL è disponibile dopo aver distribuito il tuo schema (npx sanity@latest schema deploy). Usalo quando hai bisogno di strumenti standardizzati — per esempio, se il tuo frontend usa già Apollo Client o se il tuo team conosce GraphQL ma non GROQ.
Noi usiamo esclusivamente GROQ. È più espressivo per i dati Sanity, e il plugin Vision rende il debug delle query elementare.
Portable Text: Contenuti Ricchi Fatti Bene
Portable Text è la specifica di Sanity per il testo ricco strutturato. Invece di archiviare il contenuto come stringhe HTML, archivia un array di blocchi tipizzati — paragrafi, titoli, immagini, snippet di codice, tabelle — ciascuno come oggetto JSON. Questo rende il contenuto renderizzabile in qualsiasi framework, qualsiasi piattaforma, qualsiasi formato.
La Struttura dei Dati
Ecco come appaiono un paragrafo e un blocco di codice come 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({ ... })"
}
]Ogni blocco ha un _type e una _key. I blocchi di testo standard usano "block" con span figlio (che supportano mark come grassetto, corsivo e link). I blocchi personalizzati — come il nostro codeBlock, chartBlock, table e inlineImage — usano il proprio _type e portano campi strutturati.
Perché questo è importante? Perché HTML è un formato di rendering, non di archiviazione. Se archivi <h2>Titolo</h2><p>Un po' di <strong>testo</strong></p> nel tuo database, ti sei vincolato al rendering web. Non puoi estrarlo in modo pulito per un'app mobile, una newsletter email, un PDF o la finestra di contesto di un agente AI. Portable Text separa il contenuto dalla presentazione. La specifica Portable Text è open source — non è un lock-in di Sanity.
Blocchi Personalizzati in Produzione
La nostra pipeline converte Markdown in Portable Text usando uno script Python (scripts/md_to_portable_text.py). Il convertitore gestisce blocchi standard, più i nostri quattro tipi personalizzati:
table-- usa lo schema del plugin@sanity/table. Righe e celle archiviate come dati strutturati.codeBlock-- linguaggio e codice come campi separati, abilitando l'evidenziazione della sintassi al rendering.chartBlock-- tipo di grafico, titolo, etichette degli assi, nomi delle serie e punti dati come JSON strutturato. Il frontend li renderizza con Chart.js.inlineImage-- testo alternativo, sorgente e didascalia opzionale come campi separati.
Questa struttura significa che possiamo interrogare tutti gli esempi di codice nel nostro blog (*[body[]._type == "codeBlock"]), trovare post con grafici, o estrarre tutte le immagini con testo alternativo mancante — tutto tramite GROQ.
Renderizzare il Portable Text
Sul frontend, usa @portabletext/react (o gli equivalenti Svelte/Vue). Registri componenti personalizzati per ogni tipo di blocco:
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>
),
},
}
// Nel tuo componente:
<PortableText value={post.body} components={components} />Questa è la pipeline di rendering completa. Il componente PortableText gestisce automaticamente i blocchi standard (paragrafi, titoli, liste, mark). Definisci componenti personalizzati solo per i tuoi tipi personalizzati.
Contenuti Multilingue con Sanity CMS
Sanity supporta contenuti multilingue tramite localizzazione a livello di documento (documenti separati per lingua collegati da un riferimento canonico) o localizzazione a livello di campo (campi tradotti all'interno di un unico documento). La localizzazione a livello di documento funziona meglio per SEO e pubblicazione su larga scala — è quella che usiamo nella nostra pipeline in 10 lingue.
Localizzazione a Livello di Documento vs. a Livello di Campo
| Aspetto | Livello di documento | Livello di campo |
|---|---|---|
| Approccio | Documento separato per lingua | Tutte le traduzioni in un documento |
| SEO | Ogni documento ha il proprio URL/slug | URL unico, più difficile servire pagine per lingua |
| Complessità delle query | Filtri semplici: language == "de" | Accesso a campi annidati: title.de |
| Dimensione del contenuto | Documenti piccoli e focalizzati | Un documento grande con tutte le lingue |
| Ideale per | Post del blog, pagine, contenuti SEO | Stringhe UI, etichette, metadati |
| Il nostro verdetto | Lo usiamo per tutto | Solo per stringhe UI condivise |
Abbiamo scelto la localizzazione a livello di documento perché ogni traduzione ottiene il proprio slug, il proprio URL e i propri metadati. La versione turca di un post su Supabase vs Firebase ottiene lo slug supabase-firebase-karsilastirma — turco corretto, non un hack con parametri URL.
La Nostra Architettura di Pipeline in 10 Lingue
Ecco come funziona la nostra pipeline automatizzata: scriviamo un post in inglese, poi lo traduciamo in 9 lingue aggiuntive (tedesco, francese, olandese, spagnolo, turco, italiano, svedese, norvegese, arabo). Ogni traduzione passa attraverso conversione Markdown, generazione Portable Text e pubblicazione tramite API Sanity.
L'architettura funziona così:
- Scrivi -- Markdown inglese con frontmatter YAML
- Traduci -- Traduzione AI in 9 lingue (verificata per completezza e diacritici)
- Converti -- Script Python trasforma ogni file
.mdin JSON Portable Text - Pubblica -- Chiamate API a Sanity: crea documento, carica immagini, patch dei riferimenti
Ogni documento ha un campo language e un riferimento canonicalPost che punta all'originale inglese. Ecco la query GROQ per recuperare un post e tutte le sue traduzioni:
// Recupera un post e tutte le sue traduzioni
*[_type == "post" && slug.current == "sanity-cms-guide" && language == "en"][0]{
title,
language,
"translations": *[
_type == "post" &&
canonicalPost._ref == ^._id
]{
title,
language,
"slug": slug.current
}
}Il lato schema è semplice — un campo language con un enum delle lingue supportate:
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(),
})Una cosa che abbiamo imparato a nostre spese: pubblica prima il documento inglese, poi applica i riferimenti canonicalPost sulle traduzioni usando l'ID del documento pubblicato — non il prefisso drafts.. Sanity tratta internamente i documenti in bozza e quelli pubblicati come entità separate.
Per maggiori dettagli su come questa pipeline si collega al Model Context Protocol, vedi la sezione successiva.
Funzionalità AI di Sanity: MCP, Canvas e Agent Context
Sanity si posiziona come il sistema operativo per i contenuti nell'era dell'AI. Le funzionalità AI principali includono un server MCP per far leggere e scrivere contenuti agli agenti AI, Canvas per l'editing assistito da AI all'interno di Studio, e Agent Context per agenti AI in produzione che interrogano contenuti strutturati con consapevolezza dello schema.
Integrazione con il Server MCP
Il server MCP di Sanity permette agli agenti AI — Claude Code, Cursor, Windsurf e altri — di interagire programmaticamente con il tuo workspace Sanity. Gli agenti possono leggere schemi, eseguire query GROQ, creare documenti e gestire contenuti senza wrapper API personalizzati.
Usiamo il server MCP di Sanity quotidianamente nella nostra pipeline di contenuti. I nostri agenti AI interrogano lo schema per capire la struttura dei documenti, recuperano post esistenti per trovare opportunità di link interni e pubblicano nuovi documenti. Il protocollo MCP dà agli agenti la consapevolezza dello schema — sanno quali campi esistono, quali tipi si aspettano e quali regole di validazione si applicano. Se stai costruendo agenti AI per le aziende, questo è un pattern potente.
Agent Context per AI in Produzione
Agent Context è una funzionalità separata per integrazioni AI di livello produttivo. A differenza del server MCP (progettato per strumenti per sviluppatori), Agent Context fornisce accesso in sola lettura e con scope limitato per agenti AI che devono interrogare i tuoi contenuti a runtime — pensa a chatbot, motori di raccomandazione o sistemi di personalizzazione dei contenuti.
La differenza conta: MCP è per flussi di lavoro di build-time ed editoriali (strumenti di sviluppo schema-aware), mentre Agent Context è per l'accesso ai contenuti a runtime con autenticazione appropriata e rate limiting.
I contenuti strutturati di Sanity gli danno un vantaggio reale qui. Un sito WordPress archivia i contenuti come blob HTML — un agente AI deve fare il parsing dell'HTML per capire il contenuto. Sanity archivia documenti JSON tipizzati con schemi definiti. Un agente può interrogare *[_type == "product" && category == "electronics"]{name, price, features} e ricevere dati strutturati e puliti. Niente scraping, niente parsing, niente indovinare.
Come Usiamo Sanity a Techsy
Questa non è una sezione ipotetica. Gestiamo Sanity CMS su 4 siti in produzione, pubblicando in 10 lingue con una pipeline automatizzata che abbiamo costruito nell'ultimo anno. Ecco l'architettura.
L'Architettura della Nostra Pipeline di Contenuti
La pipeline va dalla ricerca al post pubblicato in tutte e 10 le lingue:
- Ricerca -- analisi delle keyword, identificazione dei gap rispetto ai concorrenti, pattern SERP
- Brief -- specifica di scrittura strutturata con guida alle sezioni, conteggio parole, link interni
- Scrittura -- produzione del Markdown inglese con frontmatter YAML
- Conversione -- script Python trasforma Markdown in JSON Portable Text con i nostri 5 tipi di blocco personalizzati
- Pubblicazione -- chiamate API a Sanity: documento
createOrReplace, carica immagini sul CDN Sanity, patch dei riferimenti autore/categoria - Traduzione -- traduzione AI in 9 lingue, verificata per completezza
- Pubblicazione delle traduzioni -- stesso flusso di conversione/pubblicazione per lingua, con riferimento
canonicalPostpatchato sull'originale inglese
Lo schema personalizzato supporta i tipi block, table, codeBlock, chartBlock e inlineImage — tutti definiti come oggetti schema Sanity in produzione con regole di validazione. Tra i migliori strumenti AI per le startup che abbiamo testato, questa pipeline basata su Sanity è stata la più affidabile per contenuti strutturati su larga scala.
Lezioni da 400+ Pezzi Pubblicati
Alcune cose che avremmo voluto qualcuno ci dicesse:
L'ordine dei patch dei riferimenti è importante. I riferimenti Sanity non possono puntare a documenti che non esistono ancora. Pubblica prima il post inglese, poi crea le traduzioni con canonicalPost che punta all'ID pubblicato del documento inglese. L'abbiamo fatto male diverse volte all'inizio.
La distribuzione dello schema è per-workspace. Se gestisci più progetti Sanity (ne gestiamo 4), devi distribuire gli schemi a ciascuno separatamente: npx sanity@latest schema deploy per ogni configurazione di progetto.
Il piano gratuito è reale. Abbiamo gestito due dei nostri quattro siti sul piano gratuito per mesi. 20 utenti, 500K richieste API/mese, 100K richieste CDN — è abbastanza per un vero sito in produzione, non solo un progetto giocattolo.
La conversione Portable Text è il collo di bottiglia. Da Markdown a Portable Text non è banale. Liste annidate, tabelle all'interno di blockquote, blocchi di codice con caratteri speciali — edge case ovunque. Abbiamo iterato sul nostro script di conversione per mesi.
Hai bisogno di aiuto per configurare Sanity per il tuo progetto? Abbiamo costruito pipeline di contenuti multilingue per 4 siti in produzione. Ottieni una consulenza gratuita
Prezzi di Sanity CMS
Sanity offre tre piani: Free (20 utenti, 500K richieste API/mese), Growth ($15/utente/mese con ruoli avanzati e bozze pianificate) ed Enterprise (prezzi personalizzati con SLA e funzionalità di conformità). Il piano gratuito è il più generoso nel mercato dei CMS headless.
| Funzionalità | Free | Growth ($15/utente/mese) | Enterprise |
|---|---|---|---|
| Utenti | 20 | 50 | Illimitati |
| Richieste API | 500K/mese | 2,5M/mese | Personalizzato |
| Richieste CDN | 100K/mese | 500K/mese | Personalizzato |
| Ruoli | Solo admin | Admin, Developer, Editor, Contributor | Ruoli personalizzati |
| Collaborazione | Editing in tempo reale | + Pubblicazione pianificata, bozze | + Workflow |
| Supporto | Community | Dedicato + SLA | |
| Conformità | -- | -- | SOC 2, HIPAA |
Sul piano gratuito, gestiamo due dei nostri siti senza raggiungere i limiti. Il piano Growth a $15/utente/mese ha aggiunto il controllo degli accessi basato su ruoli (importante una volta che avevamo editor non tecnici) e la pubblicazione pianificata. I viewer sono gratuiti su Growth, un bel vantaggio — non vieni penalizzato per dare agli stakeholder accesso in lettura.
Come si confronta con i concorrenti?
| Funzionalità | Sanity Free | Contentful Free | Strapi Cloud Free | Payload Cloud |
|---|---|---|---|---|
| Utenti | 20 | 1 | 1 | 1 |
| Tipi di contenuto | Illimitati | 48 | Illimitati | Illimitati |
| Chiamate API | 500K/mese | Incluse | Incluse | Incluse |
| Tipi personalizzati | Sì | Limitati | Sì | Sì |
| Prezzo per crescere | $15/utente/mese | $300/mese | $29/mese | $50/mese |
Il piano gratuito di Sanity con 20 utenti è eccezionale. Contentful ti limita a 1 utente nel piano gratuito e passa a $300/mese per il piano Team. Se sei una startup o un piccolo team, il piano gratuito di Sanity ti permette di gestire veri carichi di lavoro in produzione senza spendere nulla.
Sanity offre anche un programma per startup che dà alle startup idonee un anno di accesso Growth gratuito. Vale la pena candidarsi se hai i requisiti.
Domande Frequenti
Cos'è Sanity CMS e come funziona?
Sanity CMS è una piattaforma di contenuti headless che archivia documenti JSON strutturati in un backend gestito chiamato Content Lake. Modifichi i contenuti tramite Sanity Studio (un'app React personalizzabile), li interroghi con GROQ o GraphQL e li renderizzi in qualsiasi framework frontend. I contenuti si sincronizzano in tempo reale su tutti i client connessi.
Sanity CMS è gratuito?
Sì. Il piano gratuito di Sanity include 20 utenti, 500K richieste API al mese e 100K richieste CDN — il piano gratuito più generoso tra le piattaforme CMS headless. Il piano Growth costa $15 per utente al mese e aggiunge accesso basato su ruoli, pubblicazione pianificata e limiti più alti. Il prezzo Enterprise è personalizzato.
Qual è la differenza tra Sanity e Contentful?
Sanity usa schema-as-code (gli schemi vivono nel tuo codebase), GROQ per le query e uno Studio open source completamente personalizzabile. Contentful usa la modellazione dei contenuti tramite GUI, GraphQL e un editor ospitato con meno personalizzazione. Il piano gratuito di Sanity include 20 utenti contro 1 di Contentful. Contentful ha un marketplace di plugin più grande.
Sanity CMS è adatto ai principianti?
Sanity Studio è intuitivo per gli editor di contenuti — l'esperienza di editing non richiede conoscenze tecniche. Tuttavia, la configurazione degli schemi richiede competenza in JavaScript o TypeScript. Sanity offre un'ottima documentazione, template di progetto e uno Slack della community con supporto attivo. Inizia con npm create sanity@latest e un template blog.
Posso auto-ospitare Sanity?
Sanity Studio è completamente auto-ospitabile perché è un'applicazione React open source. Puoi distribuirlo su Vercel, Netlify o qualsiasi provider di hosting statico. Il backend Content Lake è un servizio gestito — non c'è opzione di auto-ospitaggio per il layer dei dati. È un compromesso: ottieni zero gestione dell'infrastruttura ma nessun controllo sui dati on-premises.
Che tipo di database usa Sanity?
Il Content Lake di Sanity non è un database SQL o NoSQL tradizionale. È un document store gestito che archivia contenuti come JSON strutturato con un layer di query GROQ sopra. Non interagisci direttamente con il database sottostante — interagisci tramite le API di Sanity. I documenti hanno la cronologia completa delle versioni e la sincronizzazione in tempo reale integrate.
Sanity CMS è open source?
Sanity Studio è open source sotto licenza MIT — puoi farne un fork, personalizzarlo e auto-ospitarlo. Il backend Content Lake è un SaaS proprietario. Anche la specifica del linguaggio di query GROQ è open source, pubblicata su GitHub. Anche la specifica Portable Text è open source, mantenuta su portabletext.org.
Cos'è il Portable Text in Sanity?
Portable Text è la specifica di Sanity per il testo ricco strutturato. Invece di archiviare i contenuti come stringhe HTML, rappresenta paragrafi, titoli, immagini e blocchi personalizzati come oggetti JSON tipizzati in un array. Questo rende i contenuti portabili tra framework e piattaforme. Puoi definire tipi di blocco personalizzati come snippet di codice, grafici e tabelle con i propri campi strutturati.
Cos'è GROQ e in cosa differisce da GraphQL?
GROQ (Graph-Relational Object Queries) è il linguaggio di query nativo di Sanity. La sua sintassi — *[filter]{projection} — è più concisa di GraphQL per i dati Sanity, con supporto integrato per i join tramite l'operatore -> e i campi calcolati. GraphQL è disponibile anche per i team che preferiscono strumenti standardizzati o usano già Apollo Client.
Come gestisce Sanity i contenuti multilingue?
Sanity supporta la localizzazione a livello di documento (documenti separati per lingua collegati da riferimenti canonici) e la localizzazione a livello di campo (campi tradotti all'interno di un unico documento). La localizzazione a livello di documento è migliore per SEO perché ogni traduzione ottiene il proprio URL e metadati. Noi usiamo la localizzazione a livello di documento per pubblicare in 10 lingue con pipeline di traduzione e pubblicazione automatizzate.