Webhooks en Sanity.io: El Framework de 3 Capas que el 90% Implementa Mal

Webhooks en Sanity.io: El Framework de 3 Capas que el 90% Implementa Mal

Programming· 6 min read

El 90% de Implementaciones de Sanity Pierden Automatización por Configurar Webhooks Incorrectamente

Vuestra estrategia de contenido depende de webhooks. Pero la mayoría configuráis los vuestros como si fueran simples botones de notificación.

Un webhook no es un "aviso de que pasó algo". Es un evento estructurado que vuestra infraestructura puede consumir para orquestar reacciones complejas: rebuilds, sincronizaciones, notificaciones, invalidaciones de caché.

La diferencia entre una implementación que funciona y una que escala no está en el CMS. Está en cómo diseñáis el flujo de webhook.

El problema real no es recibir el evento. Es estructurar la reacción para que sea idempotente, escalable, y tolerante a fallos.

El Problema: webhooks que disparan builds sin estrategia detrás

La mayoría configuráis un webhook en Sanity con la URL de Vercel o Netlify. Cuando cambia un documento, el CMS envía una petición POST. El host recibe el payload y dispara un deploy.

Funciona. Al principio.

El problema aparece cuando escaláis:

  • 50 artículos modificados en batch = 50 builds disparadas
  • El webhook se ejecuta antes de que GROQ termine de reindexar
  • No hay retry logic si el deploy falla
  • No diferenciáis entre contenido y configuración
  • No validáis que el payload viene realmente de Sanity

Cada uno de estos puntos genera fallos en cadena. Y la mayoría no los descubrís hasta que un editor modifica 200 productos y vuestra pipeline de deploy colapsa durante 3 horas.

La implementación por defecto no es robusta. Es naïve.

El Payload de Sanity: Lo Que Realmente Estáis Recibiendo

Cuando configuráis un webhook en Sanity, el cuerpo del evento contiene datos estructurados que la mayoría ignoráis:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Este payload os dice exactamente:

  • Qué tipo de operación ocurrió (create, update, delete)
  • Qué documento se afectó (id + _type)
  • Qué revisión del schema cambió (_rev)
  • El identificador legible (slug.current)

Con esta información, vuestro handler puede decidir qué hacer. No todo necesita un deploy completo.

Por Qué Esto Cambia Todo

Vuestra pipeline puede filtrar eventos:

  • Cambios en settings o navigation → rebuild completo (afectan estructura)
  • Cambios en product → invalidar caché + reindexar búsqueda
  • Cambios en author → solo propagar a contenido relacionado

Sin esta distinción, estáis tratando una actualización de copyright como si fuera un nuevo landing page.

El Framework de 3 Capas para Webhooks Robustos en Sanity

Este framework os da la arquitectura para construir webhooks que escalan, se recuperan de errores, y diferencian entre tipos de contenido.

Capa 1: Validación y Autenticación

Antes de procesar nada, verificad la firma del webhook:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Esta capa previene ataques de replay y asegura que el evento viene de Sanity, no de un agente externo.

Capa 2: Clasificación por Tipo de Contenido

Distinguid entre operaciones que requieren rebuild y las que no:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Con esta clasificación, vuestra Edge Function o serverless handler ejecuta la lógica correcta según el evento.

Capa 3: Cola de Procesamiento con Retry

Nunca ejecutéis lógica compleja en el handler del webhook directamente. Usad una cola:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Esta aproximación os da:

  • Idempotencia: si el webhook se dispara twice, la operación ya existe
  • Retry logic: si falla, el handler puede reintentarlo con backoff exponencial
  • Observabilidad: tenéis un registro de todas las operaciones y su estado

El Error Más Común: Webhooks sin Signature Verification

La mayoría ignoran la capa de autenticación. Configuran el webhook, apuntan a su endpoint, y funcionan.

Hasta que alguien descubre la URL y empieza a enviar eventos falsos.

Sin signature verification, un agente externo puede:

  • Disparar builds falsos que agotan vuestros minutos de deployment
  • Invalidar caché continuamente
  • Sobrecargar vuestras APIs downstream

Añadir la verificación de Sanity toma 20 líneas de código. No lo ignoréis.

Sin verificación:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Con verificación:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Desplegando el Handler: Vercel Edge Function o Serverless?

Para webhooks de Sanity, vuestra mejor opción es una Edge Function en Vercel por tres razones:

  1. Latencia baja: respuesta inmediata al webhook de Sanity
  2. Distribución global: el handler se ejecuta cerca del servidor de Sanity
  3. Escalado automático: cada evento ejecuta una instancia fría pero rápida

El código del framework que os he mostrado funciona tanto en Edge Functions como en Serverless Functions estándar. La única diferencia es el runtime:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Configurar el Webhook en Sanity Dashboard

Ahora que vuestro handler está listo, configurad el webhook en Sanity:

  1. Id a Sanity DashboardAPIWebhooks
  2. Click en Add Webhook
  3. Configurad:
    • URL: vuesta Edge Function URL (ej: https://vuesto-proyecto.vercel.app/api/webhook)
    • Trigger on: seleccionad los tipos de documento que os interesan
    • Filter: opción avanzada para filtrar por condiciones (ej: solo contenido publicado)
    • Projection: qué campos incluir en el payload
    • Signature: generad un secreto y guardadlo en .env como SANITY_WEBHOOK_SECRET

La opción de filter es potente. Podéis filtrar por estado de publicación:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Así solo recibís eventos de contenido que realmente necesita procesamiento.

Monitoring: Saber Cuándo Algo Falla

Un webhook sin monitoring es un servicio ciego. Añadid logging estructurado:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Con estos logs en Sanity, podeis consultar qué webhooks fallaron y por qué.

Qué Hacer con los Eventos Adelantados

El problema más sutil: Sanity envía el webhook cuando el documento se guarda, pero antes de que GROQ indexes los cambios.

Si vuestra web consume el API de Sanity desde la frontend, el contenido nuevo puede no aparecer durante 30-60 segundos.

La solución no es esperar más. Es invalidar la caché de vuesta CDN después del rebuild.

En Vercel, disparad una invalidación de caché programática:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Añadid esto a la Capa 3 después de que el deploy complete.

Resumen: El Framework Completo

El Patrón de las 3 Capas para Webhooks Robustos:

  1. Validación: verificad la firma con HMAC-SHA256 antes de procesar
  2. Clasificación: diferenciad entre tipos de contenido y decidid la acción correspondiente
  3. Cola + Retry: encolad operaciones en Sanity o Redis para procesamiento asíncrono con reintentos

Con este framework, vuestros webhooks de Sanity dejan de ser notificaciones y se convierten en la columna vertebral de vuestra automatización de contenido.

No esperéis a que 200 documentos cambien y vuestra pipeline colapse. Implementad la clasificación por tipo desde el día uno.

Artículos relacionados

---

¿Quieres recibir contenido como este cada semana? Suscríbete a mi newsletter

Brian Mena

Brian Mena

Software engineer building profitable digital products: SaaS, directories and AI agents. All from scratch, all in production.

LinkedIn