VAMPMAKER — Convertir una demo en un producto cobrable

Vídeo — VAMPMAKER — Convertir una demo en un producto cobrable

Un SaaS que prepara la partida de rol antes de que empiece la partida · SaaS · Nicho B2C · TRPG

Cliente
Side project — RBT Studio
Rol
Full Stack / AI Engineer — producto, arquitectura y desarrollo
Periodo
Mayo 2026 – en curso (Release 1.0)
Stack
TypeScript, NestJS 11, Next.js 16, React 19, Prisma, PostgreSQL · Neon, Zustand, Tailwind 4, OpenRouter, Pollinations.ai

Dirigir una crónica se parece más a producir una serie que a jugar una partida

El Narrador llega al viernes con un arco de cinco sesiones que sostener, una ciudad con su jerarquía política, una docena de NPCs que deben sonar distintos entre sí y fichas que cuadren con la edición que se está jugando. Casi todo ese trabajo ocurre antes de que nadie tire un dado. VampMaker nació para absorber esa preparación, y la primera versión lo hacía bien. El problema era lo que pasaba después.

El problema: Nada de lo generado sobrevivía al navegador

Una auditoría del código en agosto de 2026 dejó el diagnóstico en una frase. El store escribía solo en localStorage, y el CRUD completo del backend NestJS —veinte y pico endpoints, con su esquema de PostgreSQL, sus relaciones y sus borrados en cascada— nunca llegaba a invocarse: saveCampaign() y loadCampaigns() estaban escritas, probadas contra la API y sin una sola llamada desde la interfaz. El resultado era un producto que se presentaba como SaaS —con cuenta, con tiers, con un «Plan Gratuito» en la barra lateral— y que perdía la campaña del usuario al cambiar de dispositivo. El encargo real no era añadir IA: era convertir una demo funcional en un producto cobrable.

Cómo se abordó

  1. La spec antes que el código. Con un hallazgo de ese calibre la tentación es abrir el editor y empezar a conectar cables. Escribí primero la especificación: cuatro documentos SDD —SPEC, ARCHITECTURE, SCAFFOLD, AGENTS— que fijan objetivos, no-objetivos y criterios de aceptación verificables antes de tocar una línea. Definir los no-objetivos resultó tan útil como los objetivos: pasarela de pago, colaboración multiusuario, app nativa y export a PDF quedaron fuera de Release 1.0 por escrito, y eso cerró la puerta a tres meses de deriva de alcance.
  2. Ocho agentes con su grafo de dependencias. Sobre esa spec monté un harness de ocho agentes. El proyecto lo desarrolla una sola persona, así que la división no busca paralelismo humano: busca que cada sesión de trabajo —propia o con un LLM— tenga un alcance cerrado y una definition of done comprobable.
  3. Seis decisiones documentadas como ADR. El servidor pasa a ser la fuente de verdad y localStorage baja de almacén a caché read-through. Identificadores string (cuid) de extremo a extremo, porque el frontend asumía number y en cuanto Prisma emite cuids el usuario ve «Campaña no encontrada» por un problema que en realidad es de tipos — este ADR bloquea a todos los demás. Lo que no cabe en el esquema va a columnas Json, no a tablas nuevas. Persistencia write-through síncrona por operación: una petición extra es irrelevante frente a los 10–30 segundos de una generación, y a cambio el fallo es atribuible a una acción concreta. Contrato de API estricto con un único envelope de error. Y la cuota como Guard que reserva antes e Interceptor que confirma después, de modo que una generación fallida no consuma saldo.
  4. La capa de IA, tratada como ingeniería y no como conversación. Conectar OpenRouter son veinte líneas. Lo difícil fue conseguir que el modelo devolviera siempre algo renderizable, en el idioma correcto y sin contradecir el canon de la edición elegida. Idioma: parte del inglés que se colaba no venía del modelo sino de una plantilla del propio código, y la regla explícita separa hoy claves (intactas, las consume el frontend) de valores (en español, con la terminología del juego traducida). Esquema: «devuelve SOLO JSON válido» no es una especificación, así que el prompt lleva ahora el esquema explícito con su ramificación entre ediciones. Canon en capas: núcleo universal, capa por edición y las maldiciones solo de los clanes que aparecen en la petición — antes se inyectaban las quince y se afirmaba que «la Mascarada es ley absoluta» incluso en una campaña de Dark Ages, donde no se declara hasta 1666.

