Cómo crear un SaaS de IA con OpenRouter, Stripe y Railway

Crear una plataforma SaaS de IA —del estilo de ChatGPT o Claude, con chats, historial y créditos de uso— dejó de ser un proyecto de meses. Hoy el reto real no es escribir el código, sino entender qué piezas necesitas conectar y cuánto te va a costar cada usuario.

En esta guía recorremos el proyecto completo: la arquitectura, la integración con OpenRouter para tener decenas de modelos con una sola API, los pagos con Stripe, el despliegue automático en Railway, el testing con TestSprite y —lo más importante— las consideraciones técnicas y de negocio que separan un MVP de una plataforma que aguanta usuarios reales.

Este artículo acompaña al video del canal. Aquí encontrarás el stack, los comandos exactos, el prompt base y los números de costo verificados.

Tabla de contenidos

  1. El stack: qué usar y por qué
  2. Arquitectura de monorepo
  3. Generar el proyecto con un agente
  4. Mejorar el diseño con Impeccable
  5. Integrar OpenRouter (multimodelo)
  6. Cobrar créditos con Stripe
  7. Desplegar en Railway
  8. Testing automatizado con TestSprite
  9. Qué falta para llevarlo a producción
  10. Unit economics: cuánto ganas realmente
  11. Preguntas frecuentes

1. El stack: qué usar y por qué

No hay que darle muchas vueltas: la mayoría de proyectos de este tipo terminan usando el mismo conjunto de tecnologías.

Capa Tecnología Por qué
Backend Node + Express (o Bun, Fastify, Hono) Ecosistema enorme y despliegue trivial
Base de datos PostgreSQL El estándar de facto para datos relacionales
ORM Drizzle ORM Define tablas SQL desde TypeScript, con tipado real
Dashboard React + Vite Entorno rápido y ligero para la app autenticada
Landing Astro Sitio estático, ideal para SEO y carga rápida
Modelos IA OpenRouter Un endpoint, cientos de modelos
Pagos Stripe Checkout, webhooks y CLI muy maduros
Despliegue Railway Barato, simple y con integración para agentes

Si prefieres Python, Go o Java en el backend, cámbialo sin problema. Pero si estás empezando, ve por lo común primero y reemplaza después.

¿Por qué separar landing y dashboard?

Es una decisión de arquitectura que mucha gente pasa por alto. El landing en Astro se sirve como HTML estático: carga en milisegundos y Google lo indexa sin fricción. La aplicación en sí (chats, formularios, historial) vive detrás del login, donde el SEO no importa y sí importa la interactividad.

Podrías hacerlo todo con Next.js, pero separarlos te da mejor rendimiento en la parte que necesitas posicionar.

2. Arquitectura de monorepo

Como todo está escrito en TypeScript, tiene sentido generar un monorepo:

ai-saas-platform/
├─ apps/
│  ├─ api/          # Backend Express + Drizzle
│  ├─ dashboard/    # React + Vite (app autenticada)
│  └─ landing/      # Astro (sitio público)
└─ packages/
   ├─ db/           # Esquema y tipos compartidos
   ├─ types/        # Tipos de dominio
   └─ config/       # ESLint, TS config, etc.

La carpeta packages/ es la razón de ser del monorepo: los tipos de la base de datos y las configuraciones se importan desde las tres aplicaciones, sin duplicar nada.

Tablas mínimas

  • users — cuentas y roles
  • credits / credit_transactions — saldo y movimientos
  • chats y messages — historial por usuario
  • generations — cada petición al modelo, con tokens consumidos y costo

3. Generar el proyecto con un agente

En el video usé Cursor, pero el mismo prompt funciona en Claude Code, Codex u OpenCode. La idea es entregarle una especificación completa en lugar de ir pidiendo cosas sueltas.

Prompt base (resumido)

Genera un MVP de un SaaS que permita a usuarios generar contenido con IA.

FUNCIONALIDAD
- Chat con historial por usuario, autenticación con contraseñas hasheadas.
- Sistema de créditos: paquetes de recarga de $20, $50 y $100.
- Roles: user y admin. El admin ve ingresos por paquete.
- Cada generación se guarda en el historial del usuario.

