llms.txt · um spec por stack

Padrões de arquitetura
que viram boilerplate.

Um llms.txt por stack. Aponte o LLM para o arquivo da stack em que vai trabalhar — ou para o índice num projeto full-stack novo — e ele scaffolda, codifica e deploya exatamente no padrão.

⤓ índice llms.txt
andrebassi — llms-patterns — zsh
01

Arquitetura & Stacks

Regras que valem em qualquer projeto, salvo override explícito.

Hexagonal no Go: adapters → ports → domain, nunca o inverso.
Zero ORM. pgx/v5 + interface DBTX.
Router HTTP sempre chi v5. Nunca gin, echo, gorilla.
HTTP client é stdlib net/http. Sem libs externas.
Logging com log/slog, JSON estruturado.
Taskfile-first: todo comando vira scripts/*.sh + task. Nada ad-hoc.
Testes bloqueiam deploy: build e deploy dependem de test. Cobertura ≥ 90%.
Frontend só com pnpm. Nunca npm/yarn.
Credenciais só via pass. Tolerância zero a plaintext.
Projeto novo segue AIOX SDD: PRD → Arquitetura → Stories antes de código.
Docs fazem parte do "Done": PRD, stories e CLAUDE.md sincronizados.
timeout 30s em todo comando + log com tee /tmp/log.txt.
02

Go Backend — Hexagonal

Ports & Adapters. Domínio puro, mundo externo só atrás de interface, wiring em cmd/.

adapters/ ports/ domain/ ·nunca inverso
# layout canônico
backend/
├── cmd/server/main.go        # entrypoint chi — todo o DI aqui
│   ├── worker/main.go          # Temporal worker
│   └── migrate/main.go
├── domain/
│   ├── entity/                 # entidades puras — ZERO deps externas
│   └── service/                # lógica de negócio
├── ports/
│   ├── inbound/                # SessionManager, WebhookValidator...
│   └── outbound/               # XxxRepository, Transcriber, DBTX...
├── adapters/
│   ├── driven/                 # 1 pasta por serviço externo
│   │   ├── postgres/ temporal/ stripe/ groq/ openrouter/ email/ ...
│   └── driving/http/           # rotas chi + handlers + middleware
├── internal/config/          # env vars validadas no boot (fail fast)
│   └── observability/          # Sentry + slog middleware
└── go.mod                      # go 1.26

📦Libs padrão

  • go-chi/chi/v5
  • jackc/pgx/v5
  • pashagolub/pgxmock/v4
  • stretchr/testify
  • go.temporal.io/sdk
  • log/slog · net/http

🧪Testes

  • Domain: 100%, table-driven, testdata/
  • Adapters: >90% — pgxmock, httptest, testsuite
  • go test ./... -cover -race
  • Gate <90% bloqueia CI
  • Zero flaky tolerado

🏷️Naming

  • Adapter = nome do serviço (stripe/, groq/)
  • Repos: XxxRepository
  • Capacidades: Transcriber, Messenger
  • DI só em cmd/*/main.go
  • Guard de env perigosa no config
03

Frontend — Next.js 16

App Router, React 19, Tailwind 4, pnpm, vitest. Middleware agora é proxy.ts.

frontend/src/
├── app/
│   ├── (auth)/                 # login, register, update-password
│   ├── (dashboard)/            # protegido — layout force-dynamic
│   ├── api/                    # route handlers (callback, webhook)
│   ├── providers.tsx · globals.css · layout.tsx
│   └── proxy.ts                # middleware (rename do Next 16)
├── components/<feature>/ + ui/  # Radix + custom
├── hooks/ useAuth.ts ...
├── lib/
│   ├── api.ts                  # apiFetch() — NUNCA fetch() cru
│   └── supabase/ client·server·middleware
└── types/ · test/

Convenções críticas

  • apiFetch(): JWT + 401/403 → signOut + redirect
  • Rotas internas versionadas /v1
  • Página por-usuário: force-dynamic
  • OAuth callback: criar response ANTES do client Supabase
  • Logout: router.refresh() antes de push()
  • SSE: token via ?token= (sem headers)

🛠️Build & testes

  • NEXT_PUBLIC_* = build-time → build args no fly.toml
  • Atrás de proxy: tratar x-forwarded-host
  • pnpm vitest run · por path · -t "nome"
  • eslint 9 + eslint-config-next
  • Tailwind 4 via @tailwindcss/postcss
