Architettura del livello di contenuto: approfondimento sull'ingegneria di Sanity.io
Perché abbiamo scelto la sanità mentale invece del contenuto. Una guida tecnica ai contenuti strutturati, alle proiezioni GROQ, al testo portatile e alle pipeline di immagini.
Nell’ecosistema Headless Commerce, Shopify è il Database prodotti (PIM). Eccelle nella gestione di SKU, prezzi e inventario. È senza dubbio il peggiore Content Management System (CMS) del mondo. I modelli JSON “Negozio online 2.0” di Shopify sono rigidi. I metafield sono essenzialmente stringhe non tipizzate. Per creare una vetrina veramente dinamica e di lusso, è necessario un Content Lake dedicato.
Presso Maison Code Paris, abbiamo valutato ogni CMS Headless (Contentful, Strapi, Prismic). Abbiamo scelto Sanity.io. Questo articolo spiega il ragionamento tecnico, l’architettura e i dettagli di implementazione che ci consentono di creare “costruttori di pagine” che non infrangono il codice.
Perché Maison Code ne parla
In Maison Code Paris, agiamo come la coscienza architettonica dei nostri clienti. Spesso ereditiamo stack “moderni” costruiti senza una comprensione fondamentale della scala.
Discutiamo di questo argomento perché rappresenta un punto di svolta critico nella maturità ingegneristica. Implementarlo correttamente differenzia un MVP fragile da una piattaforma resiliente di livello aziendale.
La filosofia: contenuto come dati, non HTML
In WordPress o nei semplici CMS l’editor scrive “Pagine”. Hanno un editor WYSIWYG in cui mettono testo in grassetto, aggiungono immagini e essenzialmente scrivono BLOB HTML. Questa è Presentazione accoppiata. Se desideri riutilizzare quel contenuto su un’app iOS o una notifica WatchOS, sei bloccato nell’analisi delle stringhe HTML.
Sanity tratta i contenuti come Dati strutturati.
Una “Sezione Eroe” non è un <div>. È un oggetto JSON:
{
"_type": "eroe",
"intestazione": "Collezione estiva",
"cta": { "label": "Acquista ora", "link": "/collections/summer" },
"tema": "scuro"
}
Il frontend (React) decide come renderizzarlo. L’editor inserisce semplicemente l’intento.
Il livello di query: GROQ vs GraphQL
La maggior parte dei CMS headless offre un’API GraphQL. E’ buono. Sanity offre GROQ (query di oggetti grafico-relazionali). È eccezionale. Perché? Perché GROQ consente Proiezioni (rimodellamento lato client sul server).
Scenario: hai un documento dell’autore a cui fa riferimento un post. In GraphQL, lo schema determina la forma. In GROQ puoi rimodellarlo al volo:
// Ottieni tutti i post, ma rinomina 'author.name' in 'scriptBy'
*[_tipo == "post"] {
titolo,
"scriptBy": autore->nome,
"estimatedReadingTime": round(lunghezza(corpo) / 5 / 60) + " min"
}
Notare la matematica (“round”). Notare il dereferenziamento del puntatore (->).
Possiamo calcolare il “Tempo di lettura” sul livello del database. Possiamo unire i set di dati. Possiamo proiettare oggetti enormi in sottili DTO (Data Transfer Objects) perfettamente su misura per i nostri componenti React.
Ciò riduce la dimensione del payload del 40-70% rispetto alle query GraphQL standard che effettuano un recupero eccessivo.
Architettura: il lago dei contenuti
Sanity è un archivio documenti in tempo reale (ospitato su Google Cloud). Quando “Alex” digita un carattere in Studio, questo viene sincronizzato tramite WebSocket nel datastore in millisecondi. “Chloe” vede il cursore muoversi istantaneamente (stile Google Docs).
Questo risolve il problema più grande in Headless: Anteprima. Headless tradizionale richiede una “Build” (Next.js SSG) per vedere le modifiche. Ci vogliono 2 minuti. Gli editori lo odiano. Con Sanity + Hydrogen (Remix), ci iscriviamo al flusso di contenuti. L’anteprima è istantanea.
Il gancio di reazione
“tsx import { useQuery } da ‘@sanity/react-loader’;
funzione di esportazione useSanityQuery(query, params) { // Se all’interno dell’Iframe, utilizza i dati in tempo reale. Altrimenti usa i dati costruiti. const {dati} = useQuery(query, params); restituire i dati; }
## Testo portatile: risoluzione del problema "pericolosamenteSetInnerHTML".
Se consenti agli editor di scrivere HTML, danneggeranno il tuo sito. Incolleranno un tag "script". Utilizzeranno 5 tag "h1" (distruggendo il SEO).
Sanity utilizza **Testo portatile**. È una specifica basata su JSON per il rich text.
```json
[
{
"_type": "blocco",
"stile": "normale",
"bambini": [
{ "testo": "Ciao " },
{ "text": "Mondo", "marks": ["strong"] }
]
}
]
Lo rendiamo con un componente serializzatore. Questo ci dà il controllo totale.
“tsx importa { PortableText } da ‘@portabletext/react’;
componenti cost = { // Sostituisce il modo in cui viene eseguito il rendering di H1 blocco: { h1: ({bambini}) =>
{bambini}
, }, // Incorporamenti personalizzati tipi: { instagramPost: ({valore}) =>esporta const RichText = ({ contenuto }) => (
**Sicurezza**: non è possibile alcun XSS (Cross Site Scripting). La struttura è rigorosamente tipizzata.
## La pipeline di immagini
Le immagini sono la parte più pesante di qualsiasi sito di e-commerce.
Sanity ha un **CDN immagini** integrato.
Quando un editor carica un file TIFF da 50 MB, Sanity lo archivia.
L'API ci consente di richiederlo trasformato al volo.
`https://cdn.sanity.io/images/.../my-image.jpg?w=800&h=600&fit=crop&auto=format`
Costruiamo un componente "Immagine" riutilizzabile che sfrutta questo:
1. **Hotspot e Ritaglia**: l'editor imposta il "Punto focale" sul viso del modello. Se ritagliamo in un quadrato, la faccia viene centrata automaticamente.
2. **Formattazione automatica**: trasmette AVIF a Chrome, WebP a Safari, JPEG a legacy.
3. **LQIP (segnaposto immagine di bassa qualità)**: i metadati includono una stringa di sfocatura codificata base64. Lo mostriamo immediatamente mentre viene caricata l'immagine principale.
"tsx
// urlBuilder.ts
importa imageUrlBuilder da '@sanity/image-url';
const builder = imageUrlBuilder(client);
funzione di esportazione urlFor(fonte) {
return builder.image(source).auto('format').fit('max');
}
Ingegneria degli schemi: validazioni
Trattiamo i modelli di contenuto come schemi di database. Applichiamo le regole. “Una recensione del prodotto deve avere un punteggio compreso tra 1 e 5.”
“dattiloscritto”. // schemi/review.ts defineField({ nome: ‘valutazione’, tipo: ‘numero’, convalida: (Regola) => Regola.required().min(1).max(5).error(“La valutazione deve essere 1-5”) })
Questa convalida viene eseguita in Studio. L'editor fisicamente non può pubblicare dati errati. Il codice frontend non deve mai gestire "rating: 200".
## Internazionalizzazione (i18n)
I marchi di lusso sono globali.
Ci sono due strategie in Sanity:
1. **Livello campo**:
`{ titolo: { it: "Ciao", fr: "Bonjour" } }`
* *Pro*: mantiene tutto in un unico documento. Buono per layout forti e coerenti.
* *Contro*: il documento diventa enorme.
2. **Livello documento**:
Documento "Title_EN" e documento "Title_FR".
* *Pro*: Libertà totale per mercato. La pagina francese può avere sezioni diverse rispetto alla pagina americana.
* *Contro*: Più difficile gestire la sincronizzazione.
In genere consigliamo il **Livello di campo** per "Contenuti globali" (descrizioni dei prodotti) e il **Livello di documento** per "Pagine di marketing" (le campagne spesso differiscono in base alla regione).
## 10. Sanity Connect per Shopify (sincronizzazione)
Non vuoi copiare e incollare i titoli dei prodotti da Shopify a Sanity.
Utilizziamo **Sanity Connect**.
Ascolta Shopify Webhooks.
Quando i prezzi vengono aggiornati in Shopify -> Sincronizza con Sanity.
Ma lo rendiamo **Sola lettura** in Sanity.
L'editor vede i dati del prodotto, può farvi riferimento in un Lookbook, ma non può modificare il prezzo.
Ciò mantiene la "Fonte unica della verità" (Shopify) arricchendo al contempo il "Livello di presentazione" (Sanity).
## 11. Dashboard di Studio personalizzate
Il CMS è la casa destinata al team di marketing.
Realizziamo widget dashboard personalizzati in Studio.
1. **Widget Google Analytics**: "I 5 migliori post del blog di questa settimana".
2. **Widget Shopify**: "Ticker delle vendite in tempo reale".
3. **Stato build Vercel**: "Il sito è in fase di distribuzione?".
Ciò trasforma il CMS in un centro di comando, riducendo la necessità di accedere a 5 strumenti diversi.
## 13. Strategie di migrazione: WordPress verso Sanity
La migrazione di 5.000 post di blog da WordPress è spaventosa.
Non utilizziamo "Plugin di importazione". Scriviamo script.
1. **Estrai**: Connettiti all'API REST WP. Estrai tutti i post.
2. **Trasforma**: Converti corpo HTML -> Testo portatile (usando `@portabletext/to-portabletext`).
* Questo converte i tag `<b>` in `marks`.
* Scarica le immagini, le carica su Sanity Asset Pipeline e sostituisce `<img>` src con il nuovo Asset Reference.
3. **Carica**: scrittura transazionale (100 documenti per transazione).
Risultato: un set di dati pulito e strutturato da una zuppa HTML disordinata.
## 14. Il concetto di "lago di contenuti".
Perché chiamarlo "Lago"?
Perché ci butti dentro tutto.
Prodotti. Profili del personale. Sedi dei negozi. Politiche legali.
In un CMS tradizionale, questi sono isolati.
In Sanity, sono solo documenti.
Puoi collegare una "Posizione del negozio" a un "Profilo del personale" a un "Prodotto".
"Questo prodotto è disponibile nel negozio di Parigi, gestito da Chloe."
Questa funzionalità **Grafico** consente esperienze frontend incredibilmente ricche che WordPress non può modellare.
## 15. Conclusione
La sanità mentale ci consente di disaccoppiare il "Cosa" (Contenuto) dal "Come" (Presentazione).
Trasforma il CMS da collo di bottiglia in API.
Per uno sviluppatore, interrogare i contenuti con GROQ sembra un superpotere. Per un editore, vedere le modifiche dal vivo senza premere "Aggiorna" sembra una magia.
<hr style="margin: 1rem 0" />
### Non sei soddisfatto del tuo CMS?
Se il tuo team di marketing interrompe il layout ogni volta che pubblica un post sul blog.
**[Migrare a Sanity](/contatto)**.
**[Assumi i nostri architetti](/contact)**.