ARQUITECTURA
- Monorepo con apps/api (Node + Express), apps/dashboard (React + Vite)
  y apps/landing (Astro). Código compartido en packages/.
- PostgreSQL con Drizzle ORM.
- Proveedor de modelos: OpenRouter (un solo endpoint, multimodelo).

REQUISITOS
- Archivo .env.example con todas las variables.
- Seed con datos de demo.
- README con instrucciones para levantar el proyecto y configurar Stripe.

Todo lo que va debajo de "ARQUITECTURA" es intercambiable. Si quieres otro stack, reescribe esa sección y deja el resto igual.

Vista de agente vs. vista de IDE

Un consejo práctico: genera el proyecto en la vista de agente, pero cambia a la vista de IDE apenas exista el código. Ocultar el árbol de archivos está bien para prototipar; es pésimo para entender lo que se está construyendo. Además, la terminal funciona mucho mejor desde ahí.

4. Mejorar el diseño con Impeccable

El primer resultado casi siempre se ve a "sistema interno": funciona, pero no parece un producto. Esto es normal y no depende del modelo que uses.

La solución es Impeccable, una agent skill de diseño creada por Paul Bakaus que parte del skill frontend-design de Anthropic y lo extiende con un skill principal, 23 comandos y un conjunto de reglas anti-genéricas (nada de gradientes en texto, nada de glassmorphism por defecto, nada de fuentes de sistema).

Instalación

# vía skills.sh (recomendado)
npx skills add https://github.com/pbakaus/impeccable --skill impeccable

# o con su propio instalador
npx impeccable install

Luego, dentro del agente:

/impeccable init

Nota para Cursor: los Agent Skills requieren activarse en Settings → Rules. Si el comando /impeccable no aparece, cierra y vuelve a abrir el editor.

El instalador crea las carpetas .agents/ y .claude/ (o .cursor/, según el agente). A partir de ahí puedes pedir:

/impeccable Reimplementa el diseño completo. Debe verse como un SaaS
con diseño consistente, sesiones en la barra izquierda, chat central
y selector de modelos.

Sí, consume tokens. Es el costo de que la interfaz no parezca generada en cinco minutos.

Consejo: antes de ejecutar, cambia al modo plan. El agente te devuelve un resumen de todos los cambios que va a hacer y puedes corregirlo antes de tocar una sola línea. Léelo. Siempre.

5. Integrar OpenRouter (multimodelo)

OpenRouter expone cientos de modelos —de OpenAI, Anthropic, Google, DeepSeek, Qwen, Moonshot y decenas de proveedores más— detrás de un solo endpoint compatible con el SDK de OpenAI. Cambiar de modelo es cambiar un string, no reescribir la integración.

Pasos

  1. Crea una cuenta y recarga créditos. El mínimo de recarga es de $5 y es más que suficiente para probar el intercambio entre varios modelos.
  2. Ve a KeysCreate Key.
  3. Ponle nombre, una expiración (o ninguna, si la plataforma debe seguir funcionando) y, muy recomendable, un límite de crédito por llave.
  4. Copia la key a tu .env:
OPENROUTER_API_KEY=sk-or-v1-...

⚠️ Nunca subas esa llave a GitHub. Cualquiera que la encuentre consume tu saldo.

El detalle de costos que el video no cubre

OpenRouter cobra una comisión de ~5.5% al comprar créditos con tarjeta (≈5% con cripto, con un mínimo por transacción). No es un markup por token —los precios por modelo son de paso directo— pero sí afecta tus márgenes reales. Lo veremos en la sección de unit economics.

También existe un tier gratuito con modelos :free limitado a 20 peticiones por minuto y 50 diarias (que sube a 1.000 diarias tras comprar al menos $10 en créditos). Sirve para desarrollar, no para producción.

6. Cobrar créditos con Stripe

