15 Apps en Producción, Un Solo Stack: Lo Que Aprendimos Construyendo SaaS Real en México
Este artículo no es una opinión teórica sobre qué tecnologías “deberías” usar. Es un reporte de campo. Desde IAmanos hemos construido y desplegado más de 15 aplicaciones SaaS que están en producción hoy, sirviendo clientes reales en México, corriendo sobre el mismo stack tecnológico.
WouWou (plataforma veterinaria). GlamBook (reservas para salones de belleza). Lead Desk (CRM comercial). PrintDesk (gestión de imprentas). Credit-Solo (préstamos SOFOM). FisioCore (fisioterapia). Capitán Inventario (control de inventarios). Fenga (diseños con IA). Terminal (secretaria IA). Results OS (dashboard SEO). Cotizador. Chat iAmanos. Y más.
Cada una de estas apps fue construida, probada y desplegada con el mismo stack base. Eso no fue coincidencia — fue una decisión arquitectónica que tomamos después de probar (y descartar) varias alternativas. En este artículo te contamos exactamente qué usamos, por qué lo elegimos, qué alternativas descartamos, y los gotchas que nadie te cuenta hasta que estás en producción con clientes reales.
Si estás por construir un SaaS en México en 2026, este artículo te puede ahorrar meses de decisiones equivocadas.
Next.js 16 con App Router: El Framework Que Elegimos (y Por Qué)
Next.js 16 es el framework base de todas nuestras aplicaciones. No fue amor a primera vista — fue una decisión pragmática que se ha validado con cada proyecto nuevo.
App Router vs Pages Router
En 2024, cuando empezamos a migrar proyectos al App Router, la documentación era confusa y la comunidad estaba dividida. Hoy, en 2026, el App Router es la forma correcta de construir con Next.js. Server Components reducen el JavaScript que llega al cliente, los Layouts compartidos eliminan re-renders innecesarios, y los Server Actions simplificaron las mutaciones de datos al punto de eliminar la necesidad de API routes para operaciones CRUD básicas.
¿Qué ganamos en la práctica? Time-to-first-byte de menos de 200ms en todas nuestras apps. Carga inicial percibida instantánea gracias a streaming y Suspense boundaries. SEO nativo porque los Server Components renderizan en el servidor.
proxy.ts en lugar de middleware.ts
Este es un gotcha que pocos mencionan. En Next.js 16, el archivo middleware.ts tradicional fue reemplazado conceptualmente por proxy.ts para interceptar requests a nivel de red. En nuestros proyectos, usamos proxy.ts para manejar autenticación de rutas protegidas, redirecciones de dominios y rate limiting básico.
El middleware clásico todavía funciona, pero proxy.ts te da control más granular sobre el request antes de que llegue al framework. Para apps con multi-tenancy o dominios personalizados, esta diferencia es crítica.
Server Actions: El fin de las API routes para CRUD
Antes de Server Actions, cada operación CRUD requería: una API route en app/api/, un fetch desde el cliente, manejo de errores en ambos lados, y serialize/deserialize de datos. Con Server Actions, la mutación es una función async que se llama directamente desde el componente:
En WouWou, Lead Desk, GlamBook y todas nuestras apps, el 90% de las operaciones de escritura son Server Actions. Las API routes las reservamos para webhooks (Stripe, WhatsApp), integraciones externas y endpoints que necesitan autenticación por API key.
El resultado: menos código, menos superficie de ataque, menos bugs de serialización, desarrollo más rápido.
Por qué Next.js y no Remix, Nuxt o SvelteKit
Remix: Excelente framework, pero el ecosistema de componentes y librerías es significativamente más pequeño que el de Next.js. Cuando necesitas una librería de charts, un date picker, un editor de texto rico o un componente de drag-and-drop, en React/Next.js tienes 10 opciones probadas en producción. En Remix tienes 2-3.
Nuxt (Vue): Lo usamos en un proyecto en 2023. El framework es sólido, pero encontramos que la velocidad de desarrollo es menor porque Vue requiere más boilerplate que React para componentes complejos. En un contexto donde estamos construyendo 2-3 apps por mes, esa diferencia se acumula.
SvelteKit: Tecnológicamente superior en varias métricas, pero el ecosistema de componentes empresariales (tablas, formularios complejos, dashboards) es inmaduro comparado con React. Para un blog personal, SvelteKit es fenomenal. Para un CRM con 25 modelos de datos, necesitas el ecosistema React.
Prisma 7 con PrismaPg: ORM de Producción (Con Sus Gotchas)
Prisma es nuestro ORM (Object-Relational Mapper) y honestamente, es una relación de amor-odio. Lo seguimos usando porque las alternativas son peores, no porque sea perfecto.
Lo que Prisma 7 hace extraordinariamente bien
Type safety end-to-end: El schema de Prisma genera tipos de TypeScript automáticamente. Cuando agregas un campo a un modelo, tu IDE te marca inmediatamente todos los lugares del código donde necesitas actualizar. En un proyecto con 25 modelos como GlamBook, esto evita literalmente cientos de bugs.
Migraciones declarativas: Defines el estado deseado de tu base de datos en el schema, Prisma calcula el diff y genera la migración SQL. No escribes SQL a mano para ALTER TABLE. Esto es especialmente valioso cuando tienes múltiples entornos (local, staging, producción).
Relaciones intuitivas: Un include: { appointments: true } te trae el cliente con todas sus citas. Un select granular evita over-fetching. Para el 95% de las consultas, Prisma genera SQL eficiente.
El adapter PrismaPg: por qué existe y cómo se configura
En Prisma 7, la conexión a PostgreSQL cambió significativamente. Ya no usas la URL directamente en el schema.prisma — usas el adapter @prisma/adapter-pg con PrismaPg en tu archivo de configuración prisma.config.ts.
¿Por qué el cambio? Prisma 7 movió a un modelo de drivers nativos que permite más control sobre la conexión, pool sizing y timeouts. En producción con Docker, esto importa porque puedes ajustar el pool de conexiones según los recursos del contenedor.
En nuestro lib/prisma.ts de cada proyecto, el patrón es siempre el mismo: singleton de PrismaClient con adapter PrismaPg, la URL se lee de DATABASE_URL del .env, y en desarrollo hay un global que previene múltiples instancias por hot reload.
Los gotchas de Prisma en Docker
Aquí es donde la documentación oficial se queda corta y la experiencia real importa:
- Binary targets: Prisma genera binarios platform-specific. Si desarrollas en macOS (ARM) y despliegas en Linux (x64), necesitas declarar ambos targets en el schema. Si olvidas esto, tu app crashea en producción con un error críptico de “query engine not found”.
- prisma generate en Docker build: El
RUN npx prisma generatedebe ir DESPUÉS delCOPY prisma/ prisma/pero ANTES delCOPY . .para aprovechar la cache de layers. Si lo pones al final, cada cambio en cualquier archivo regenera Prisma innecesariamente. - Migraciones en producción: Nunca corras
prisma migrate deven producción. Siempreprisma migrate deploy. La diferencia es quedevpuede hacer reset de la base de datos si encuentra drift, y “reset en producción” = pérdida de datos. - Connection pool en contenedores: El pool default de Prisma es de 10 conexiones. Si tienes 5 apps conectándose al mismo PostgreSQL, eso son 50 conexiones. PostgreSQL por default acepta 100. A la sexta app, empiezas a recibir “too many clients”. Ajusta
connection_limita 3-5 por app.
Por qué Prisma y no Drizzle, TypeORM o SQL raw
Drizzle: Más ligero, más cercano al SQL, excelente performance. Pero las migraciones son menos maduras que las de Prisma, y el ecosistema de herramientas (Prisma Studio, extensiones VS Code) es más limitado. Para proyectos nuevos donde sabes exactamente qué vas a consultar, Drizzle es competitivo. Para proyectos que evolucionan rápidamente con modelos cambiantes, Prisma gana.
TypeORM: Lo usamos en un proyecto en 2023. Los decoradores son verbosos, el manejo de relaciones es más propenso a errores, y la experiencia de TypeScript es inferior a la de Prisma. No regresamos.
SQL raw: Para consultas complejas de reporting o analytics, sí usamos prisma.$queryRaw. Pero para CRUD diario, escribir SQL a mano en 2026 es como escribir ensamblador: funciona, pero hay mejores abstracciones.
PostgreSQL: La Base de Datos Que No Falla (y Por Qué No Usamos SQLite en Producción)
Cada una de nuestras apps en producción usa PostgreSQL. Cada una tiene su propia instancia de PostgreSQL en un contenedor Docker dedicado. No compartimos bases de datos entre apps.
Por qué no SQLite en producción
SQLite es fantástico para desarrollo local y para apps que tienen un solo proceso de escritura. Pero en producción con múltiples usuarios concurrentes, SQLite tiene un problema fundamental: write lock a nivel de base de datos. Si dos usuarios guardan datos al mismo tiempo, uno tiene que esperar.
En nuestro Cotizador, la primera versión usaba SQLite. Funcionó bien con 5 usuarios. Con 50 usuarios concurrentes, las escrituras empezaron a fallar con errores de “database is locked”. Migramos a PostgreSQL y el problema desapareció permanentemente.
La regla que seguimos es simple: SQLite para prototipos y desarrollo local, PostgreSQL para todo lo que va a producción.
PostgreSQL por contenedor: aislamiento total
Cada app tiene su propio contenedor postgres:16-alpine con su propia base de datos, usuario y contraseña. ¿Por qué no un solo PostgreSQL compartido? Por seguridad y operaciones:
- Seguridad: Si una app tiene una vulnerabilidad de SQL injection, solo accede a su propia base de datos. Las otras apps no se ven afectadas.
- Backup independiente: Puedes hacer backup y restore de una app sin tocar las demás.
- Recursos aislados: Si WouWou tiene un query pesado, no ralentiza Lead Desk.
- Versiones independientes: Si necesitas migrar una app a PostgreSQL 17 beta, puedes hacerlo sin afectar las demás.
El overhead de memoria es mínimo: cada instancia de PostgreSQL Alpine usa ~30MB de RAM base. Con 15 instancias, eso son 450MB — insignificante en un VPS con 16GB.
Configuración de producción que usamos
En el docker-compose.yml de cada app, PostgreSQL se configura con volúmenes persistentes, healthcheck, y restart policy. La conexión entre la app y su base de datos se hace por la red Docker interna, nunca exponiendo el puerto 5432 al exterior.
Claude Sonnet 4.6 + Anthropic SDK: IA de Producción
Cada app de IAmanos que tiene funcionalidad de IA usa Claude de Anthropic. No usamos OpenAI GPT-4 para las features de producción. La decisión fue técnica, no ideológica.
Por qué Claude y no GPT-4
Rendimiento en español: En nuestras pruebas internas, Claude Sonnet produce texto en español más natural que GPT-4, especialmente en contextos mexicanos. Las respuestas tienen menos anglicismos, mejor manejo de modismos y un tono más apropiado para interacciones de negocio en México.
Context window: Claude ofrece 200K tokens de contexto (1M en la versión extendida). Para apps como WouWou donde el chat Ayu necesita consultar la base de datos de 206 razas, tener un context window amplio es esencial para dar respuestas informadas.
Consistencia: Claude es más consistente en seguir instrucciones del system prompt. En un chatbot de producción, la consistencia importa más que la creatividad máxima — quieres que el bot responda de la misma forma al mismo tipo de pregunta, siempre.
Precio: Claude Sonnet 4.6 es competitivo en precio con GPT-4. Para generación de contenido en lote (las 206 razas de WouWou costaron $19.28 USD), es extraordinariamente eficiente.
Cómo integramos Claude en cada app
Usamos el Anthropic SDK oficial para JavaScript. El patrón es siempre el mismo:
- System prompt específico por app: Cada app tiene un system prompt que define el rol, las herramientas disponibles y las restricciones. El system prompt de Ayu (WouWou) es completamente diferente al del chat de iAmanos.
- Tools/Function calling: Claude no solo genera texto — ejecuta acciones. En WouWou, Ayu tiene 7 herramientas que puede invocar: buscar razas, cotizar servicios, consultar inventario, agendar citas, etc.
- Streaming: Todas nuestras interfaces de chat usan streaming. La respuesta empieza a aparecer inmediatamente, no después de que Claude termina de generar todo el texto. La percepción de velocidad mejora dramáticamente.
- Rate limiting y fallback: Cada app tiene rate limiting por usuario (máximo N requests por minuto) y un fallback graceful si la API de Anthropic no responde en 10 segundos.
Costos reales de la API de Anthropic
Nuestro gasto mensual en API de Anthropic para todas las apps en producción es de aproximadamente $150 USD. Eso cubre el chat IA de WouWou, el chat de iAmanos, las funcionalidades de IA en Lead Desk, Terminal, y las demás apps. El secreto es usar Claude Sonnet (no Opus) para la mayoría de las interacciones, reservando Opus para tareas que requieren razonamiento complejo.
Tailwind v4 + NextAuth v5: UI y Autenticación
Tailwind v4: CSS sin drama
Tailwind es nuestra solución de styling para todas las apps. En la versión 4, las mejoras más relevantes para nuestro flujo de trabajo son:
- CSS nativo en lugar de PostCSS: Tailwind v4 compila directamente a CSS sin PostCSS como intermediario. El build es más rápido y hay menos capas de abstracción que pueden fallar.
- Container queries: Para componentes que necesitan responder a su contenedor y no al viewport (como tarjetas en un dashboard), container queries eliminaron una categoría completa de hacks CSS que usábamos antes.
- Dark mode mejorado: Varias de nuestras apps (GlamBook, Terminal) tienen dark mode. Tailwind v4 simplificó la implementación con
@variant dark.
No usamos ninguna librería de componentes tipo Chakra UI, Material UI o shadcn/ui como dependencia directa. Construimos nuestro propio set de componentes base con Tailwind puro. La razón es control: cuando necesitas que un botón se comporte exactamente como tu diseño exige, una librería de componentes se convierte en obstáculo.
NextAuth v5: Autenticación que no reinventamos
NextAuth v5 (ahora Auth.js) maneja la autenticación en todas nuestras apps. El patrón es siempre Credentials Provider (email + contraseña hasheado con bcrypt) con JWT sessions.
¿Por qué no usamos OAuth con Google/GitHub? Porque nuestros clientes son negocios mexicanos. El administrador de una veterinaria no tiene cuenta de GitHub, y usar Google OAuth agrega una dependencia externa innecesaria. Email + contraseña es universal, funciona siempre, y no depende de terceros.
En apps con roles (Lead Desk tiene admin y asesor, WouWou tiene admin y cliente), el rol se guarda en el JWT y se valida en el middleware/proxy. Un asesor no puede acceder a /admin aunque modifique la URL a mano.
Docker Multi-Stage Builds: De Código a Contenedor en 2 Minutos
Todas nuestras apps usan Dockerfile multi-stage. El patrón es el mismo para cada proyecto:
Stage 1 — Dependencies: Instala node_modules. Esta layer se cachea mientras el package.json no cambie, ahorrando tiempo en builds subsecuentes.
Stage 2 — Build: Copia el código, genera Prisma, ejecuta next build. Produce el output standalone.
Stage 3 — Production: Image base node:20-alpine, copia solo el output del build, no los node_modules completos. La imagen final pesa ~150MB en lugar de ~800MB.
Por qué multi-stage importa
- Seguridad: La imagen de producción no tiene devDependencies, no tiene el código fuente completo, no tiene herramientas de build. Superficie de ataque mínima.
- Tamaño: 150MB vs 800MB. Con 15 apps, eso es 2.25GB vs 12GB de imágenes en el VPS. El disco importa.
- Deploy más rápido: Imagen más pequeña = build más rápido = menos downtime.
El script de deploy
Cada proyecto tiene un deploy.sh que ejecuta tres pasos: rsync del código local al VPS, docker build en el VPS, y docker compose up -d para reiniciar el contenedor. Todo el proceso tarda menos de 2 minutos para la mayoría de las apps.
No usamos CI/CD con GitHub Actions ni pipelines automatizados. ¿Por qué? Porque somos un equipo pequeño construyendo apps a alta velocidad. La complejidad de mantener pipelines de CI/CD no se justifica cuando un bash deploy.sh hace el mismo trabajo en menos tiempo. Cuando crezcamos a 10 devs, revisaremos esta decisión.
Comparaciones Reales: Por Qué No Elegimos Laravel, Supabase o Firebase
Laravel
Laravel es un framework excelente con una comunidad enorme. Lo descartamos por tres razones específicas:
- Lenguaje: PHP vs TypeScript. Con TypeScript, usamos el mismo lenguaje en frontend y backend. Con Laravel, necesitas PHP en backend y JavaScript/TypeScript en frontend. Dos mundos, dos mentalidades, más fricción.
- IA: La integración de modelos de IA (Anthropic, OpenAI) tiene mejor soporte nativo en el ecosistema JavaScript/TypeScript. Los SDK oficiales son first-class citizens en Node.js.
- Componentes: React tiene el ecosistema de componentes más grande del mundo. Laravel Livewire es poderoso, pero no tiene la misma variedad de componentes listos para producción.
Si estuviéramos construyendo un ERP tradicional sin IA, Laravel sería una opción perfectamente válida. Pero para SaaS con IA integrada, Next.js + TypeScript es objetivamente más eficiente.
Supabase
Supabase es PostgreSQL como servicio con autenticación, storage y functions incluidos. Lo usamos en un proyecto piloto y encontramos tres limitaciones:
- Vendor lock-in: Las funciones RPC de Supabase y su sistema de Row Level Security son específicos de Supabase. Si necesitas migrar a otro proveedor, reescribes una parte significativa del backend.
- Costo a escala: El tier gratuito es generoso para prototipos. El tier Pro ($25/mes) tiene límites de bandwidth, storage y requests que se alcanzan rápido con una app en producción con tráfico real. Con nuestro setup Docker + PostgreSQL propio, pagamos $0 por base de datos (está incluido en el VPS).
- Flexibilidad: Supabase te da un PostgreSQL con restricciones. Nuestro PostgreSQL en Docker no tiene restricciones — podemos instalar extensiones, configurar replicación, ajustar memory settings, lo que necesitemos.
Firebase
Firebase fue una opción seria en 2022. En 2026, para SaaS con datos relacionales, ya no lo es:
- NoSQL: Firestore es una base de datos documental. Las relaciones entre entidades (un cliente tiene citas, cada cita tiene servicios, cada servicio tiene precio) son naturales en PostgreSQL y artificiales en Firestore. En un CRM como Lead Desk con 25+ modelos relacionados, Firestore sería una pesadilla.
- Costos impredecibles: Firebase cobra por lectura, escritura y transfer. Un dashboard que muestra 50 registros hace 50 lecturas. Si 100 usuarios abren el dashboard, son 5,000 lecturas. Los costos escalan de forma no lineal y difícil de predecir.
- Google lock-in: Tu base de datos vive en los servidores de Google. Si Google decide cambiar precios, descontinuar Firestore (como hizo con otros productos), o si tienes un problema con tu cuenta de Google Cloud, no tienes alternativa inmediata.
Velocidad de Desarrollo: De Idea a Producción en Días
La ventaja más importante de nuestro stack no es el performance ni el costo — es la velocidad de desarrollo.
Con el stack estandarizado, un nuevo proyecto SaaS sigue este timeline:
- Día 1: Clonar boilerplate, definir modelos de Prisma, configurar NextAuth, crear layout base con Tailwind.
- Día 2-3: Construir las páginas principales con Server Components y Server Actions. CRUD completo para los modelos core.
- Día 4: Integrar Claude si la app tiene funcionalidad de IA. Configurar system prompt y tools.
- Día 5: Dockerfile, deploy.sh, primer deploy al VPS. App en producción con dominio y SSL.
Cinco días de idea a producción. No para un prototipo — para una app funcional con autenticación, base de datos, IA y SSL en un dominio real.
¿Cómo es posible? Porque no reinventamos nada. El boilerplate ya tiene la autenticación configurada, el Dockerfile optimizado, el schema de Prisma base, los componentes de UI más comunes, y los patrones de integración con Claude. Cada proyecto nuevo hereda todo eso y solo agrega lo específico del dominio.
Para comparar: con Laravel + Vue + configuración manual de servidor, el mismo proceso toma 2-3 semanas. Con Firebase + React sin framework de servidor, toma 1-2 semanas pero con deuda técnica que pagas después. Nuestro stack nos da velocidad SIN deuda.
Costos Reales del Stack en Producción
Transparencia total. Esto es lo que cuesta mantener 15+ apps en producción con este stack:
- VPS Hostinger KVM: $200 USD/mes — aloja TODAS las apps con Docker + Traefik.
- Dominios: ~$50 USD/mes prorrateado — dominios .com y subdominios.
- API Anthropic (Claude): ~$150 USD/mes — todas las features de IA de todas las apps.
- Google AI (Imagen, Maps): ~$50 USD/mes — generación de imágenes y servicios de mapas.
- Email (Resend): $0 — tier gratuito cubre nuestro volumen actual.
- SSL (Let’s Encrypt via Traefik): $0 — certificados gratuitos renovados automáticamente.
- Monitoring: $0 — Docker logs + scripts propios.
Total: ~$450 USD/mes para 15+ apps en producción.
Compara esto con AWS/GCP para el mismo setup: EC2 instances, RDS instances, load balancers, CloudFront, ACM, Route53, CloudWatch. Fácilmente $3,000+ USD/mes. Nuestro stack cuesta 85% menos que la alternativa cloud enterprise.
Y el revenue: un solo cliente de WouWou a $377/mes casi cubre la infraestructura completa. El modelo de negocio funciona porque los costos fijos son bajos.
Cuándo Este Stack Es (y No Es) la Decisión Correcta
Usa este stack si:
- Estás construyendo un SaaS B2B con datos relacionales (CRM, ERP, gestión, plataformas).
- Tu app necesita IA integrada (chatbots, generación de contenido, análisis).
- Quieres controlar tu infraestructura y mantener costos bajos.
- Tu equipo sabe TypeScript (o está dispuesto a aprenderlo).
- Necesitas desplegar rápido y iterar sobre la marcha.
Considera alternativas si:
- Tu app es mobile-first: React Native o Flutter pueden ser mejor opción que un PWA con Next.js.
- Tu equipo es PHP: Laravel es productivo si tu equipo ya domina el stack.
- Solo necesitas un landing page: Astro o Hugo son mejores que Next.js para sitios estáticos puros.
- Necesitas real-time intensivo: Phoenix (Elixir) o un backend WebSocket dedicado puede ser más apropiado que Next.js para apps con miles de conexiones WebSocket simultáneas.
No existe el stack perfecto universal. Existe el stack correcto para tu contexto. El nuestro funciona para SaaS con IA en México, y después de 15+ apps, estamos seguros de ello.
Si quieres que construyamos tu SaaS con este stack, conoce nuestra fábrica de apps o ve las apps que ya hemos construido.
¿Quieres una app con IA para tu negocio? Agenda una llamada →
Preguntas Frecuentes
¿Qué stack tecnológico usa IAmanos para construir SaaS en México?
IAmanos usa Next.js 16 (App Router), Prisma 7 con PrismaPg adapter, PostgreSQL, Claude Sonnet 4.6 (Anthropic SDK), Tailwind v4, NextAuth v5 y Docker multi-stage builds. Este stack está validado en 15+ apps en producción incluyendo WouWou, GlamBook, Lead Desk, PrintDesk y más.
¿Por qué Next.js en lugar de Laravel para SaaS con IA?
Next.js permite usar TypeScript en frontend y backend (mismo lenguaje), tiene mejor integración nativa con SDKs de IA (Anthropic, OpenAI), y el ecosistema de componentes React es el más grande del mundo. Laravel es excelente para proyectos sin IA, pero para SaaS con inteligencia artificial integrada, Next.js + TypeScript es más eficiente.
¿Cuánto cuesta mantener un SaaS en producción con este stack?
IAmanos mantiene 15+ apps en producción por aproximadamente $450 USD/mes total: $200 VPS, $150 API Anthropic, $50 dominios, $50 Google AI. SSL es gratuito con Let’s Encrypt vía Traefik. El mismo setup en AWS costaría $3,000+ USD/mes.
¿Cuánto tiempo toma construir un SaaS con el stack de IAmanos?
Con el boilerplate estandarizado, un nuevo SaaS funcional va de idea a producción en 5 días: día 1 modelos y auth, días 2-3 páginas y CRUD, día 4 integración IA, día 5 deploy con Docker y SSL. No es un prototipo — es una app completa con autenticación, base de datos y dominio real.
¿Prisma 7 o Drizzle ORM para proyectos nuevos en 2026?
Prisma 7 para proyectos con modelos de datos que cambian frecuentemente y donde el type safety end-to-end es crítico (CRMs, ERPs, plataformas). Drizzle para proyectos donde sabes exactamente qué vas a consultar y quieres estar más cerca del SQL. IAmanos usa Prisma porque construimos apps que evolucionan rápido con muchos modelos relacionados.