Lovable → arquitectura de producción

Tu app de Lovable funciona.
Su arquitectura nunca existió.

Lovable generó tu codebase entero un prompt a la vez, y nadie — ni humano ni modelo — diseñó jamás cómo encaja todo. Ahora cada feature nueva cuesta más que la anterior, y el agente que escribió la app no puede desenredarla. useDeploy le da a tu producto la arquitectura de backend que nunca tuvo: módulos acotados, fronteras enforzadas en CI y contratos tipados. El front que tus usuarios validaron se queda; el spaghetti es lo que se va.

Por qué las apps de Lovable se pudren desde adentro

Lovable no degrada un codebase — genera uno que nunca estuvo estructurado. Cada prompt apila código donde al modelo le queda cómodo: reglas de negocio adentro de componentes, llamadas a la base al lado de click handlers, helpers duplicados porque el modelo no ve los cinco que ya escribió. Los builders describen siempre el mismo arco — "para el prompt 50 es spaghetti" (aiboilerplate.dev). Y a diferencia de un desorden humano, este no tiene ningún hilo del que tirar. Los devs humanos dejan patrones consistentes que podés aprender y contra los que refactorizar; como lo puso un comentarista de Hacker News, el código de un LLM "no tiene nada de eso, y si lo tiene es de pura casualidad y no se repite" (news.ycombinator.com). Mientras la app es chica, nada de esto duele. El día que tenés usuarios reales y necesitás cambiar el pricing o arreglar un bug de permisos, descubrís que no hay ningún lugar donde las cosas viven — solo lugares donde las cosas terminaron.

Síntomas que tu app de Lovable ya tiene

El prompt 51 rompe los prompts 12 y 34

Pedís un cambio y features que shippeaste hace semanas dejan de andar en silencio. Nada aísla nada, así que el blast radius de cada edición es la app entera.

El mismo fetch, pegado nueve veces

Lovable no ve los helpers que ya escribió, así que cada pantalla re-implementa la misma query con filtros apenas distintos. Arreglar el bug es encontrar las nueve copias — y vas a encontrar siete.

Nadie sabe dónde vive el pricing

Los límites de plan se chequean en la UI, se asumen en un webhook y están hardcodeados en dos componentes. Cambiás uno y los otros discrepan en silencio.

Frontend y backend comparten archivo

Render, chequeos de auth y escrituras de datos conviven en el mismo componente. No hay ninguna línea que el modelo no cruce, porque nunca se dibujó ninguna.

Dejaste de pedir cambios

El síntoma más claro: evitás tocar features que andan porque no podés predecir qué se lleva puesto el próximo prompt.

Cómo se ve la estructura de verdad

En useDeploy, cada capability es un módulo acotado con cuatro capas, y el layering no es un diagrama en un README — es una regla que el build enforza. El flat-config de ESLint le prohíbe al código de domain importar Express, Prisma o cualquier cosa de la capa de infraestructura; un agente (o un humano cansado) que cruza la línea se come un CI en rojo, no una podredumbre lenta. Este árbol es todo el modelo mental: cuando preguntás "¿dónde vive X?", el directorio responde.

apps/server/src/modules
 1  apps/server/src/modules/
 2  ├── iam/          # auth, sessions, users
 3  │   ├── domain/          # business rules — no I/O
 4  │   ├── application/     # use cases + ports
 5  │   ├── infrastructure/  # Prisma repos, adapters
 6  │   └── interfaces/http/ # routes + Zod schemas
 7  ├── tenancy/      # orgs, members, invitations
 8  ├── billing/      # plans, providers, webhooks
 9  ├── storage/      # uploads + storage adapters
10  ├── ai/           # LLM provider, streaming
11  └── webhooks/     # signed outgoing delivery

Lo que ya viene estructurado

Fronteras que rompen el build

Layering DDD enforzado por el flat-config de ESLint: el código de domain no puede importar express, @prisma/client ni infraestructura. Cruzá la línea y el CI se pone en rojo — es una pared, no una convención.

Contratos que atrapan el payload drift

Schemas Zod compartidos vía @app/contracts, un cliente openapi-fetch tipado y un gate de CI api-types-fresh que falla cuando server y cliente discrepan — sobre payloads reales, no solo tipos.