Stripe no está disponible en todos los países. Si operas desde LATAM, revisa tu caso: alternativas viables son Mercado Pago, dLocal, Culqi o PayPal. Aun así, puedes crear una cuenta sandbox para probar la integración completa sin cobrar de verdad.

Claves de API

En el dashboard de Stripe: Desarrolladores → Claves de API → Clave secreta.

STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

El problema del webhook en local

Stripe no puede enviar eventos a localhost. Necesitas exponer una URL con HTTPS, y para eso está el Stripe CLI:

npm install -g @stripe/cli@latest
stripe login

Instalar los skills de Stripe

Este es el comando correcto (en el video se menciona de forma abreviada):

stripe agent setup

Detecta automáticamente qué agentes tienes instalados —Claude Code, Codex y Cursor tienen soporte automático— e instala el plugin correspondiente, los agent skills y el servidor MCP. Si prefieres hacerlo a mano:

# Claude Code
claude plugin install stripe@claude-plugins-official

# Codex
codex plugin add stripe@openai-curated

# Cursor (dentro del agente)
/add-plugin stripe

Con los skills instalados, puedes simplemente pedir:

Configura los webhooks de Stripe para el flujo de compra de créditos.

El agente crea el endpoint, arranca stripe listen, obtiene el whsec_... y lo escribe en tu .env. Sin entrar al panel.

Probar el flujo

Usa las tarjetas de prueba de Stripe (por ejemplo 4242 4242 4242 4242), compra un paquete y verifica que el webhook acredite el saldo. Si los créditos aparecen sin recargar la página, la integración quedó bien.

7. Desplegar en Railway

Railway es barato, simple, y —clave para este flujo— tiene soporte oficial para agentes.

Instalar CLI y skills

npm install -g @railway/cli
railway login

# instala CLI + skills + MCP en un solo paso
railway setup agent

# o solo los skills
railway skills install

# o vía skills.sh
npx skills add railwayapp/railway-skills

Esto instala el skill use-railway, que cubre creación de proyectos y servicios, despliegues, variables de entorno y ciclo de vida de releases. Soporta Claude Code, Codex, OpenCode y Cursor.

Desplegar

/use-railway Despliega este proyecto en Railway.

Toma entre 15 y 20 minutos. Al terminar tendrás tres servicios en el panel —API, dashboard y landing— con todas las variables de entorno ya cargadas, incluida la de OpenRouter. Recuerda actualizar las URLs de los webhooks de Stripe para que apunten al dominio de producción.

Sobre los créditos gratuitos

Railway ofrece un trial de 30 días con $5 de crédito de uso (una sola vez). Pasado el trial —o agotado el crédito— la cuenta pasa al plan Free con $1 mensual de crédito y límites estrictos (1 vCPU, 0.5 GB RAM por servicio). El plan Hobby cuesta $5/mes e incluye $5 de uso; el consumo por encima de eso se factura aparte.

Si ves ofertas de más créditos, suelen venir de programas de referidos o campañas puntuales. El trial estándar publicado es de $5.

8. Testing automatizado con TestSprite

Con una interfaz que ofrece decenas de modelos, probar cada uno a mano es inviable. TestSprite genera y ejecuta tests end-to-end sobre el proyecto ya desplegado.

npx @testsprite/testsprite-mcp@latest

Te pedirá una API key (se genera desde el panel: Create API Key). Instala sus skills automáticamente —testsprite-onboard y testsprite-verify— en .claude/skills/. Si usas Cursor, cópialos también a .agents/skills/ para que los reconozca.

Después basta con pedirlo en lenguaje natural:

Ayúdame a testear mi proyecto usando TestSprite.

En mi caso generó 16 tests divididos entre frontend y backend. Varios fallaron en la primera pasada, lo cual es la parte útil: te dice qué funcionalidad falta. La segunda instrucción cierra el ciclo:

Implementa las características faltantes para que pase el resto de los
tests, y crea un usuario nuevo si es necesario.

Los tests generados son código Playwright/Cypress normal: puedes abrirlos, editar los valores que se escriben en cada input e intervenir cualquier paso. No es una caja negra.

