MAISON CODE .
/ Headless CMS · Sanity · Backend · Architecture · Content Strategy

Diseño de la capa de contenido: análisis profundo de ingeniería de Sanity.io

Por qué elegimos Sanity en lugar de Contentful. Una guía técnica sobre contenido estructurado, proyecciones GROQ, texto portátil y canales de imágenes.

AB
Alex B.
Diseño de la capa de contenido: análisis profundo de ingeniería de Sanity.io

En el ecosistema de Headless Commerce, Shopify es la Base de datos de productos (PIM). Se destaca en la gestión de SKU, precios e inventario. Podría decirse que es el peor Sistema de gestión de contenidos (CMS) del mundo. Las plantillas JSON “Tienda online 2.0” de Shopify son rígidas. Los metacampos son esencialmente cadenas sin tipo. Para crear un escaparate de lujo verdaderamente dinámico, necesita un Content Lake dedicado.

En Maison Code Paris, evaluamos todos los CMS Headless (Contentful, Strapi, Prismic). Elegimos Sanity.io. Este artículo explica el razonamiento técnico, la arquitectura y los detalles de implementación que nos permiten crear “constructores de páginas” que no rompen el código.

Por qué Maison Code habla de esto

En Maison Code Paris, actuamos como la conciencia arquitectónica de nuestros clientes. A menudo heredamos stacks “modernos” construidos sin una comprensión fundamental de la escala.

Discutimos este tema porque representa un punto de inflexión crítico en la madurez de la ingeniería. Implementarlo correctamente diferencia un MVP frágil de una plataforma resistente de nivel empresarial.

La filosofía: contenido como datos, no HTML

En WordPress o CMS simples, el editor escribe “Páginas”. Tienen un editor WYSIWYG donde ponen texto en negrita, agregan imágenes y esencialmente escriben blobs HTML. Esta es Presentación acoplada. Si desea reutilizar ese contenido en una aplicación de iOS o una notificación de WatchOS, no podrá analizar cadenas HTML.

Sanity trata el contenido como Datos Estructurados. Una “Sección de héroe” no es una <div>. Es un objeto JSON:

{
  "_type": "héroe",
  "heading": "Colección de verano",
  "cta": { "label": "Comprar ahora", "link": "/colecciones/verano" },
  "tema": "oscuro"
}

El Frontend (React) decide cómo renderizar esto. El editor simplemente ingresa la intención.

La capa de consulta: GROQ vs GraphQL

La mayoría de los CMS sin cabeza ofrecen una API GraphQL. Es bueno. Sanity ofrece GROQ (Consultas de objetos relacionales de gráficos). Es excepcional. ¿Por qué? Porque GROQ permite Proyecciones (remodelación del lado del cliente en el servidor).

Escenario: Tienes un documento de autor al que hace referencia una publicación. En GraphQL, el esquema dicta la forma. En GROQ, puedes remodelarlo sobre la marcha:

// Obtener todas las publicaciones, pero cambiar el nombre de 'nombre.autor' a 'escrito por'
*[_type == "publicación"] {
  título,
  "escrito por": autor->nombre,
  "tiempo de lectura estimado": round(longitud(cuerpo) / 5/60) + "min"
}

Observe las matemáticas (redondo). Observe la desreferenciación del puntero (->). Podemos calcular el “Tiempo de lectura” en la capa de la base de datos. Podemos unir conjuntos de datos. Podemos proyectar objetos enormes en DTO (objetos de transferencia de datos) delgados perfectamente adaptados a nuestros componentes de React.

Esto reduce el tamaño de la carga útil entre un 40% y un 70% en comparación con las consultas GraphQL estándar que se recuperan en exceso.

Arquitectura: el lago de contenidos

Sanity es un Almacén de documentos en tiempo real (alojado en Google Cloud). Cuando “Alex” escribe un carácter en Studio, se sincroniza a través de WebSocket con el almacén de datos en milisegundos. “Chloe” ve el cursor moverse instantáneamente (estilo Google Docs).

Esto resuelve la mayor fricción en Headless: Vista previa. El modo Headless tradicional requiere una “compilación” (Next.js SSG) para ver los cambios. Eso lleva 2 minutos. Los editores lo odian. Con Sanity + Hydrogen (Remix), nos suscribimos al flujo de contenido. La vista previa es instantánea.

El gancho de reacción

importar {useQuery} desde '@sanity/react-loader';

función de exportación useSanityQuery (consulta, parámetros) {
    // Si está dentro del Iframe, use datos en vivo. De lo contrario, utilice datos creados.
    const {datos} = useQuery(consulta, parámetros);
    datos de devolución;
}

Texto portátil: Resolviendo el problema “peligrosamente SetInnerHTML”

Si permite que los editores escriban HTML, dañarán su sitio. Pegarán una etiqueta “script”. Usarán 5 etiquetas h1 (destruyendo el SEO). Sanity utiliza Texto portátil. Es una especificación basada en JSON para texto enriquecido.

[
  {
    "_type": "bloquear",
    "estilo": "normal",
    "niños": [
      { "texto": "Hola " },
      { "texto": "Mundo", "marcas": ["fuerte"] }
    ]
  }
]

Representamos esto con un componente serializador. Esto nos da un control total.

importar {PortableText} desde '@portabletext/react';

componentes constantes = {
  // Anula cómo se representa H1
  bloquear: {
    h1: ({niños}) => <h1 className="text-4xl font-bold track-tight">{niños}</h1>,
  },
  // Incrustaciones personalizadas
  tipos: {
    instagramPost: ({valor}) => <InstagramEmbed id={valor.url} />,
    tarjeta de producto: ({valor}) => <ID de tarjeta de producto={valor.productId} />
  }
};

