AI-ready
Cómo este boilerplate está optimizado para que un agente de IA escriba código que funcione.
Última actualización 3 may 2026
Filosofía
Los LLMs no leen tu mente — leen tu código. Un boilerplate AI-friendly minimiza la ambigüedad: tipos exactos, patrones repetidos, ADRs explícitos.
Tipos como contrato
@app/contracts exporta schemas Zod y tipos inferidos. Un agente que mira el contract sabe exactamente qué payload mandar y qué esperar de vuelta. Sin documentación que se desactualiza.
import { CreateUserInput } from '@app/contracts';
// El tipo es la doc.Branded IDs
UserId ≠ OrganizationId ≠ string. Si un agente confunde uno con otro, el TS server lo detecta antes del commit. Menos bugs sutiles.
Result en lugar de throws
Los LLMs propagan errores mejor cuando son valores. Result<T, E> se mapea naturalmente a JSON, a tests, a docs.
ADRs versionados
docs/adr/ documenta decisiones arquitectónicas (por qué BetterAuth, por qué billing agnóstico al proveedor). Un agente lee la ADR antes de proponer un cambio que la contradiga.
Generadores
bun run gen:domain <name> genera el scaffold de un agregado completo (entity, VOs, repo, use cases, controller, tests). El agente sigue el patrón existente sin inventar uno nuevo.
MCP-friendly
Schemas de Prisma + OpenAPI generado en apps/server/openapi.json. Cualquier agente con tools de OpenAPI explora el API sin adivinar.
Patrones repetidos
Cada agregado tiene la misma estructura (domain/, application/, infrastructure/, interface/). Un LLM aprende el patrón en un dominio y lo replica en el siguiente sin fricción.
Guardrails del endpoint de chat
POST /api/v1/ai/chat cuesta plata real, así que está blindado:
- El cliente solo puede enviar mensajes
useryassistant. El rolsystemlo rechaza el schema de@app/contracts. modeldebe serAI_MODELo estar enAI_ALLOWED_MODELS; cualquier otro da 422 antes de llamar al upstream.- La salida está limitada por
AI_MAX_OUTPUT_TOKENS. - Si el cliente se desconecta, el stream upstream se aborta para que una pestaña cerrada deje de gastar tokens.
[!NOTE] En Bun 1.3.x un POST cuyo body ya fue consumido no emite evento de desconexión, así que el abort por desconexión puede no dispararse. Dos límites duros lo cubren:
AI_MAX_OUTPUT_TOKENSyAI_STREAM_TIMEOUT_MS(default 120000), un tope de tiempo que aborta la llamada upstream. El stream también se aborta si una escritura a la respuesta falla o la respuesta se destruye.