Plan gratuito: 150 créditos al mes. Los planes de pago empiezan en $19/mes (400 créditos) y $69/mes (1.600 créditos). Cada ejecución consume créditos, así que en CI el gasto escala rápido.

9. Qué falta para llevarlo a producción

Esta es la parte que realmente importa y la que ninguna herramienta de vibe coding resuelve por ti. Lo que tienes hasta aquí es un MVP funcional; lo siguiente es lo que lo rompe con usuarios reales.

9.1 Concurrencia y validación de créditos

Si un usuario abre tres pestañas y lanza tres prompts simultáneos con solo dos créditos, es muy probable que los tres pasen: ninguna respuesta terminó todavía, así que ninguna descontó saldo.

La solución es validar el saldo en la base de datos, no en la aplicación, con una transacción atómica que reserve el crédito antes de llamar al modelo:

-- Reserva atómica: falla si no hay saldo suficiente
UPDATE credits
SET balance = balance - $1
WHERE user_id = $2 AND balance >= $1
RETURNING balance;

Si el UPDATE no devuelve filas, no hay saldo. Punto. Toda la lógica vive en un solo lugar y no importa cuántas instancias de tu API estén corriendo.

9.2 Streaming y pool de conexiones

Este es el error de arquitectura más caro. Si mantienes una conexión de base de datos abierta durante toda la respuesta del modelo, con un pool de 20 conexiones el usuario 21 se queda esperando.

La respuesta del modelo puede tardar 30 segundos o más, sobre todo con modelos que tienen thinking activado. La conexión a la base de datos debe abrirse, hacer su trabajo y cerrarse —no acompañar todo el streaming.

Patrón correcto:

  1. Reservar créditos (transacción corta, conexión liberada).
  2. Llamar a OpenRouter y hacer streaming al cliente vía SSE.
  3. Al terminar, abrir una nueva conexión corta para persistir el mensaje y ajustar el consumo real de tokens.

Para cargas altas, añade una cola con límite de concurrencia: BullMQ, RabbitMQ o AWS SQS. Lo mismo aplica al procesamiento de pagos.

9.3 ¿Qué pasa si el usuario cierra la pestaña?

Si ya enviaste la petición, OpenRouter ya te cobró. Así que sí: normalmente hay que cobrar al usuario. Pero eso implica manejar el corte de conexión y calcular los tokens realmente consumidos hasta ese punto.

La alternativa —la que usan ChatGPT y Claude— es continuar la generación en el backend y guardarla en el historial aunque el usuario se haya ido. Es mejor experiencia, pero requiere infraestructura de trabajos en segundo plano.

9.4 Controles de abuso

Estás pagando la API por todos tus usuarios. Como mínimo:

  • Límite de max_tokens por petición.
  • Rate limiting por usuario y por IP.
  • Verificación de email obligatoria antes de generar.
  • Límite de crédito configurado en la propia API key de OpenRouter.

9.5 Reglas de negocio

  • ¿Los créditos expiran? ¿En cuánto tiempo?
  • ¿Hay reembolsos cuando una generación falla?
  • ¿Cómo manejas los chargebacks? (Stripe cobra $15 por disputa, no reembolsable si la pierdes.)

Para profundizar en el diseño de este tipo de sistemas, la referencia clásica sigue siendo System Design Primer: colas, caché, sharding, replicación y streaming explicados con sus trade-offs.

10. Unit economics: cuánto ganas realmente

Esta es la sección que más gente ignora, y la que decide si el negocio existe.

Cuando pagas por un servicio de vibe coding como Lovable o Bolt, no estás pagando el desarrollo —lo hace la IA— ni la nube, que es relativamente barata. Estás pagando la experiencia y, sobre todo, ellos te revenden el costo de los modelos. Combinan un modelo caro para planificar y uno barato para generar código: ahí está el margen.

Tú vas a hacer exactamente lo mismo. Veamos los números con un paquete de $20 y un markup de 2× (el usuario recibe $10 en tokens):