04

DevOps

Toda automação roda via Task (go-task) — cada projeto tem um Taskfile.yaml v3 e nada executa fora dele: nunca comando ad-hoc no shell. A lógica vive em scripts/*.sh (bash, set -euo pipefail), a task só embrulha o script e loga com tee. Task names são a API pública do projeto (task -l = documentação); scripts/ é a trilha de auditoria.

# vocabulário Taskfile — task names são contrato
dev  dev:api  dev:worker  web:dev
test  test:backend  test:frontend  test:coverage   # dependência de build/deploy
lint  build                                        # CGO_ENABLED=0, deps:[test]
supabase:start  supabase:reset  migrate  migrate:local
deploy  deploy:backend  deploy:frontend  deploy:worker
logs:fly  status:fly  health
plan  apply  dev:apply  prd:apply                  # repos IaC — prd sempre com prompt:
vpn:up  vpn:down  vpn:status                       # acesso a recursos privados
# anatomia Taskfile v3 — gates, args, idempotência
build:
  deps: [test]                                # teste falhou = não builda
  cmds: [./scripts/build.sh 2>&1 | tee /tmp/build.log]
apply:
  desc: 'Uso: task apply -- env/dev/vpc'
  cmds: [terragrunt apply --working-dir {{.CLI_ARGS}}]
prd:apply:
  prompt: "PRODUCAO: confirma apply em prd?"     # destrutivo/prod = prompt obrigatório
supabase:start:
  status: [supabase status > /dev/null 2>&1]    # skip se já rodando
# Docker multi-stage → chainguard (0 CVEs)
FROM golang:1.26-alpine AS builder
RUN CGO_ENABLED=0 go build -ldflags "-X main.Version=${VERSION}" -o server ./cmd/server

FROM chainguard/static:latest
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]
# IaC — Terragrunt Stacks (OpenTofu) — wrapper YAML é O padrão:
# cada componente é configurado por manifest YAML estilo CRD; HCL fica genérico
infra/
├── root.hcl                    # locals: project, modules_base + remote_state
├── _units/<comp>/terragrunt.hcl  # templates parametrizados (vpc, rds, alb, ecs...)
├── env/{dev,qas,prd}/          # env.hcl: environment, region, account_id, module_ref
└── manifests/{env}/<comp>.yaml # wrapper YAML: apiVersion/kind/metadata/spec → yamldecode

# unit: backend + provider GERADOS, módulo por git tag
generate "backend"  { contents = s3 key "{env}/{comp}/terraform.tfstate" + dynamodb lock }
generate "provider" { contents = default_tags Project/Environment/ManagedBy }
terraform { source = "${modules_base}/<module>?ref=${local.ref}" }  # repo separado, semver
inputs    = merge(yamldecode(file("manifests/${env}/<comp>.yaml")).spec, {...})
# Ansible — playbook em fases, inventário YAML, orquestração do CP[0]
- name: "Fase 1 — Preparar OS"      # role prepare: sysctl 30+, modprobe, UFW, swap off
  hosts: microk8s
  become: yes
  roles: [prepare]
- name: "Fase 3 — Join nodes"
  hosts: control_plane[0]            # orquestra do primeiro CP
  tasks:
    - command: microk8s kubectl cluster-info
      register: api  until: api.rc == 0  retries: 18  delay: 10
    - include_tasks: tasks/join-node.yaml
      loop: "{{ groups['control_plane'][1:] + groups['workers'] }}"

🚀Fly.io

  • Região iad (Supabase) ou gru (BR)
  • Backend: strategy=immediate, 1 máquina
  • Worker Temporal: immediate (rolling panica)
  • Migrations no release_command
  • PG: fly proxy 15432:5432 + psql
  • NEXT_PUBLIC_* via [build.args]

🗄️Supabase / PG

  • pgx/v5, backend como service_role (bypassa RLS)
  • RLS em tabelas tenant-scoped
  • migrations/<ts>_<desc>.sql idempotentes
  • DATABASE_URL direto 5432 (não pooler)
  • sslmode=require sempre
  • pg_dump dentro do container do supabase

🔐Credenciais & K8s

  • pass show client/env/key → env var
  • Nunca echo; unset depois
  • kubectl: verificar contexto ANTES
  • Nunca flag -w watch
  • GitOps: ArgoCD + GitLab CI
  • Finalizers: delete + patch finalizers:[]

🏗️Terraform / Terragrunt

  • Wrapper YAML é o padrão: muda infra editando manifest, não HCL
  • Nunca terraform apply na mão — só via task
  • Módulos em repo separado, ref por git tag
  • 1 state por componente por env (S3 + DynamoDB)
  • Promoção: bump module_ref dev → qas → prd
  • Lint: tflint + checkov antes do apply

📋Ansible

  • Inventário YAML, nunca INI — groups + children
  • Módulo declarativo > shell (apt, sysctl, systemd)
  • Shell só com creates:/changed_when
  • Tags em todo bloco funcional
  • Secrets via pass no deploy, zero hardcode
  • Health: register + until + retries, nunca sleep

☁️Cloudflare

  • DNS proxied (orange) quando há Access
  • SSL Full, não Flexible (origin com cert LE)
  • Zero Trust Access: OTP email, criado via API
  • Workers: wrangler deploy --containers-rollout=immediate
  • WARP/tunnel pra RDS em subnet privada
  • Debug: wrangler tail --format=pretty
05

AIOX Spec-Driven Development

Specs antes de código. Paths exatos — nunca PRD.md, nunca docs/specs/.

@pm → prd.md @architect → architecture.md @sm → stories/ @dev → código @qa → gate @devops → deploy
docs/
├── prd.md                       # Goals · FR/NFR · Assumptions · Epics
├── architecture.md              # Tech Stack table · Data Models · DDL · Workflows
├── stories/
│   ├── {epic}.{story}.{slug}.md # Status · Executor · AC · Tasks · Dev Notes
│   └── DEPENDENCY-GRAPH.md
└── runbooks/<topic>.md

📋Story — seções na ordem exata

Status → Executor Assignment → Story ("As a…") → Acceptance Criteria → Tasks/Subtasks → Dev Notes (contexto completo; dev nunca relê architecture.md) → Change Log → Dev Agent Record → QA Results.

⚖️Regras de execução

  • executor ≠ quality_gate — sempre
  • Story atômica: começa e termina antes da próxima
  • Ordem do grafo de dependências, nunca pular
  • Status e Tasks atualizados em tempo real
  • Paralelismo só sem dependência mútua
06

Stack Padrão

Escolhas default. Desviar exige justificativa na arquitetura.

CamadaEscolhaÁrea
BackendGo 1.26 · chi v5 · pgx/v5 · sloggo
WorkflowsTemporalgo
DBPostgreSQL 15+ (Supabase ou self-managed)ops
AuthSupabase JWTgofe
FrontendNext.js 16 · React 19 · Tailwind 4 · pnpmfe
FE testesvitest + testing-library + jsdomfe
STT / LLMGroq Whisper V3 · Claude (OpenRouter/Anthropic)go
Billing / EmailStripe (API nativa, sem SDK) · Resendgo
ObservabilidadeSentry + slog JSONops
DeployFly.io (iad/gru) · CF Pages · K8sops
Imagenschainguard/static (0 CVEs)ops
AutomaçãoTaskfile + scripts/ops
IaC / GitOpsTerraform/Terragrunt · Helm · ArgoCD · GitLab CIops
07

Bootstrap de Projeto Novo

Checklist na ordem. Specs primeiro, código depois.

1️⃣Specs & estrutura

  • docs/prd.md + architecture.md + stories/
  • Taskfile.yaml + scripts/ no dia zero
  • Backend: cmd/ domain/ ports/ adapters/ internal/config
  • Frontend: (auth)/(dashboard), lib/api.ts, providers

2️⃣Infra & gates

  • supabase/migrations/ + RLS
  • Dockerfile chainguard + fly.toml por app
  • CLAUDE.md na raiz: comandos + gotchas de produção
  • Testes como deps de build/deploy; gates de cobertura ligados
08

Specs Completas

Conteúdo integral de cada llms.txt, embutido na página. Copie direto ou abra o arquivo.

https://llms.andrebassi.com.br/llms.txt ↗ llms.txt

  
conteúdo copiado ✓