Prompts para código mantenible: reglas para carpetas y nomenclatura
Escribe prompts para código mantenible añadiendo reglas claras para la estructura de carpetas, la nomenclatura y la configuración, de modo que la salida de la IA sea fácil de depurar y de desplegar.

Por qué el código generado por IA se vuelve difícil de mantener
El código generado por IA impresiona el primer día porque funciona rápido y muestra resultados al instante. El problema empieza unos días después, cuando necesitas añadir una función, corregir un bug o entregar el proyecto a otra persona. Sin reglas claras, el modelo optimiza por “hacer que funcione ahora”, no por “hacer que sea fácil de cambiar después”.
Los prompts vagos son la causa habitual. Si no especificas la estructura de carpetas, las reglas de nombres y la configuración, el modelo completa los huecos de forma distinta cada vez. Así acabas con archivos dispersos por directorios aleatorios, tres maneras de nombrar lo mismo y ajustes escondidos en sitios que nadie piensa revisar. El código puede seguir funcionando, pero se vuelve frágil.
Señales comunes de que vas hacia un desastre de mantenimiento incluyen estilos inconsistentes para funciones similares, ubicación de archivos impredecible, nombres que derivan con el tiempo (userService, users_service, UserSvc) y configuración mezclada en el código sin valores por defecto claros. Los pequeños cambios empiezan a causar rupturas sorprendentes en otras partes.
Para un fundador en solitario o un equipo pequeño, “mantenible” suele significar que puedes encontrar las cosas rápido, cambiar un comportamiento sin romper cinco más y que una persona nueva pueda incorporarse sin una guía detallada. También implica menos sorpresas nocturnas como autenticación rota, secretos expuestos o un enredo confuso de archivos.
Añade restricciones siempre que el proyecto vaya a vivir más que una demo, o cuando esperes más de una iteración. Deja que el modelo improvise solo para experimentos descartables, pruebas rápidas o scripts puntuales. Si podrías enviarlo, mantenerlo o pagar a alguien para arreglarlo luego, establece restricciones desde el inicio.
Las tres restricciones que más importan
Si quieres prompts para código mantenible, no empieces pidiendo más funciones. Empieza añadiendo tres restricciones que decidan cómo se organiza el código, cómo se nombra y cómo se configura. Estas son dolorosas de cambiar después.
1) Estructura de carpetas (dónde va cada cosa)
Una regla de carpetas hace la salida predecible y evita el desastre de “todo en la raíz”.
Define reglas como: mantener un único punto de entrada, agrupar el código por responsabilidad y separar el código de la app de la configuración, los scripts y los tests. También di lo que nunca debe ocurrir (por ejemplo, nada de lógica de negocio en componentes UI, no código de base de datos dentro de rutas).
2) Nombres (cómo reconocerás las cosas más tarde)
Las reglas de nombres reducen trabajo duplicado y confusión. Sin ellas, te encuentras con dos archivos que hacen lo mismo o con un utils.ts que se convierte en un cajón de sastre.
Sé específico: nombres de archivo, nombres de componentes, funciones, rutas y tablas de base de datos deben seguir un estilo y reflejar su propósito. Usa verbos consistentes para acciones (create, update, delete) y evita nombres vagos como data, helper o thing.
3) Configuración (cómo se manejan ajustes y secretos)
La mayoría de prototipos generados por IA se rompen al pasar de ejecuciones locales a despliegues reales. Las restricciones claras de configuración lo evitan.
Define estas reglas desde el principio:
- Un único lugar de configuración (vars de entorno + un módulo de config), no constantes dispersas
- Separar defaults de dev y prod, con fallback seguros
- Nunca hardcodear secretos, tokens o claves API en código o archivos de ejemplo
- Proporcionar un archivo
.env.examplemínimo que solo contenga marcadores de posición - Fallar rápido si faltan configuraciones requeridas con un error claro
Si heredaste una app generada por IA que ignora estas restricciones, esta limpieza suele ser lo primero porque hace que cualquier arreglo posterior sea más sencillo.
Una plantilla de prompt reusable que puedes copiar
La victoria más rápida es un bloque pequeño y reusable de restricciones. Pégalo en cualquier solicitud y ajusta solo lo que importa para el proyecto.
Aquí tienes una plantilla que puedes copiar tal cual:
CONSTRAINTS
1) Before coding, output a brief file tree (max 15 lines). Ask 2-4 questions only if needed.
2) Folder structure:
- Keep source in /src
- Keep shared utilities in /src/lib
- Keep UI components in /src/components
- Keep config in /config
3) Naming:
- Files: kebab-case (user-profile.ts)
- React components: PascalCase
- Functions/vars: camelCase
- No single-letter names (except i/j in loops)
4) Configuration and secrets:
- Read all secrets from environment variables
- Provide a sample .env.example (no real secrets)
- Safe defaults for dev, strict checks for prod
5) If a rule conflicts with the framework:
- Follow the framework default
- Explain the conflict in 2-3 sentences
- Suggest the closest alternative that keeps the spirit of the rule
6) Output:
- Generate code file-by-file with clear filenames
- Add short comments only where the intent is not obvious
Mantén las reglas específicas, pero no sobre-detalladas. Las buenas restricciones describen resultados que puedes verificar (dónde viven los archivos, cómo lucen los nombres, de dónde vienen los secretos). Evita reglas de estilo minuciosas que generan trabajo innecesario.
Un hábito que previene salida desordenada: pide primero el árbol de archivos. Obliga al modelo a planear y te da una oportunidad rápida para decir “mueve auth a /src/lib” antes de que escriba 10 archivos.
Si estás arreglando código generado por IA después, las restricciones también aceleran la reparación. Cuando todo tiene un hogar predecible, es más fácil ver lo que falta y parchearlo sin romper partes no relacionadas.
Paso a paso: cómo escribir tus restricciones
Los buenos prompts para código mantenible empiezan con claridad y añaden solo las reglas que realmente vas a hacer cumplir. Si añades demasiadas, el modelo las ignorará o generará relleno.
Un flujo simple que funciona
Escribe tu prompt en cinco partes, en este orden:
- Empieza con una frase que indique el trabajo a hacer (para quién es y la acción principal).
- Fija lo esencial del stack (framework, lenguaje y cualquier versión que afecte sintaxis o config). Omitir lo demás.
- Define reglas del proyecto: cómo se organizan las carpetas y cómo se nombran archivos, componentes y funciones.
- Define cómo funciona la configuración: qué va en vars de entorno, qué defaults son seguros y qué nunca debe ser comiteado.
- Exige una secuencia de salida: primero un plan de archivos, luego el código y finalmente un breve auto-chequeo de lo verificado.
Este orden importa. Si comienzas con carpetas y nombres antes del objetivo, a menudo obtienes una estructura ordenada que resuelve el problema equivocado.
Ejemplo pequeño (misma idea, palabras más simples)
Imagina que quieres un rastreador de facturas simple para un freelance. Si fijas React + TypeScript y dices “mantén server code en /api, UI en /web, tipos compartidos en /shared”, evitas mucho caos. Añade nomenclatura como “components en PascalCase, hooks empiezan con use” y evitas el misterio posterior de dónde vive la lógica.
Sé estricto con la configuración: “leer secretos solo desde vars de entorno, proveer .env.example y fallar rápido con un error claro si falta una variable”. Esa sola línea evita los clásicos problemas de autenticación rota y secretos expuestos.
Termina exigiendo un resumen de auto-chequeo. Empuja al modelo a detectar archivos faltantes, nombres desajustados y defaults inseguros antes de que tú lo hagas.
Restricciones de estructura de carpetas que mantienen el proyecto ordenado
Un árbol de carpetas limpio es una de las restricciones más fáciles de añadir. La meta no es perfección: es predictibilidad, para que tú (o alguien más) pueda encontrar cosas rápido y arreglarlas sin romper partes no relacionadas.
Una estructura simple que sirve para la mayoría de apps web pequeñas podría ser:
src/ui/para pantallas y componentes reutilizablessrc/domain/para reglas de negocio (qué hace la app)src/data/para base de datos y APIs externas (cómo se guarda/obtiene la info)src/shared/para helpers verdaderamente compartidos (pequeños, aburridos, reutilizados)src/config/para defaults de la app (no secretos)
Añade una regla más: separa UI, lógica de negocio y acceso a datos. En términos simples, la UI no debería hablar directamente con la base de datos y el código de base de datos no debería decidir qué puede hacer un usuario.
Para evitar archivos de 800 líneas, define “una responsabilidad por archivo” de forma práctica. Un archivo debe tener un propósito principal (un componente, un servicio, un repositorio). Si necesita dos cabeceras distintas, sepáralo. Si se reutiliza en tres lugares, muévelo a shared/. Si solo se reutiliza dentro de una feature, mantenlo dentro de esa carpeta. Evita un utils/ genérico: exige nombres de carpeta específicos como shared/date/ o shared/format/.
Una regla útil para cuándo crear un nuevo módulo vs añadir a uno existente: crea una carpeta nueva solo cuando aparece un nuevo concepto en la app. Una app de facturación podría añadir domain/invoices/ y ui/invoices/ cuando las facturas se conviertan en una feature real, no solo una pantalla aislada.
Si heredas salida desordenada de IA, estas restricciones aceleran la remediación. Mucho del trabajo es mover código a límites claros antes de poder reparar con seguridad lógica, auth o problemas de seguridad.
Reglas de nombres que evitan confusión después
El nombre es donde el código generado por IA suele desviarse. Si tu prompt es estricto aquí, pasarás menos tiempo cazando imports, adivinando qué hace una función o desenredando modelos “casi iguales”.
Elige un estilo por cosa y no mezcles. Un mapeo simple que puedes pegar en prompts es:
- Archivos y carpetas: kebab-case (ej.,
user-profile.ts) - Componentes React / clases: PascalCase (ej.,
UserProfile) - Funciones y variables: camelCase (ej.,
fetchUserProfile) - Constantes: SCREAMING_SNAKE_CASE (ej.,
MAX_RETRIES) - Rutas API: kebab-case (ej.,
/user-profile)
Los nombres de archivo deben coincidir con lo que exportan. Si un archivo exporta UserService, llámalo user-service.ts. No exportes cinco cosas no relacionadas desde un mismo archivo. Una exportación principal por archivo mantiene los imports previsibles y facilita refactors.
Para funciones, usa nombres que empiecen por verbo y digan qué pasa: getUserById, validateSignupForm, saveInvoice, sendPasswordResetEmail. Evita nombres vagos como process, handleThing o doWork. Si es async, sé consistente: añade un sufijo Async en todas partes o confía en el contexto, pero no mezcles estilos.
Los modelos de datos deben usar sustantivos en singular (User, Invoice). Los campos de BD deben seguir una convención (snake_case es común en SQL; camelCase es común en el código de la app). Elige una y mantente. Alinea nombres relacionados para que createdAt mapee limpiamente a created_at, no a create_date en un sitio y created en otro.
Una pequeña lista de “no usar” ahorra tiempo: temp, misc, helper2, final_v3, newNew. Si heredaste una base con nombres así, renombrar y reorganizar suele pagar al instante porque los nombres poco claros ocultan bugs.
Restricciones de configuración: entornos, secretos y defaults
Sé estricto sobre lo que es configuración y lo que es código. Configuración es todo lo que cambia entre dev, staging y prod: URL de la BD, claves API, orígenes permitidos, settings de cookies, feature flags. Código es la lógica que permanece: rutas, validación, reglas de negocio.
Una buena restricción es separar configuración en tiempo de ejecución de la de tiempo de compilación. La config de runtime debe venir de variables de entorno, porque puede cambiar sin recompilar. La config de build puede vivir en archivos comiteados, como un módulo tipado con defaults seguros o config/*.json para valores no secretos.
Los secretos necesitan reglas explícitas porque las apps generadas por IA a menudo los filtran por accidente:
- Nunca hardcodear secretos en código o archivos de configuración
- Nunca loggear secretos (incluyendo logs de debug)
- Nunca commitear secretos (solo un archivo de ejemplo)
- Fallar rápido si falta un secreto requerido
- Usar nombres claros como
DATABASE_URLyJWT_SECRET
Los defaults también importan. Pide valores seguros y aburridos para que la app se comporte de forma predecible incluso antes de tunearla. Por ejemplo: CORS restringido (permitir solo una lista conocida), cookies de auth con HttpOnly y Secure en producción, y sesiones con un timeout de inactividad corto y una duración máxima clara.
También exige un lugar donde se documente la configuración. El patrón más simple es un .env.example con comentarios, más una sección breve “Configuration” en el README que liste cada variable, su propósito y un ejemplo de valor. Esa restricción ahorra horas, sobre todo cuando un prototipo funcionó en una máquina pero se rompe en despliegue.
Restricciones de calidad: errores, validación y tests pequeños
La mayoría de apps generadas por IA fallan en producción por razones mundanas: errores poco claros, validación ausente y sin tests alrededor de las partes riesgosas. Unas pocas restricciones de calidad hacen la salida más fácil de depurar ahora y más fácil de arreglar después.
Empieza forzando un manejo de errores consistente. Pide un patrón único, no una mezcla de strings lanzados, respuestas ad hoc y fallos silenciosos. Exige errores explícitos, con la misma forma y seguros para mostrar a usuarios.
Luego exige validación en los límites, donde entra mala data: rutas API, formularios, webhooks, jobs en background. Sin validación obtendrás bugs raros como “funciona en mi máquina” o “falla solo para algunos usuarios”.
Restricciones que puedes copiar:
- Usa un único formato de error (por ejemplo:
{ code, message, details? }) y nunca lances strings planos. - Valida todas las entradas externas en el límite, devuelve errores de validación claros y no confíes en datos del cliente.
- Mantén funciones pequeñas (aprox. 20–40 líneas) y con valores de retorno previsibles (sin tipos mezclados).
- Loggea fallos inesperados con suficiente contexto para reproducir (request id, user id si está disponible, acción).
Los tests no necesitan ser grandes para ayudar. Pide un conjunto mínimo que cubra el riesgo. Si tienes login, un flujo de pago o una acción create/update, esos son los primeros en cubrir. Un mínimo ligero podría incluir rechazo de auth con credenciales inválidas, un camino de éxito del flujo principal más una falla común, y una prueba de validación que demuestre que la entrada mala devuelve un error claro.
Finalmente, exige una breve sección “cómo ejecutar localmente” en la salida, incluyendo las vars de entorno necesarias y defaults seguros. Esto evita muchos proyectos que “no arrancan”.
Ejemplo de prompt: construir una pequeña app que se mantenga
Imagina que quieres una app pequeña con login, una página de perfil y un formulario de settings. Sin restricciones, una IA suele dispersar la lógica de auth por páginas, mezclar llamadas a la BD en código UI e inventar nombres de archivos según le venga. Con reglas claras, obtienes límites limpios y un plan de archivos que puedes depurar después.
Aquí tienes un prompt de ejemplo que puedes copiar y ajustar:
Build a small app with:
- Login page
- Profile page (shows name + email)
- Settings page (update display name, toggle a feature flag)
Hard constraints (do not violate):
1) Folder structure:
- /src/routes = route definitions only
- /src/handlers = request/response logic only (no database queries)
- /src/services = business rules (auth, profile, settings)
- /src/data = database access only (queries, repositories)
- /src/config = configuration loader and typed config
2) Naming:
- Files: kebab-case (profile-handler.ts)
- Exports: camelCase functions, PascalCase types
- One main export per file
3) Code boundaries:
- Routes call handlers
- Handlers call services
- Services call data layer
- Data layer is the only place allowed to import the DB client
4) Config constraints:
- Read DATABASE_URL and AUTH_SECRET from environment variables
- Never hardcode secrets or sample keys
- Add FEATURE_SETTINGS_ENABLED default=false when missing
- Provide a single config object from /src/config
Deliverables:
- Start with a file tree
- Then output code file-by-file
- Finish with a summary table: file created/changed + 1 sentence why
Si quieres una salida aún más estricta, añade: “If you need to add a new file, explain why it belongs in that folder.” Empuja al modelo a respetar los límites en lugar de volcar todo en un mismo sitio.
Errores comunes al añadir restricciones
Las restricciones están pensadas para hacer la salida más fácil de leer, cambiar y arreglar. Los problemas más habituales ocurren cuando las reglas son demasiado vagas para guiar al modelo o tan estrictas que chocan con el framework que usas.
Error 1: Sobre-restringir el proyecto
Es fácil escribir reglas que suenan limpias pero fuerzan elecciones antinaturales. Por ejemplo, exigir una estructura personalizada que va contra las convenciones de Next.js, o prohibir el archivo de configuración estándar de un framework porque parece desordenado. El modelo entonces gasta esfuerzo esquivando tus reglas en lugar de construir código correcto.
Un enfoque más seguro: mantén los defaults del framework salvo que tengas una razón real para cambiarlos. Añade restricciones solo donde veas confusión recurrente (como dónde viven las rutas API o los tipos compartidos).
Error 2: Sub-restringir con palabras vagas
“Código limpio”, “mejores prácticas” y “enterprise-ready” no le dicen al modelo qué hacer. Cámbialos por comprobaciones que pueda seguir.
Ejemplos de restricciones que realmente funcionan:
- “Output a file tree first, then code files in that order.”
- “Use one naming style: camelCase for variables, PascalCase for components.”
- “Put env vars in
.env.exampleand read them only via a config module.” - “No new libraries unless you ask first and explain why.”
- “If you move files, include migration steps.”
Otro problema común es dejar que el modelo invente librerías o archivos de configuración que no pediste. Pides auth y añade tres paquetes, dos configs y una nueva herramienta de build.
No olvides pasos de migración al cambiar la estructura. Un pequeño rename puede romper imports, tests y despliegue. Pide un breve “qué cambió” y los comandos necesarios para actualizar rutas. Y siempre exige un árbol de archivos; sin él, la salida se vuelve dispersa y difícil de ensamblar.
Lista rápida y siguientes pasos
Antes de aceptar código generado por IA (o mergearlo), haz una pasada de 5 minutos. Estas comprobaciones detectan la mayoría de problemas de “funciona ahora, caro después”:
- El árbol de archivos coincide con tus reglas (capas, carpetas, código compartido) y no hay directorios aleatorios.
- Los nombres son consistentes: el mismo concepto no se llama de tres formas distintas en archivos, rutas y variables.
- No hay secretos en el código: no claves API, tokens, URLs privadas ni credenciales reales en archivos, comentarios o configs de ejemplo.
- La configuración es clara: hay un lugar documentado para vars de entorno, los defaults son seguros y el comportamiento no cambia silenciosamente entre dev y prod.
- Se puede ejecutar con pasos de copiar-pegar: alguien nuevo puede instalar, configurar y ejecutar sin adivinar.
Si no puedes responder sí a la mayoría, para. Una pequeña limpieza ahora cuesta menos que depurar dentro de un mes, especialmente cuando los problemas están escondidos en confusión de nombres, config dispersa o una estructura que fomenta el espagueti.
Si ya tienes una base desordenada generada por IA, hazla comprensible antes de añadir features. Un orden práctico: congela el scope 24 horas, mapea la estructura actual (carpetas, puntos de entrada, dónde vive la config y los secretos), elige un estándar de nombres y aplícalo primero al camino crítico, centraliza la configuración con un archivo de ejemplo seguro y pasos claros de arranque, y añade algunas comprobaciones pequeñas (validación, manejo básico de errores, uno o dos tests smoke) para prevenir regresiones.
Si estás atascado con un prototipo de herramientas como Lovable, Bolt, v0, Cursor o Replit que no se comporta en producción, FixMyMess (fixmymess.ai) puede ejecutar una auditoría gratuita de código para señalar problemas de estructura, nombres, configuración y seguridad antes de cualquier arreglo. Así obtienes un plan claro, no otra ronda de conjeturas.
Preguntas Frecuentes
Why does AI-generated code get messy so fast?
AI suele optimizar por “funciona ahora”, así que puede tomar atajos que parecen bien hasta que necesitas cambiar algo. Sin reglas claras sobre estructura, nomenclatura y configuración, cada nuevo prompt puede producir un patrón distinto, lo que hace que el código sea frágil ante modificaciones.
What are the easiest signs that my project is becoming hard to maintain?
Fíjate en nombres inconsistentes para el mismo concepto, archivos que aparecen en carpetas aleatorias y valores de configuración codificados en varios lugares. Otro signo común es que un pequeño cambio provoca roturas no relacionadas, lo que suele indicar que las responsabilidades están mezcladas.
When should I add constraints vs letting the model improvise?
Añade restricciones siempre que el proyecto pueda enviarse, vaya a tener más de una iteración o vaya a ser entregado a otra persona. Si es realmente una demo desechable o un script puntual, puedes ser más laxo y aceptar cierto desorden.
Why are folder structure, naming, and configuration the “big three” constraints?
La estructura de carpetas determina dónde irá el código futuro, la nomenclatura determina cómo encontrarás y reutilizarás las cosas, y la configuración determina si la app sobrevive al despliegue. Esas tres afectan a todos los archivos y son costosas de arreglar más tarde.
What’s the fastest way to keep AI output organized from the start?
Pide primero un árbol de archivos breve antes de cualquier código y límitalo a algo legible, como 15 líneas. Luego exige que el código se genere archivo por archivo con los nombres de fichero, así puedes ver rápidamente si algo cayó en el lugar equivocado antes de que el modelo genere docenas de archivos.
What naming rules prevent duplicate or confusing files?
Elige una convención por categoría y úsala siempre: archivos en kebab-case, componentes en PascalCase, funciones en camelCase, y nombres de rutas consistentes. También exige que los nombres de archivo coincidan con su exportación principal y evita cajones de ‘utils’ vagos usando nombres específicos.
What configuration rules stop the usual deployment breakages?
Exige un único cargador/módulo de configuración, lee secretos solo desde variables de entorno e incluye un .env.example con solo marcadores de posición. También pide chequeos que fallen rápido si falta un valor requerido: los fallos silenciosos suelen ser la razón por la que los prototipos se rompen en producción.
How do I avoid over-constraining a project with too many rules?
Ocurre cuando tus reglas luchan contra las convenciones del framework, forzando soluciones forzadas. Una buena práctica: sigue la convención del framework cuando haya conflicto y añade restricciones solo donde veas confusión repetida (por ejemplo, límites entre UI, servicios y acceso a datos).
What quality constraints help without slowing everything down?
Pide un formato de error coherente en toda la app, validación en los límites (rutas/formularios/webhooks) y un conjunto mínimo de tests alrededor de los flujos de riesgo como auth o create/update. Estas restricciones añaden poco código, pero hacen los fallos mucho más fáciles de depurar y previenen regresiones.
I inherited a messy AI-generated codebase—what should I do first?
Empieza por mapear el árbol de archivos actual e identificar dónde está la configuración y los secretos. Luego elige un estándar de nombres y aplícalo primero al camino crítico. Si estás atascado con una app generada por herramientas como Lovable, Bolt, v0, Cursor o Replit, FixMyMess (fixmymess.ai) puede realizar una auditoría gratuita de código y ofrecer un plan de remediación claro, a menudo con arreglos en 48–72 horas.