Referencia de despliegue, configuración y administración para AI Reality Check.
AI Reality Check está desplegado en Railway con un servicio web Next.js y una base de datos PostgreSQL. La aplicación se construye con `npm run build` y se inicia con `npm start`.
Dado que el despliegue automático de Railway desde GitHub puede dejar de funcionar silenciosamente, siempre despliegue manualmente: `cd ai-reality-check && railway up`. Esto construye y despliega en un solo paso.
El dominio de producción es airealitycheck.ai, configurado en los ajustes de dominio personalizado de Railway. El SSL se maneja automáticamente a través de Let's Encrypt (TLS 1.3).
DATABASE_URL — Cadena de conexión de PostgreSQL (proporcionada por Railway). ENCRYPTION_KEY — Clave hex de 32 bytes para encriptación AES-256-GCM. ANTHROPIC_API_KEY — Clave API para Claude (Check de confianza + Chatbot). NEXT_PUBLIC_APP_URL — https://airealitycheck.ai. RESEND_API_KEY — Clave API para correos de enlace mágico.
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET — Credenciales de Google OAuth. GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET — Credenciales de GitHub OAuth. Todas las URIs de redirección de OAuth deben apuntar a /api/auth/callback/google y /api/auth/callback/github respectivamente.
Nunca haga commit de variables de entorno a git. Todos los secretos se gestionan a través de la configuración de variables de entorno de Railway. La ENCRYPTION_KEY debe tener exactamente 64 caracteres hexadecimales (32 bytes). Genere una con: openssl rand -hex 32
Se utiliza Prisma 6 para el acceso a la base de datos. El esquema está en prisma/schema.prisma. Ejecute `npx prisma db push` para sincronizar cambios de esquema (no se necesitan migraciones para desarrollo).
User, AuthToken, Session, Result, AuditLog, WaitlistEntry, ChatConversation, ChatMessage. Todos los datos de usuario se encriptan en reposo usando AES-256-GCM antes del almacenamiento.
Use Docker para PostgreSQL local: `docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=airealitycheck postgres:16`. Configure DATABASE_URL=postgresql://postgres:postgres@localhost:5432/airealitycheck en .env.
Todos los datos de resultados y mensajes de chat se encriptan con AES-256-GCM antes del almacenamiento en la base de datos. Las claves se gestionan mediante variables de entorno y nunca se exponen al cliente. El texto original del Check de confianza nunca se almacena.
Las cabeceras de seguridad se aplican mediante middleware: CSP, X-Frame-Options DENY, HSTS, X-Content-Type-Options nosniff, Referrer-Policy, Permissions-Policy. CSP permite 'self' para scripts, estilos, imágenes, fuentes y conexiones.
Todas las rutas API que cambian estado validan un token CSRF. El token se genera del lado del servidor y se actualiza automáticamente a través del componente CsrfRefresh. Los tokens expiran después de 24 horas.
Limitador de frecuencia en memoria con límites por endpoint: Check de confianza 10/hora, Check de preparación/gastos 20/hora, enlace mágico 5/15min, Chatbot 30/hora. Adecuado para despliegue de instancia única.
Autenticación basada en correo electrónico a través de Resend. El usuario ingresa su correo, recibe un enlace mágico, hace clic para verificar. El token se hashea con bcrypt y expira en 15 minutos. La cookie de sesión se establece al verificar.
Se soportan Google y GitHub OAuth. Las cookies de sesión usan SameSite=Lax (requerido para redirecciones OAuth de origen cruzado). Las cookies se establecen directamente en los objetos de respuesta para las respuestas de redirección.
Las sesiones duran 24 horas. Configuración de cookies: HttpOnly, Secure (producción), SameSite=Lax, Path=/. Los registros de sesión se almacenan en la base de datos con userId y expiración.
Navegue a /admin/marketing (requiere variable ADMIN_EMAIL + autenticación). Seleccione una plataforma (X, LinkedIn, Facebook) y un tema, luego Claude genera contenido de redes sociales listo para publicar con ganchos, hashtags y CTAs.
POST a /api/marketing/waitlist-blast envía correos de lanzamiento a todos los suscriptores del waitlist que no han sido notificados. Envía en lotes de 50, rastrea notifiedAt para prevenir envíos dobles. Protegido por autenticación de admin + CSRF.
Configure la variable de entorno ADMIN_EMAIL en Railway con su dirección de correo. Solo los usuarios autenticados que coincidan con este correo pueden acceder a las herramientas de marketing. Todas las acciones están protegidas por CSRF y registradas en auditoría.
Cree un nuevo archivo .ts en src/data/blog-content/ con campos de título, slug, descripción, contenido y relatedCheck. Agregue la importación al archivo index.ts. El sitemap y el feed RSS se actualizan automáticamente.
Los artículos usan datos estáticos de TypeScript (sin CMS, sin base de datos). Cada artículo enlaza a un check relacionado mediante CTA. El contenido admite encabezados, párrafos, listas y texto en negrita. Los artículos están solo en inglés (no se traducen).
El sitemap en /sitemap.xml y el feed RSS en /feed.xml incluyen automáticamente nuevos artículos. No se necesita actualización manual — ambos leen del array de contenido del blog en tiempo de compilación.
Cuatro plantillas de correo en src/lib/emails.ts: correo de bienvenida (al registrarse), resumen de resultados (después del check), re-engagement (para usuarios incompletos) y envío masivo al waitlist (anuncio de lanzamiento). Todas usan HTML con marca en tema oscuro.
Active mediante /api/marketing/waitlist-blast. Envía a todos los registros de WaitlistEntry donde notifiedAt es nulo. Lotes de 50 con retrasos para evitar límites de frecuencia. Cada envío exitoso actualiza notifiedAt para prevenir re-envíos.
Sin RESEND_API_KEY configurada, todos los correos se registran en la consola en lugar de enviarse. Use esto para desarrollo local para verificar el contenido y los triggers de correo sin enviar mensajes realmente.
Los esquemas JSON-LD de FAQ, Breadcrumb y Product se aplican en las páginas de checks y precios. Pruebe con la herramienta de resultados enriquecidos de Google (search.google.com/test/rich-results) para verificar que los datos estructurados se renderizan correctamente.
Imágenes OG dinámicas generadas vía /api/og/result?type={check}&score={score}. Imágenes OG basadas en archivos en directorios de layout para páginas estáticas. Pruebe con depuradores de redes sociales (Twitter Card Validator, LinkedIn Post Inspector).
Agregue airealitycheck.ai a Google Search Console, verifique vía DNS y envíe el sitemap. Monitoree el estado de indexación, errores de cobertura y rendimiento de búsqueda. Revise problemas de datos estructurados en la pestaña de Mejoras.
Todas las acciones significativas se registran en la tabla audit_logs: inicio de sesión, envío de checks, vistas de resultados, uso del chatbot. Cada registro incluye userId, acción, endpoint, hash de IP y metadatos.
Vea los registros de la aplicación con `railway logs -n 50`. Consulte el panel de Railway para el estado de despliegue, uso de recursos y seguimiento de errores.
Verifique que la aplicación está funcionando accediendo a la página de inicio. Compruebe /sitemap.xml y /robots.txt para verificar que la generación estática funciona.
Verifique que SameSite esté configurado como Lax (no Strict). Verifique que las URIs de redirección de OAuth coincidan exactamente. Compruebe que CSP form-action incluya los dominios de los proveedores de OAuth. Consulte docs/issues/google-oauth-login-broken.md para el informe completo.
El despliegue automático de Railway desde GitHub puede dejar de funcionar silenciosamente. Siempre use `railway up` desde el directorio ai-reality-check como alternativa confiable. Verifique con `railway logs` que la nueva versión esté en ejecución.
Verifique que DATABASE_URL esté configurado correctamente en el entorno de Railway. Para desarrollo local, asegúrese de que el contenedor Docker de PostgreSQL esté en ejecución. Ejecute `npx prisma db push` para sincronizar el esquema.
Verifique que ANTHROPIC_API_KEY esté configurado y sea válido. Compruebe los límites de frecuencia (10/hora por usuario). Asegúrese de que el texto de entrada tenga menos de 5,000 caracteres. Revise los registros de Railway para errores específicos de la API.