Ir al contenido

Usa este checklist antes de cada despliegue a producción para garantizar que todas las configuraciones estén correctas y prevenir errores comunes.

  • DATABASE_URL configurada con Neon connection string
    • Formato: postgresql://user:pass@ep-xxx.aws.neon.tech/neondb?sslmode=require
    • Obtener de: console.neon.tech
  • JWT_SECRET generado con openssl rand -base64 32
    • ⚠️ Nunca reutilizar el mismo secret de desarrollo
    • ⚠️ Generar uno único para producción
  • CLIENT_URL con dominio de producción
    • Formato: https://talentbricks.ai (sin trailing slash)
  • SENDGRID_API_KEY configurado
  • SENDGRID_FIELD_FROM_EMAIL con email verificado en SendGrid
  • SENDGRID_FIELD_FROM_NAME con nombre de tu marca
  • ADMIN_EMAILS con emails reales (separados por coma)
    • Ejemplo: admin@empresa.com,juan@empresa.com
    • Estos usuarios tendrán acceso al dashboard de admin

2. Almacenamiento de Videos (elige una opción)

Sección titulada «2. Almacenamiento de Videos (elige una opción)»

Solo si usas videos en producción (recomendado). La variable STORAGE_PROVIDER controla el proveedor activo.

  • STORAGE_PROVIDER configurado: aws o azure
  • AWS_S3_IAM_ACCESS_KEY configurado
  • AWS_S3_IAM_SECRET_KEY configurado
  • AWS_S3_FILES_BUCKET configurado
    • Ejemplo: talentbricks-videos-prod
  • AWS_S3_REGION configurado
    • Ejemplo: us-east-1
  • CLOUDFRONT_DOMAIN configurado
    • Formato: d1234567890abc.cloudfront.net (sin https://)
  • CLOUDFRONT_KEY_PAIR_ID configurado
    • Obtener de: CloudFront → Key pairs
  • CLOUDFRONT_PRIVATE_KEY configurado (en una línea con \n)
    • Formato: -----BEGIN RSA PRIVATE KEY-----\nMIIE...\n-----END RSA PRIVATE KEY-----

Verificar:

  • Usuario IAM tiene permisos s3:PutObject y s3:GetObject
  • Bucket S3 tiene CORS configurado correctamente
  • CloudFront distribution está en estado “Deployed”
  • AZURE_STORAGE_ACCOUNT_NAME configurado
  • AZURE_STORAGE_ACCOUNT_KEY configurado
    • Obtener de: Storage Account → Security + networking → Access keys
  • AZURE_STORAGE_CONTAINER_NAME configurado
    • Ejemplo: videos

Verificar:

  • Container creado con acceso privado (sin acceso anónimo)
  • La key es válida (se puede rotar en el portal de Azure si es necesario)
  • GITHUB_CLIENT_ID configurado
  • GITHUB_CLIENT_SECRET configurado
  • Authorization callback URL es:
    • https://tu-dominio.com/auth/github/callback
  • REACT_APP_GOOGLE_ANALYTICS_ID configurado si usas GA4
  • Migraciones de Prisma ejecutadas:

    Ventana de terminal
    # En Fly.io
    flyctl ssh console -C "cd /app && npx prisma migrate deploy"
    # En Railway
    railway run npx prisma migrate deploy
  • Índices de base de datos creados correctamente

  • Connection pooling habilitado en Neon (recomendado)

  • Variables de entorno no están en el código fuente
  • .env está en .gitignore
  • Secrets de producción son diferentes a desarrollo
  • HTTPS habilitado en dominio custom
  • Certificado SSL válido (auto-gestionado por Fly.io/Railway)
Ventana de terminal
# Verificar que flyctl está autenticado
flyctl auth whoami
# Verificar secrets configurados
flyctl secrets list -a talentbricksai
# Deploy
wasp deploy fly deploy
Ventana de terminal
# Verificar variables
railway variables
# Deploy (automático en git push, o manual):
railway up
  • La app carga sin errores en https://tu-dominio.com

  • Página de inicio (landing) se muestra correctamente

  • No hay errores 500 en la consola del navegador

  • No hay errores en logs del servidor:

    Ventana de terminal
    # Fly.io
    flyctl logs -a talentbricksai
    # Railway
    railway logs --tail
  • Registro de nuevo usuario funciona
  • Email de verificación llega correctamente
    • Verificar en SendGrid → Activity
  • Login con email + password funciona
  • “Olvidé mi contraseña” funciona
    • Email de reset llega
    • Link de reset funciona
  • (Opcional) Login con Google funciona
  • (Opcional) Login con GitHub funciona
  • Página de pricing carga correctamente
  • Click en “Comprar Curso” redirige a Stripe Checkout
  • Checkout muestra el precio correcto
  • Usar tarjeta de prueba de Stripe funciona:
    • Tarjeta: 4242 4242 4242 4242
    • Fecha: cualquier fecha futura
    • CVC: cualquier 3 dígitos
  • Después del pago, usuario es redirigido a la app
  • Webhook de Stripe se recibe correctamente:
    Ventana de terminal
    # Verificar en Stripe Dashboard
    Webhooks tu endpoint Recent deliveries 200 OK
  • Usuario tiene acceso al curso comprado
  • Enrollment aparece en base de datos:
    SELECT * FROM "Enrollment" WHERE "userId" = <user-id>;
  • Click en plan mensual redirige a Stripe Checkout
  • Pago de suscripción se procesa correctamente
  • Usuario tiene subscriptionStatus = 'active' en DB
  • Acceso a contenido premium funciona
  • Cancelación de suscripción funciona (portal de Stripe)
  • Abrir un curso con video
  • El video carga correctamente (no error 403)
  • URL del video es de CloudFront (no S3 directo)
    • Formato correcto: https://d123.cloudfront.net/...
    • Formato incorrecto: https://s3.amazonaws.com/...
  • Video se reproduce sin problemas
  • Signed URL expira después del tiempo configurado (ej: 1 hora)
  • Usuarios en ADMIN_EMAILS pueden acceder a /admin
  • Usuarios normales no pueden acceder a /admin (redirige o muestra error)
  • Dashboard muestra estadísticas correctas:
    • Total de usuarios
    • Cursos activos
    • Enrollments
    • Revenue (si aplica)
  • Lista de cursos carga correctamente
  • Detalle de curso muestra información correcta
  • Lecciones se marcan como completadas
  • Progreso del curso se actualiza en tiempo real
  • Certificado se genera al completar curso
  • Certificado se puede descargar en PDF
  • Email de bienvenida llega al registrarse
  • Email de verificación llega con link correcto
  • Email de reset de password funciona
  • Emails tienen el branding correcto (from name, from email)
  • Emails no caen en spam
    • Verificar SPF/DKIM en SendGrid
    • Hacer prueba con Gmail, Outlook, etc.
  • Plausible/GA4 está recibiendo eventos
  • Pageviews se registran correctamente
  • Eventos custom funcionan (si aplica)
  • Tiempo de carga de landing page < 3 segundos
  • Tiempo de carga de dashboard < 2 segundos
  • Imágenes están optimizadas
  • No hay memory leaks en logs
    Ventana de terminal
    # Verificar memoria
    flyctl status -a talentbricksai
  • Configurar alertas de uptime (ej: UptimeRobot, Pingdom)
  • Configurar alertas de errores (ej: Sentry, Rollbar)
  • Configurar monitoreo de logs
  • Configurar alertas de uso de DB (Neon dashboard)

Si algo sale mal, tener plan de rollback:

Ventana de terminal
# Ver deployments anteriores
flyctl releases -a talentbricksai
# Rollback a versión anterior
flyctl releases rollback -a talentbricksai
  1. Dashboard → Deployments
  2. Encontrar deployment funcional anterior
  3. Click •••Redeploy

Reversar Migraciones de DB (último recurso)

Sección titulada «Reversar Migraciones de DB (último recurso)»
Ventana de terminal
# ⚠️ Peligroso - solo si migraciones rompen la app
npx prisma migrate resolve --rolled-back <migration-name>
  • Rate limiting configurado para endpoints sensibles
  • CORS configurado correctamente en main.wasp
  • Cookies tienen flags Secure y HttpOnly
  • Inputs están validados con Zod
  • Queries/Actions verifican permisos del usuario
  • No hay SQL injection vectors
  • No hay XSS vectors (todo el contenido está sanitizado)
  • Secrets no están en logs
  • Error messages no revelan información sensible

Ver guía completa: Despliegue en Fly.io

Comandos útiles:

Ventana de terminal
# Ver status
flyctl status -a talentbricksai
# Ver logs
flyctl logs -a talentbricksai --tail
# SSH a la instancia
flyctl ssh console -a talentbricksai
# Ver secrets
flyctl secrets list -a talentbricksai
# Configurar secret
flyctl secrets set SECRET_NAME=value -a talentbricksai

Ver guía completa: Despliegue en Railway

Comandos útiles:

Ventana de terminal
# Ver status
railway status
# Ver logs
railway logs --tail
# Ver variables
railway variables
# Configurar variable
railway variables set SECRET_NAME=value
# Abrir dashboard
railway open

Si estás migrando de otra plataforma o cambiando configuración:

  • Backup completo de base de datos antes de migrar
  • Exportar variables de entorno del sistema anterior
  • Probar en staging antes de producción (si tienes)
  • Configurar DNS con TTL bajo (ej: 300s) para rollback rápido
  • Sincronizar usuarios/datos si cambiaste de DB
  • Actualizar webhooks en servicios externos (Stripe, etc.)
  • Verificar que emails llegan después de migración

Ver guía completa: Migración de Variables de Entorno

  1. Ver logs: flyctl logs o railway logs
  2. Verificar que todas las variables REQUIRED están configuradas
  3. Verificar formato de variables (ej: DATABASE_URL)
  1. Verificar STRIPE_WEBHOOK_SECRET es correcto
  2. Verificar URL del webhook en Stripe dashboard
  3. Probar con CLI de Stripe: stripe listen --forward-to localhost:3001/stripe-webhook
  1. Verificar CLOUDFRONT_PRIVATE_KEY está en formato correcto
  2. Verificar CloudFront distribution permite signed URLs
  3. Verificar IAM permissions en S3
  1. Verificar SENDGRID_API_KEY es válido
  2. Verificar sender email está verificado en SendGrid
  3. Ver Activity en SendGrid dashboard
  4. Verificar SPF/DKIM records

Si encuentras problemas:

  1. Revisar logs del servidor
  2. Revisar documentación específica del error
  3. Buscar en Wasp Discord
  4. Abrir issue en GitHub con logs y detalles