Claude Code y Sanity CMS: guía de producción para content ops
Implementa Sanity CMS con Claude Code para SEO, páginas de producto, contenido multilingüe y CTA de monetización.
Qué es Sanity CMS
Sanity CMS es un headless CMS para gestionar contenido estructurado: artículos, landing pages, ofertas, autores, FAQ, casos de cliente, textos de campaña y CTA reutilizables. Headless CMS significa que el panel editorial está separado del sitio o la aplicación que muestra el contenido. El equipo edita en Sanity Studio, el contenido vive en Content Lake y el frontend consulta solo los campos que necesita.
Para lectores de CMS y content ops, la parte importante no es “tener otro editor”. La parte útil es convertir contenido disperso en activos medibles. Un artículo puede tener keyword objetivo, intención de búsqueda, enlaces internos, CTA, responsable de revisión, nota de verificación y fecha de actualización. Cuando esos datos son campos, Claude Code puede crear schema, consultas GROQ, helpers de fetch, componentes y scripts de revisión.
Sanity define sus modelos con archivos de schema. La referencia oficial de tipos está en Sanity Schema Types, y la sintaxis de consulta está en GROQ syntax. Claude Code acelera mucho el trabajo inicial, pero las reglas de producción siguen siendo responsabilidad del equipo: slug único, exclusión de drafts, alt text obligatorio, CTA correcto y eventos de analítica conectados a ingresos.
En 2026 conviene pensar Sanity como infraestructura de monetización, no solo como CMS. Si vendes plantillas, cursos, consultoría o servicios de implementación, el contenido debe dirigir a la siguiente acción correcta. Un tutorial básico puede invitar a descargar un PDF gratuito; una comparación de CMS puede llevar a una auditoría de migración; una guía de governance puede terminar en formación para equipos.
Arquitectura de producción 2026
Una arquitectura sana separa edición, API, frontend, analítica y monetización. Esa separación evita que todo termine pegado dentro del body del artículo y permite optimizar cada parte sin romper las demás.
| Capa | Rol en producción | Métrica principal | Trabajo para Claude Code |
|---|---|---|---|
| Sanity Studio | Edición de posts, ofertas, FAQ, CTA y notas de revisión | Campos faltantes, cola de revisión, drafts antiguos | schemaTypes, previews, validaciones |
| Content Lake | Fuente API de contenido estructurado | Tamaño de query, caché, separación de dataset | GROQ, filtros de draft, filtros de locale |
| Frontend | Páginas SEO, listados, detalle y landing pages | Páginas indexadas, velocidad, clicks en CTA | fetch helpers, tipos, componentes |
| Analytics/CRM | Conectar lectura, compra y consulta | eventos, formularios iniciados, compras, leads | nombres de eventos, QA checklist |
| Monetización | PDF gratuito, Gumroad, Stripe, training o consultoría | ingresos, calidad del lead, reembolsos | variantes de CTA, tablas, routing de ofertas |
La regla práctica es separar el contenido que cambia por motivos comerciales. Un CTA no debería ser texto libre dentro del artículo si luego quieres probar diferentes ofertas. Una FAQ no debería duplicarse en diez páginas si el equipo legal o ventas la corrige cada mes. Un estado de revisión no debería vivir en una hoja externa si decide qué se publica.
Para ampliar el contexto, revisa Claude Code blog CMS, compara patrones con Claude Code Contentful CMS y conecta el contenido con aplicaciones mediante Claude Code API development. Si el objetivo es convertir contenido en ingresos, la siguiente parada natural es training / consultation.
Use cases reales
Primer use case: una biblioteca SEO multilingüe. Un equipo publica primero en un idioma y luego localiza a español, inglés, japonés, chino, francés, alemán o portugués. Si solo copia Markdown, pronto aparecen errores: una versión sin CTA, otra sin enlaces internos, otra con description demasiado larga. En Sanity puedes guardar locale, canonicalSlug, targetKeyword, searchIntent y localizedCta. Claude Code puede auditar esos campos y generar una lista de piezas incompletas antes de publicar.
Segundo use case: funnel de contenido a producto. No todos los lectores están listos para comprar lo mismo. Quien busca un tutorial puede necesitar una checklist gratis. Quien compara Sanity con Contentful quizá quiere una revisión de migración. Quien lee sobre governance puede necesitar formación para su equipo. Un documento CTA con intent, label y href permite mostrar la oferta adecuada sin editar cada artículo manualmente.
Tercer use case: migración de CMS con auditoría de contenido. Al pasar de WordPress, Contentful, Notion o Markdown a Sanity, no conviene mover basura histórica. La migración es el momento de clasificar contenido por tráfico, intención, frescura, prueba y ruta comercial. Campos como contentScore, lastReviewedAt, reviewOwner y monetizationStatus convierten la migración en una mejora del negocio, no solo en un cambio técnico.
Cuarto use case: una sola fuente para marketing y ventas. En equipos B2B es común que la web diga una cosa, ventas otra y soporte otra. Sanity puede guardar explicaciones, objeciones, proof points y FAQ como documentos reutilizables. El sitio los muestra al público; una herramienta interna los muestra al equipo comercial. Claude Code puede construir el fetch, los componentes y la API para que todo salga de la misma fuente.
Schema listo para copiar
Este schema funciona como punto de partida en Sanity v3. Guárdalo como schemaTypes/post.ts. Incluye campos que afectan SEO, operación y monetización: locale, description, imagen con alt, CTA, nota de verificación y fecha de publicación.
// schemaTypes/post.ts
import {defineField, defineType} from 'sanity'
export const post = defineType({
name: 'post',
title: 'Post',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Title',
type: 'string',
validation: (rule) => rule.required().max(90),
}),
defineField({
name: 'slug',
title: 'Slug',
type: 'slug',
options: {source: 'title', maxLength: 96},
validation: (rule) => rule.required(),
}),
defineField({
name: 'locale',
title: 'Locale',
type: 'string',
options: {
list: [
{title: 'English', value: 'en'},
{title: 'Spanish', value: 'es'},
{title: 'Japanese', value: 'ja'},
],
},
validation: (rule) => rule.required(),
}),
defineField({
name: 'description',
title: 'SEO description',
type: 'text',
rows: 3,
validation: (rule) => rule.required().max(120),
}),
defineField({
name: 'heroImage',
title: 'Hero image',
type: 'image',
options: {hotspot: true},
fields: [
defineField({
name: 'alt',
title: 'Alt text',
type: 'string',
validation: (rule) => rule.required(),
}),
],
validation: (rule) => rule.required(),
}),
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [{type: 'block'}, {type: 'image'}],
validation: (rule) => rule.required(),
}),
defineField({
name: 'cta',
title: 'Monetization CTA',
type: 'object',
fields: [
defineField({name: 'label', title: 'Label', type: 'string'}),
defineField({name: 'href', title: 'URL', type: 'url'}),
defineField({name: 'intent', title: 'Intent', type: 'string'}),
],
}),
defineField({
name: 'verificationNote',
title: 'Verification note',
type: 'text',
rows: 4,
}),
defineField({
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
validation: (rule) => rule.required(),
}),
],
preview: {
select: {title: 'title', subtitle: 'locale', media: 'heroImage'},
},
})
// schemaTypes/index.ts
import {post} from './post'
export const schemaTypes = [post]
GROQ y fetch desde el cliente
No uses una sola query para todo. El listado no necesita el body completo; la página de detalle sí necesita body, CTA y nota de verificación.
// src/lib/sanity/queries.ts
export const postsByLocaleQuery = `
*[
_type == "post" &&
locale == $locale &&
defined(slug.current) &&
defined(publishedAt)
] | order(publishedAt desc) [0...$limit] {
_id,
title,
description,
"slug": slug.current,
publishedAt,
"heroImageUrl": heroImage.asset->url,
"heroImageAlt": heroImage.alt,
cta
}
`
export const postBySlugQuery = `
*[
_type == "post" &&
locale == $locale &&
slug.current == $slug
][0] {
_id,
title,
description,
"slug": slug.current,
publishedAt,
body,
verificationNote,
cta,
"heroImageUrl": heroImage.asset->url,
"heroImageAlt": heroImage.alt
}
`
// src/lib/sanity/client.ts
import {createClient} from '@sanity/client'
import {postBySlugQuery, postsByLocaleQuery} from './queries'
export const sanityClient = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID || '',
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
apiVersion: '2026-06-02',
useCdn: process.env.NODE_ENV === 'production',
})
export async function getPosts(locale: string, limit = 12) {
return sanityClient.fetch(postsByLocaleQuery, {locale, limit})
}
export async function getPostBySlug(locale: string, slug: string) {
return sanityClient.fetch(postBySlugQuery, {locale, slug})
}
npm install sanity @sanity/client @sanity/image-url
set NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id
set NEXT_PUBLIC_SANITY_DATASET=production
Pitfalls y fallos frecuentes
El primer pitfall es diseñar el schema solo para la plantilla actual. Parece rápido, pero se vuelve caro cuando llegan idiomas, autores, CTA, fechas de revisión y scoring. Separa desde el principio los campos que afectan negocio y gobierno.
El segundo pitfall es traer demasiado contenido en las queries. Un listado que descarga el body completo de veinte artículos puede pasar en desarrollo, pero perjudica caché, build time y velocidad real. Usa queries separadas para cards, detalle, sitemap y relacionados.
El tercer pitfall es publicar drafts o contenido sin revisar. publishedAt ayuda, pero muchos equipos necesitan reviewStatus o datasets separados. Claude Code puede escribir tests para la query; el equipo debe decidir la regla editorial.
El cuarto pitfall es tratar monetización como un banner universal. La intención de búsqueda cambia por página. Si el CTA no coincide con el momento del lector, no convierte.
Checklist de rollout
- Exigir
title,description,slug,heroImage.altypublishedAt. - Separar posts, FAQ, autores, offers y CTA cuando se reutilizan.
- Crear GROQ distinto para listado, detalle, sitemap y relacionados.
- Guardar
localey canonical para contenido multilingüe. - Revisar enlaces oficiales, enlaces internos, CTA y nota de verificación antes de publicar.
- Unificar nombres de eventos entre analítica, venta y formularios.
- Revisar tráfico, clicks, compras y consultas 30 días después.
CTA de monetización
Sanity CMS tiene sentido cuando el contenido se convierte en un sistema de adquisición, educación y venta. ClaudeCodeLab puede revisar un blog Markdown, Contentful, WordPress o Sanity existente y convertirlo en schema, GROQ, checklist editorial y rutas de monetización. Si necesitas conectar artículos SEO con plantillas, training o consultoría, empieza desde training / consultation con contenido real y objetivos de ingresos reales.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Workflow de Obsidian a CLAUDE.md con Claude Code
Convierte notas de trabajo de Obsidian en notas operativas de CLAUDE.md para no repetir contexto.
Claude Code Revenue CTA Routing: de artículos a PDF, Gumroad y consulta
Un flujo con Claude Code para dirigir lectores a PDF gratis, Gumroad o consulta según intención.
Reglas de handoff para equipos con Claude Code: evidencia, permisos, rollback e ingresos
Formato práctico para entregar trabajo de Claude Code con pruebas, permisos, rollback, PDF gratis, Gumroad y consulta.