exportar const Texto enriquecido = ({ contenido }) => (
    <Valor de TextoPortable={contenido} componentes={componentes} />
);

Seguridad: No es posible XSS (Cross Site Scripting). La estructura está estrictamente tipificada.

El canal de imágenes

Las imágenes son la parte más pesada de cualquier sitio de comercio electrónico. Sanity tiene un Image CDN incorporado. Cuando un editor carga un archivo TIFF de 50 MB, Sanity lo almacena. La API nos permite solicitar su transformación sobre la marcha.

https://cdn.sanity.io/images/.../my-image.jpg?w=800&h=600&fit=crop&auto=format

Creamos un componente de “Imagen” reutilizable que aprovecha esto:

  1. Punto de acceso y recorte: el editor establece el “Punto de enfoque” en la cara del modelo. Si recortamos a un cuadrado, la cara se centra automáticamente.
  2. Formato automático: Sirve AVIF a Chrome, WebP a Safari, JPEG a heredado.
  3. LQIP (marcador de posición de imagen de baja calidad): los metadatos incluyen una cadena de desenfoque codificada en base64. Mostramos esto instantáneamente mientras se carga la imagen principal.
// urlBuilder.ts
importar imageUrlBuilder desde '@sanity/image-url';

const constructor = imageUrlBuilder(cliente);

función de exportación urlFor (fuente) {
  devolver builder.image(fuente).auto('formato').fit('max');
}

Ingeniería de esquemas: validaciones

Tratamos los modelos de contenido como esquemas de bases de datos. Hacemos cumplir las reglas. “Una reseña de producto debe tener una calificación entre 1 y 5.”

// esquemas/review.ts
definir campo ({
  nombre: 'calificación',
  tipo: 'número',
  validación: (Regla) => Rule.required().min(1).max(5).error("La calificación debe ser 1-5")
})

Esta validación se ejecuta en Studio. El editor físicamente no puede publicar datos incorrectos. El código de interfaz nunca tiene que manejar “calificación: 200”.

Internacionalización (i18n)

Las marcas de lujo son globales. Hay dos estrategias en Sanity:

  1. Nivel de campo: { título: { en: "Hola", fr: "Bonjour" } }
    • Pro: Mantiene todo en un solo documento. Bueno para diseños fuertes y consistentes.
    • Con: El documento se vuelve enorme.
  2. Nivel de documento: Documento Title_EN y documento Title_FR.
    • Pro: Libertad total por mercado. La página francesa puede tener secciones diferentes a las de la página estadounidense.
    • Desventaja: Es más difícil gestionar la sincronización.

Normalmente recomendamos Nivel de campo para “Contenido global” (descripciones de productos) y Nivel de documento para “Páginas de marketing” (las campañas suelen diferir según la región).

10. Sanity Connect para Shopify (sincronización)

No desea copiar y pegar títulos de productos de Shopify a Sanity. Usamos Sanity Connect. Escucha Shopify Webhooks. Cuando el precio se actualiza en Shopify -> Se sincroniza con Sanity. Pero lo hacemos Solo lectura en Sanity. El Editor ve los datos del producto, puede hacer referencia a ellos en un Lookbook, pero no puede cambiar el precio. Esto mantiene la “Fuente única de la verdad” (Shopify) al tiempo que enriquece la “Capa de presentación” (Sanity).

11. Paneles de estudio personalizados

El CMS es el hogar destinado al equipo de marketing. Creamos widgets de panel personalizados en Studio.

  1. Widget de Google Analytics: “Las 5 publicaciones de blog principales de esta semana”.
  2. Widget de Shopify: “Ticker de ventas en vivo”.
  3. Estado de compilación de Vercel: “¿Se está implementando el sitio?”. Esto convierte el CMS en un centro de comando, lo que reduce la necesidad de iniciar sesión en 5 herramientas diferentes.

13. Estrategias de migración: WordPress a la cordura

Migrar 5.000 publicaciones de blog desde WordPress da miedo. No utilizamos “Complementos de importación”. Escribimos guiones.

  1. Extracto: Conéctese a la API REST de WP. Retire todas las publicaciones.
  2. Transformar: Convertir cuerpo HTML -> Texto portátil (usando @portabletext/to-portabletext).
    • Esto convierte etiquetas <b> en marcas.
    • Descarga imágenes, las sube a Sanity Asset Pipeline y reemplaza el <img> src con la nueva referencia de activos.
  3. Cargar: Escritura transaccional (100 documentos por transacción). Resultado: un conjunto de datos limpio y estructurado a partir de una sopa HTML desordenada.

14. El concepto de “lago de contenidos”

¿Por qué llamarlo “Lago”? Porque tiras todo lo que hay en él. Productos. Perfiles del personal. Ubicaciones de tiendas. Políticas Jurídicas. En un CMS tradicional, estos están aislados. En Sanity, son solo documentos. Puede vincular una “Ubicación de la tienda” a un “Perfil del personal” a un “Producto”. “Este producto está disponible en la tienda de París, gestionada por Chloe.” Esta capacidad de Gráfico permite experiencias de interfaz increíblemente ricas que WordPress no puede modelar.

15. Conclusión

La cordura nos permite desacoplar el “Qué” (Contenido) del “Cómo” (Presentación). Convierte el CMS de un cuello de botella en una API. Para un desarrollador, consultar contenido con GROQ parece ser un superpoder. Para un editor, ver sus cambios en vivo sin presionar “Actualizar” parece mágico.


¿No estás satisfecho con tu CMS?

Si su equipo de marketing rompe el diseño cada vez que publican una publicación en el blog. Contrate a nuestros arquitectos.