Concepto Monto
Precio del paquete $20.00
Comisión Stripe (tarjeta doméstica US: 2.9% + $0.30) −$0.88
Costo de tokens en OpenRouter −$10.00
Comisión de recarga OpenRouter (~5.5%) −$0.55
Infraestructura prorrateada (Railway) −$1.00
Margen bruto ≈ $7.57 (38%)

Ajuste importante para LATAM: si tus clientes pagan con tarjetas emitidas fuera de Estados Unidos, Stripe suma un 1.5% de comisión internacional (total ≈ 4.4% + $0.30) y hasta un 1% adicional por conversión de moneda. Ese mismo paquete de $20 pasa a costarte $1.18 en comisiones, y el margen cae a ~$7.27.

Y esto no incluye: sistema de colas, notificaciones, almacenamiento de imágenes generadas (S3, DigitalOcean Spaces), soporte, ni las generaciones que fallan y tienes que reembolsar. Presupuesta con holgura.

Regla práctica

Un markup de 2× es agresivo. Con las comisiones apiladas, 2.5× a 3× es lo razonable si quieres que el margen sobreviva a los reembolsos, al soporte y a los picos de consumo.

Cómo seguir extendiendo el proyecto

En la raíz del proyecto crea una carpeta docs/ y arrastra ahí tus notas de producto. Después, en modo plan, pide una funcionalidad a la vez:

Añade soporte para modelos que generan imágenes.

Ojo con las implicaciones: si generas imágenes, necesitas almacenarlas en el historial del usuario, y eso significa integrar un servicio de archivos (S3, DigitalOcean Spaces o similar) con URLs firmadas y política de retención. No es "una funcionalidad más": es un subsistema.

Aquí es donde cambia el enfoque. Puedes seguir pidiendo cosas a ciegas, o entender qué hay debajo y decidir cuándo delegar en un servicio y cuándo implementarlo tú. Esa decisión es la diferencia técnica real.

Preguntas frecuentes

¿Necesito saber programar para crear un SaaS de IA?

Para generar el MVP, no. Para llevarlo a producción con usuarios que pagan, sí. Los problemas que aparecen —concurrencia, pool de conexiones, streaming, manejo de cobros fallidos— no se resuelven pidiéndole cosas al agente sin entender qué está pasando.

¿Por qué OpenRouter y no la API de OpenAI directamente?

Porque OpenRouter te da un endpoint compatible con el SDK de OpenAI y acceso a cientos de modelos de decenas de proveedores. Si tu producto le permite al usuario elegir modelo, es la opción obvia. Si solo vas a usar un proveedor, ir directo te ahorra la comisión de recarga.

¿Cuánto cuesta mantener esta plataforma al mes?

El piso ronda los $5–$15 mensuales: Railway Hobby ($5/mes con $5 de uso incluido) más el consumo de base de datos y ancho de banda. Los tokens de IA no son un costo fijo: los cubre el usuario a través de los créditos que compra.

¿Qué hago si Stripe no está disponible en mi país?

Puedes crear una cuenta sandbox para desarrollar y desplegar con otra pasarela: Mercado Pago, dLocal, Culqi o PayPal, según tu mercado. La lógica de créditos no cambia; solo el adaptador de pagos y el formato del webhook.

¿Los Agent Skills funcionan en cualquier editor?

Los de este artículo (Impeccable, Railway, Stripe, TestSprite) soportan Claude Code, Codex, Cursor y OpenCode, entre otros. Se instalan en .agents/skills/ o .claude/skills/ según el agente, así que si mañana cambias de herramienta, tus skills siguen funcionando.

¿Cuál es la diferencia entre un Agent Skill y un MCP?

Un skill es conocimiento procedimental: instrucciones sobre cómo hacer algo bien. Un MCP es acceso a datos y acciones en vivo sobre un servicio. En la práctica suelen resolver necesidades parecidas y varias plataformas —Stripe y Railway, por ejemplo— ofrecen ambos.

Recursos

¿Dudas o sugerencias para el siguiente artículo? Déjalas en los comentarios. También puedes reservar una asesoría personalizada en fazt.dev.