Seis bounded contexts el día uno

iam, tenancy, billing, storage, ai y webhooks viven cada uno en su propio módulo, partido en capas de domain, application, infrastructure e interface.

450+ tests y un gate E2E

Una suite de regresión más un gate end-to-end de Playwright en CI. "Sigue andando" es algo que el pipeline demuestra, no algo que esperás.

Side effects fuera de los handlers

Un event bus con outbox durable: emails, webhooks y syncs se despachan de forma confiable en vez de vivir inline en los route handlers.

Docs que el agente lee de verdad

Un CLAUDE.md operativo más docs de arquitectura en /docs, para que cada prompt arranque desde las reglas del repo y no desde los defaults del modelo.

El camino de migración: quedate con el front, reconstruí el back

No tenés que tirar lo que funcionó. El front-end que produjo Lovable suele ser la parte genuinamente validada — usuarios reales lo clickearon — y es React, así que viaja. Exportá tu código, quedate con las pantallas y reconstruí el backend sobre useDeploy en vez de desenredar lo que Lovable improvisó. Auth, organizaciones, billing y uploads ya existen como módulos testeados, lo que reduce el trabajo a una sola tarea: mover la lógica de negocio real de tu producto — una fracción del código generado — a bounded contexts donde por fin tiene una dirección. Andá ruta por ruta: elegí una pantalla, apuntá su acceso a datos al cliente de API tipado, borrá el backend improvisado del que dependía. Cada ruta que movés achica el spaghetti y agranda la parte de tu app que el CI defiende activamente.

Preguntas de builders de Lovable

¿Puedo quedarme con el front-end que armó Lovable?+
En general, sí. Lovable emite React, y las pantallas que iteraste con usuarios reales son la parte más validada de tu app. La reconstrucción apunta a la parte que los usuarios nunca vieron — el backend — que es donde el spaghetti vive de verdad. Exportá tu código, quedate con los componentes y apuntá su acceso a datos al cliente de API tipado de useDeploy.
¿Esto no es el rewrite del que todos me advirtieron?+
Es una fracción de uno. La advertencia asume que reescribís todo; acá, auth, organizaciones, billing y uploads ya existen como módulos testeados — solo reescribís la lógica que es única de tu producto. Eso suele ser una parte chica de lo que Lovable generó, porque la mayoría del código generado era plomería.
¿Puedo seguir construyendo con IA después?+
Ese es el punto de las paredes. Los agentes siguen escribiendo features adentro de la estructura de módulos, y las fronteras las enforzan ESLint y CI — un prompt no puede mover en silencio llamadas a la base adentro de las reglas de negocio ni driftear la API, porque el build falla antes. Te quedás con la velocidad; te sacás el miedo.
No soy dev de backend. ¿De verdad puedo hacer esto?+
Con honestidad: vas a necesitar un agente (Claude Code, Cursor) y la disposición a leer lo que hace. El repo shippea un CLAUDE.md operativo y docs de arquitectura en /docs justamente para que un agente haga el trabajo pesado bajo reglas. Si no querés ver código nunca, combinar la base con un dev freelance para el port sigue siendo más barato que rescates en serie sobre el spaghetti.

Una licencia. Dos formas de tenerla.

CORE

Founder

$99pago único

Un snapshot congelado de UseDeploy. Tuyo para siempre, sin updates.

  • Descarga del zip con versión frozen
  • Código completo, uso comercial, proyectos ilimitados
  • Los 800+ tests · todas las páginas de docs
  • Refund a 14 días
RECOMMENDED

LATEST + UPDATES

Lifetime

$199$249pago único

Siempre el último UseDeploy. Re-descargá cada release, gratis.

  • Zip de la última versión — re-descargable para siempre
  • Cada release futuro sin cargo extra
  • Soporte Discord priority
  • Los 800+ tests · todas las páginas de docs
  • Refund a 14 días

Dale a tu app la arquitectura que se salteó

useDeploy es una base SaaS Bun + Express + Prisma + Next.js con fronteras DDD enforzadas en CI. Auth, orgs y billing ya están construidos — tu agente arma features adentro de paredes que no puede cruzar.