AI-ready
Como este boilerplate está otimizado para que um agente de IA escreva código que funcione.
Última atualização 3 de mai. de 2026
Filosofia
LLMs não leem sua mente — leem seu código. Um boilerplate AI-friendly minimiza ambiguidade: tipos exatos, padrões repetidos, ADRs explícitos.
Tipos como contrato
@app/contracts exporta schemas Zod e tipos inferidos. Um agente que olha o contract sabe exatamente qual payload enviar e o que esperar de volta. Sem documentação que desatualiza.
import { CreateUserInput } from '@app/contracts';
// O tipo é a doc.Branded IDs
UserId ≠ OrganizationId ≠ string. Se um agente confunde um com o outro, o TS server pega antes do commit. Menos bugs sutis.
Result no lugar de throws
LLMs propagam erros melhor quando são valores. Result<T, E> mapeia naturalmente para JSON, para testes, para docs.
ADRs versionados
docs/adr/ documenta decisões arquiteturais (por que BetterAuth, por que billing agnóstico ao provider). Um agente lê o ADR antes de propor uma mudança que o contradiga.
Generators
bun run gen:domain <name> gera o scaffold de um aggregate completo (entity, VOs, repo, use cases, controller, testes). O agente segue o padrão existente sem inventar um novo.
MCP-friendly
Schemas Prisma + OpenAPI gerado em apps/server/openapi.json. Qualquer agente com tools OpenAPI explora a API sem adivinhar.
Padrões repetidos
Cada aggregate tem a mesma estrutura (domain/, application/, infrastructure/, interface/). Um LLM aprende o padrão em um domínio e replica no próximo sem fricção.
Guardrails do endpoint de chat
POST /api/v1/ai/chat custa dinheiro de verdade, então é blindado:
- O cliente só pode enviar mensagens
usereassistant. O papelsystemé rejeitado pelo schema de@app/contracts. modeldeve serAI_MODELou estar emAI_ALLOWED_MODELS; qualquer outro dá 422 antes de chamar o upstream.- A saída é limitada por
AI_MAX_OUTPUT_TOKENS. - Se o cliente desconecta, o stream upstream é abortado para que uma aba fechada pare de gastar tokens.
[!NOTE] No Bun 1.3.x um POST cujo body já foi consumido não emite evento de desconexão, então o abort por desconexão pode não disparar. Dois limites rígidos cobrem isso:
AI_MAX_OUTPUT_TOKENSeAI_STREAM_TIMEOUT_MS(padrão 120000), um teto de tempo que aborta a chamada upstream. O stream também é abortado se uma escrita na resposta falha ou a resposta é destruída.