Skip to Content
WalkthroughCrear un evento

Crear un evento de principio a fin

Cada evento publicado involucra tres sistemas en orden estricto. Saltarse alguno rompe el flujo de reservación o de visualización.

Supabase → Cloudinary → Sanity Studio → Frontend (DB) (imagen) (contenido) (automático)

Paso 1 — Supabase: registrar el evento en la base de datos

El worker consulta la tabla events para validar slugs, obtener precios y vincular reservaciones. El evento debe existir en Supabase antes de que alguien pueda reservar.

Esquema de la tabla events

Si la tabla aún no existe, créala en el SQL Editor de Supabase:

CREATE TABLE events ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), slug TEXT UNIQUE NOT NULL, title TEXT NOT NULL, event_date TIMESTAMPTZ, price_amount NUMERIC(10, 2) NOT NULL DEFAULT 0, capacity INT NOT NULL DEFAULT 30, capacity_used INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() );

capacity_used se incrementa automáticamente cuando un usuario crea una reservación. Si capacity_used >= capacity, el worker rechaza nuevas reservaciones con el error EVENT_FULL. Configura el trigger correspondiente según tu lógica de negocio.

Insertar un nuevo evento

INSERT INTO events (slug, title, event_date, price_amount, capacity) VALUES ( 'yoga-restaurativo-mayo-2025', 'Yoga Restaurativo', '2025-05-17T11:00:00-06:00', 300.00, 30 );

El slug es el vínculo entre Supabase y Sanity. Debe ser idéntico en ambos sistemas. Define el slug aquí primero y úsalo al crear el documento en Studio.


Paso 2 — Cloudinary: subir la imagen del evento

Todas las imágenes del sitio se sirven desde Cloudinary. Sanity no almacena la imagen directamente; guarda únicamente el Public ID de Cloudinary.

Consulta la guía completa en Cloudinary → Gestión de imágenes.

Lo que necesitas de ese paso: el Public ID de la imagen subida (ej. eventos/yoga-restaurativo-mayo).


Paso 3 — Sanity Studio: crear el documento del evento

Abre el Studio en http://localhost:3333 y crea un nuevo documento de tipo Evento.

Campos obligatorios

CampoDónde usarloEjemplo
titleTítulo principal de la tarjeta y páginaYoga Restaurativo
slugDebe coincidir exactamente con el slug de Supabaseyoga-restaurativo-mayo-2025
eventDateFecha/hora exacta para ordenamiento y filtros2025-05-17T11:00:00
priceAmountPrecio numérico — lo usa el worker para crear la orden de PayPal300

Campos de visualización

CampoDescripciónEjemplo
eyebrowEtiqueta pequeña sobre el títuloEVENTO DE PRIMAVERA
dateFecha formateada para la UI17 de mayo, 11:00 am
dateShortVersión compacta para tarjetasMAY 17
timeRangeDuración del evento11:00 am – 1:10 pm
pricePrecio formateado para mostrarMXN $300.00
descriptionTexto corto para tarjetas (2-3 líneas)
longDescriptionDescripción completa en la página del evento

Imagen (Cloudinary)

CampoDescripción
imagePublicIdEl Public ID copiado de Cloudinary (ver Paso 2)
imageAltTexto alternativo descriptivo para accesibilidad

Ubicación

CampoEjemplo
locationCentro Holístico Zen
cityCiudad de México
stateOrProvinceCDMX
mapsEmbedUrlURL del iframe de Google Maps
mapsDirectionsUrlURL de “Cómo llegar” de Google Maps

Itinerario

El campo itinerary es un arreglo de bloques con dos campos cada uno:

{ time: "11:00 am", activity: "Bienvenida y respiración inicial" } { time: "11:20 am", activity: "Secuencia de apertura de caderas" } { time: "1:00 pm", activity: "Savasana y cierre" }

Opciones adicionales

  • comingSoon — actívalo para publicar el evento sin mostrar precio ni formulario de reservación. Útil para anunciar con anticipación.
  • reservationUrl — si el botón de reservación apunta a un link externo en lugar del modal.
  • seo — metaTítulo, metaDescripción e imagen OG para redes sociales.

Publicar

Una vez rellenos todos los campos, haz clic en Publish en la esquina superior derecha del Studio. El evento queda disponible para el frontend inmediatamente (la web hace fetch de Sanity en tiempo de carga).


Paso 4 — Frontend: cómo se visualiza

El frontend consume los eventos a través de queries GROQ. No requiere ninguna acción manual — basta con que el evento esté publicado en Sanity.

Query de lista (eventos futuros)

*[_type == "event" && (eventDate >= now() || !defined(eventDate))] | order(eventDate asc) { title, slug, eyebrow, description, date, dateShort, timeRange, price, priceAmount, imagePublicId, imageAlt, comingSoon }

Query de detalle (por slug)

*[_type == "event" && slug.current == $slug][0] { title, slug, eyebrow, description, longDescription, date, dateShort, timeRange, price, priceAmount, imagePublicId, imageAlt, comingSoon, itinerary, location, city, stateOrProvince, mapsEmbedUrl, mapsDirectionsUrl, seo }

Flujo de reservación

Cuando el usuario hace clic en Reservar:

  1. ReservationModal llama a GET /api/reservations/check?slug=<slug> — verifica si ya tiene reservación activa
  2. Si no tiene: llama a POST /api/reservations con { eventSlug, fullName, email }
  3. El worker busca el evento en Supabase por slug — por eso el slug debe coincidir
  4. Si hay cupo: crea la reservación en estado pending
  5. El modal abre el flujo de PayPal para completar el pago

Checklist de verificación

Antes de anunciar el evento, confirma cada punto:

SistemaQué verificar
SupabaseEl registro existe con el slug correcto y price_amount = precio real
CloudinaryLa imagen está subida y el Public ID es el correcto
SanityEl documento está publicado (no en borrador), slug coincide con Supabase
FrontendLa tarjeta del evento aparece en la página de inicio
ReservaciónEl modal de reservación abre y el check de cupo responde correctamente
PayPalEn sandbox: se puede completar el flujo de pago end-to-end
Last updated on