harness de 8 agentes: CostProbe → ContractMigrator → PersistenceBuilder → ResilienceBuilder → ExperienceBuilder → QuotaBuilder → DocWriter

Solución: Monorepo con tres workspaces y un contrato que rompe la compilación, no la producción

backend, frontend y shared, donde el paquete compartido contiene los tipos de dominio que ambos extremos consumen. Backend NestJS 11 con módulos por dominio, Prisma sobre PostgreSQL en Neon, JWT en cookie httpOnly y filtro global de excepciones. Frontend Next.js 16 con React 19, App Router, Zustand y una vista de campaña con pestañas: arco, sesiones, NPCs, fichas y mapas. Motor de generación con seis endpoints sobre deepseek-chat vía OpenRouter para texto y Pollinations.ai para imágenes — el prompt de imagen se mantiene deliberadamente en inglés, porque los modelos de difusión rinden peor en español: lo que se traduce es lo que ve el usuario, no lo que consume el generador. Cuatro ediciones soportadas (V5, V20, Dark Ages y Sabbat), cada una con su lore, sus facciones y sus cargos de ciudad.

Resultados

No hay métricas de uso que enseñar: el producto está en fase de Release 1.0 y la persistencia servidor-autoritativa está en curso. Lo que sí hay es criterio acumulado, que es lo que de verdad viaja de un proyecto al siguiente. Release 1.0 cierra persistencia servidor-autoritativa, errores no silenciosos, un único camino de navegación, export a Markdown para llevar el material a la mesa y límite de cuota por cuenta.

  • 6 ADR — decisiones estructurales con su alternativa descartada
  • ~190 — tokens ahorrados por generación al dejar de repetir la regla de idioma seis veces
  • 4 — ediciones soportadas, cada una con su lore y sus cargos

"Antes de tocar el prompt, averigua quién escribe el texto. Pasé un rato convencido de que el inglés venía del modelo. Una parte venía de una plantilla del propio código."

Qué se aprendió

  1. Un prompt sin esquema es una API sin contrato. «Devuelve JSON válido» no es una especificación. Si la interfaz espera quince claves concretas, esas quince claves van en el prompt — y las que consume el código no se traducen aunque el resto del contenido sí.
  2. El contexto que contradice al dominio cuesta más que el contexto que falta. Inyectar las reglas de la Camarilla en una campaña medieval no es solo desperdiciar tokens: es pedirle activamente al modelo que se equivoque. Trocear el canon por edición mejoró la salida y la abarató.
  3. Un hook con useState no es estado compartido. Cada componente que llamaba a useAuth tenía su propio user y su propia petición. Como la barra lateral vive en el layout raíz y no se remonta al navegar, el login funcionaba de verdad —cookie emitida, sesión válida— pero la aplicación seguía pintándose como si no. Un error de arquitectura de estado disfrazado de bug de autenticación.
  4. Escribir la spec primero convirtió «arreglar la app» en ocho unidades verificables. Es la diferencia entre un refactor que no se sabe cuándo termina y ocho bloques con criterio de terminado.

Repositorio y demo pendientes de publicar.

Más casos

  • STORYPRINTS — Ocho respuestas de un padre convertidas en un objeto físico en dos minutos
  • BRANDAI — Identidad de marca portable entre herramientas de IA
  • RBT.STUDIO — Cuando el producto eres tú mismo
  • AIMPLAS — App 3D para tablets que acompaña a un casco y un patinete reales
  • D-GO — Web para D-Go, un motor direct-drive para bicicletas de carga
  • THE SMART LOLLIPOP — Landing para The Smart Lollipop, un dispositivo de salud infantil
  • EONIA — La capa de decisión biológica que faltaba entre medir e intervenir
  • EL ÚLTIMO ZARPE — Un roguelike sin meta-progresión, donde solo se acumula comprensión
  • FOTOGRAFÍA · DIRECCIÓN DE ARTE — Una gramática visual, no un estilo — del negativo de medio formato al libro impreso
  • NOTJUSTCODE — Visión, diseño y mercado revisados dentro del editor, sobre el repositorio
  • SDD HARNESS — Un wizard de 5 fases para que los agentes construyan lo que tenía en la cabeza

La cuarta tinta

Cuéntame el proyecto. Respondo en menos de 24 horas, desde Barcelona.

contact@rbt-studio.com