docs(pt-BR): add examples translation

This commit is contained in:
Paulo Victor Gomes
2026-03-21 14:06:49 +01:00
parent 1ef8bc1e72
commit be6d7f314a
6 changed files with 1235 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# Exemplo de CLAUDE.md de Projeto
Este é um exemplo de arquivo CLAUDE.md no nível de projeto. Coloque-o na raiz do seu projeto.
## Visão Geral do Projeto
[Descrição breve do seu projeto - o que ele faz, stack tecnológica]
## Regras Críticas
### 1. Organização de Código
- Muitos arquivos pequenos em vez de poucos arquivos grandes
- Alta coesão, baixo acoplamento
- 200-400 linhas típico, 800 máximo por arquivo
- Organize por feature/domínio, não por tipo
### 2. Estilo de Código
- Sem emojis em código, comentários ou documentação
- Imutabilidade sempre - nunca mutar objetos ou arrays
- Sem console.log em código de produção
- Tratamento de erro adequado com try/catch
- Validação de entrada com Zod ou similar
### 3. Testes
- TDD: escreva testes primeiro
- Cobertura mínima de 80%
- Testes unitários para utilitários
- Testes de integração para APIs
- Testes E2E para fluxos críticos
### 4. Segurança
- Sem segredos hardcoded
- Variáveis de ambiente para dados sensíveis
- Validar toda entrada de usuário
- Apenas queries parametrizadas
- Proteção CSRF habilitada
## Estrutura de Arquivos
```
src/
|-- app/ # Next.js app router
|-- components/ # Reusable UI components
|-- hooks/ # Custom React hooks
|-- lib/ # Utility libraries
|-- types/ # TypeScript definitions
```
## Padrões-Chave
### Formato de Resposta de API
```typescript
interface ApiResponse<T> {
success: boolean
data?: T
error?: string
}
```
### Tratamento de Erro
```typescript
try {
const result = await operation()
return { success: true, data: result }
} catch (error) {
console.error('Operation failed:', error)
return { success: false, error: 'User-friendly message' }
}
```
## Variáveis de Ambiente
```bash
# Required
DATABASE_URL=
API_KEY=
# Optional
DEBUG=false
```
## Comandos Disponíveis
- `/tdd` - Fluxo de desenvolvimento orientado a testes
- `/plan` - Criar plano de implementação
- `/code-review` - Revisar qualidade de código
- `/build-fix` - Corrigir erros de build
## Fluxo Git
- Conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`
- Nunca commitar direto na main
- PRs exigem revisão
- Todos os testes devem passar antes do merge

View File

@@ -0,0 +1,308 @@
# Django REST API — CLAUDE.md de Projeto
> Exemplo real para uma API Django REST Framework com PostgreSQL e Celery.
> Copie para a raiz do seu projeto e customize para seu serviço.
## Visão Geral do Projeto
**Stack:** Python 3.12+, Django 5.x, Django REST Framework, PostgreSQL, Celery + Redis, pytest, Docker Compose
**Arquitetura:** Design orientado a domínio com apps por domínio de negócio. DRF para camada de API, Celery para tarefas assíncronas, pytest para testes. Todos os endpoints retornam JSON — sem renderização de templates.
## Regras Críticas
### Convenções Python
- Type hints em todas as assinaturas de função — use `from __future__ import annotations`
- Sem `print()` statements — use `logging.getLogger(__name__)`
- f-strings para formatação, nunca `%` ou `.format()`
- Use `pathlib.Path` e não `os.path` para operações de arquivo
- Imports ordenados com isort: stdlib, third-party, local (enforced by ruff)
### Banco de Dados
- Todas as queries usam Django ORM — SQL bruto só com `.raw()` e queries parametrizadas
- Migrations versionadas no git — nunca use `--fake` em produção
- Use `select_related()` e `prefetch_related()` para prevenir queries N+1
- Todos os models devem ter auto-fields `created_at` e `updated_at`
- Índices em qualquer campo usado em `filter()`, `order_by()` ou cláusulas `WHERE`
```python
# BAD: N+1 query
orders = Order.objects.all()
for order in orders:
print(order.customer.name) # hits DB for each order
# GOOD: Single query with join
orders = Order.objects.select_related("customer").all()
```
### Autenticação
- JWT via `djangorestframework-simplejwt` — access token (15 min) + refresh token (7 days)
- Permission classes em toda view — nunca confiar no padrão
- Use `IsAuthenticated` como base e adicione permissões customizadas para acesso por objeto
- Token blacklisting habilitado para logout
### Serializers
- Use `ModelSerializer` para CRUD simples, `Serializer` para validação complexa
- Separe serializers de leitura e escrita quando input/output diferirem
- Valide no nível de serializer, não na view — views devem ser enxutas
```python
class CreateOrderSerializer(serializers.Serializer):
product_id = serializers.UUIDField()
quantity = serializers.IntegerField(min_value=1, max_value=100)
def validate_product_id(self, value):
if not Product.objects.filter(id=value, active=True).exists():
raise serializers.ValidationError("Product not found or inactive")
return value
class OrderDetailSerializer(serializers.ModelSerializer):
customer = CustomerSerializer(read_only=True)
product = ProductSerializer(read_only=True)
class Meta:
model = Order
fields = ["id", "customer", "product", "quantity", "total", "status", "created_at"]
```
### Tratamento de Erro
- Use DRF exception handler para respostas de erro consistentes
- Exceções customizadas de regra de negócio em `core/exceptions.py`
- Nunca exponha detalhes internos de erro para clientes
```python
# core/exceptions.py
from rest_framework.exceptions import APIException
class InsufficientStockError(APIException):
status_code = 409
default_detail = "Insufficient stock for this order"
default_code = "insufficient_stock"
```
### Estilo de Código
- Sem emojis em código ou comentários
- Tamanho máximo de linha: 120 caracteres (enforced by ruff)
- Classes: PascalCase, funções/variáveis: snake_case, constantes: UPPER_SNAKE_CASE
- Views enxutas — lógica de negócio em funções de serviço ou métodos do model
## Estrutura de Arquivos
```
config/
settings/
base.py # Shared settings
local.py # Dev overrides (DEBUG=True)
production.py # Production settings
urls.py # Root URL config
celery.py # Celery app configuration
apps/
accounts/ # User auth, registration, profile
models.py
serializers.py
views.py
services.py # Business logic
tests/
test_views.py
test_services.py
factories.py # Factory Boy factories
orders/ # Order management
models.py
serializers.py
views.py
services.py
tasks.py # Celery tasks
tests/
products/ # Product catalog
models.py
serializers.py
views.py
tests/
core/
exceptions.py # Custom API exceptions
permissions.py # Shared permission classes
pagination.py # Custom pagination
middleware.py # Request logging, timing
tests/
```
## Padrões-Chave
### Camada de Serviço
```python
# apps/orders/services.py
from django.db import transaction
def create_order(*, customer, product_id: uuid.UUID, quantity: int) -> Order:
"""Create an order with stock validation and payment hold."""
product = Product.objects.select_for_update().get(id=product_id)
if product.stock < quantity:
raise InsufficientStockError()
with transaction.atomic():
order = Order.objects.create(
customer=customer,
product=product,
quantity=quantity,
total=product.price * quantity,
)
product.stock -= quantity
product.save(update_fields=["stock", "updated_at"])
# Async: send confirmation email
send_order_confirmation.delay(order.id)
return order
```
### Padrão de View
```python
# apps/orders/views.py
class OrderViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
pagination_class = StandardPagination
def get_serializer_class(self):
if self.action == "create":
return CreateOrderSerializer
return OrderDetailSerializer
def get_queryset(self):
return (
Order.objects
.filter(customer=self.request.user)
.select_related("product", "customer")
.order_by("-created_at")
)
def perform_create(self, serializer):
order = create_order(
customer=self.request.user,
product_id=serializer.validated_data["product_id"],
quantity=serializer.validated_data["quantity"],
)
serializer.instance = order
```
### Padrão de Teste (pytest + Factory Boy)
```python
# apps/orders/tests/factories.py
import factory
from apps.accounts.tests.factories import UserFactory
from apps.products.tests.factories import ProductFactory
class OrderFactory(factory.django.DjangoModelFactory):
class Meta:
model = "orders.Order"
customer = factory.SubFactory(UserFactory)
product = factory.SubFactory(ProductFactory, stock=100)
quantity = 1
total = factory.LazyAttribute(lambda o: o.product.price * o.quantity)
# apps/orders/tests/test_views.py
import pytest
from rest_framework.test import APIClient
@pytest.mark.django_db
class TestCreateOrder:
def setup_method(self):
self.client = APIClient()
self.user = UserFactory()
self.client.force_authenticate(self.user)
def test_create_order_success(self):
product = ProductFactory(price=29_99, stock=10)
response = self.client.post("/api/orders/", {
"product_id": str(product.id),
"quantity": 2,
})
assert response.status_code == 201
assert response.data["total"] == 59_98
def test_create_order_insufficient_stock(self):
product = ProductFactory(stock=0)
response = self.client.post("/api/orders/", {
"product_id": str(product.id),
"quantity": 1,
})
assert response.status_code == 409
def test_create_order_unauthenticated(self):
self.client.force_authenticate(None)
response = self.client.post("/api/orders/", {})
assert response.status_code == 401
```
## Variáveis de Ambiente
```bash
# Django
SECRET_KEY=
DEBUG=False
ALLOWED_HOSTS=api.example.com
# Database
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
# Redis (Celery broker + cache)
REDIS_URL=redis://localhost:6379/0
# JWT
JWT_ACCESS_TOKEN_LIFETIME=15 # minutes
JWT_REFRESH_TOKEN_LIFETIME=10080 # minutes (7 days)
# Email
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST=smtp.example.com
```
## Estratégia de Teste
```bash
# Run all tests
pytest --cov=apps --cov-report=term-missing
# Run specific app tests
pytest apps/orders/tests/ -v
# Run with parallel execution
pytest -n auto
# Only failing tests from last run
pytest --lf
```
## Workflow ECC
```bash
# Planning
/plan "Add order refund system with Stripe integration"
# Development with TDD
/tdd # pytest-based TDD workflow
# Review
/python-review # Python-specific code review
/security-scan # Django security audit
/code-review # General quality check
# Verification
/verify # Build, lint, test, security scan
```
## Fluxo Git
- `feat:` novas features, `fix:` correções de bug, `refactor:` mudanças de código
- Branches de feature a partir da `main`, PRs obrigatórios
- CI: ruff (lint + format), mypy (types), pytest (tests), safety (dep check)
- Deploy: imagem Docker, gerenciada via Kubernetes ou Railway

View File

@@ -0,0 +1,267 @@
# Go Microservice — CLAUDE.md de Projeto
> Exemplo real para um microserviço Go com PostgreSQL, gRPC e Docker.
> Copie para a raiz do seu projeto e customize para seu serviço.
## Visão Geral do Projeto
**Stack:** Go 1.22+, PostgreSQL, gRPC + REST (grpc-gateway), Docker, sqlc (SQL type-safe), Wire (injeção de dependência)
**Arquitetura:** Clean architecture com camadas domain, repository, service e handler. gRPC como transporte principal com gateway REST para clientes externos.
## Regras Críticas
### Convenções Go
- Siga Effective Go e o guia Go Code Review Comments
- Use `errors.New` / `fmt.Errorf` com `%w` para wrapping — nunca string matching em erros
- Sem funções `init()` — inicialização explícita em `main()` ou construtores
- Sem estado global mutável — passe dependências via construtores
- Context deve ser o primeiro parâmetro e propagado por todas as camadas
### Banco de Dados
- Todas as queries em `queries/` como SQL puro — sqlc gera código Go type-safe
- Migrations em `migrations/` com golang-migrate — nunca alterar banco diretamente
- Use transações para operações multi-etapa via `pgx.Tx`
- Todas as queries devem usar placeholders parametrizados (`$1`, `$2`) — nunca string formatting
### Tratamento de Erro
- Retorne erros, não use panic — panic só para casos realmente irrecuperáveis
- Faça wrap de erros com contexto: `fmt.Errorf("creating user: %w", err)`
- Defina sentinel errors em `domain/errors.go` para lógica de negócio
- Mapeie erros de domínio para gRPC status codes na camada de handler
```go
// Domain layer — sentinel errors
var (
ErrUserNotFound = errors.New("user not found")
ErrEmailTaken = errors.New("email already registered")
)
// Handler layer — map to gRPC status
func toGRPCError(err error) error {
switch {
case errors.Is(err, domain.ErrUserNotFound):
return status.Error(codes.NotFound, err.Error())
case errors.Is(err, domain.ErrEmailTaken):
return status.Error(codes.AlreadyExists, err.Error())
default:
return status.Error(codes.Internal, "internal error")
}
}
```
### Estilo de Código
- Sem emojis em código ou comentários
- Tipos e funções exportados devem ter doc comments
- Mantenha funções abaixo de 50 linhas — extraia helpers
- Use table-driven tests para toda lógica com múltiplos casos
- Prefira `struct{}` para canais de sinal, não `bool`
## Estrutura de Arquivos
```
cmd/
server/
main.go # Entrypoint, Wire injection, graceful shutdown
internal/
domain/ # Business types and interfaces
user.go # User entity and repository interface
errors.go # Sentinel errors
service/ # Business logic
user_service.go
user_service_test.go
repository/ # Data access (sqlc-generated + custom)
postgres/
user_repo.go
user_repo_test.go # Integration tests with testcontainers
handler/ # gRPC + REST handlers
grpc/
user_handler.go
rest/
user_handler.go
config/ # Configuration loading
config.go
proto/ # Protobuf definitions
user/v1/
user.proto
queries/ # SQL queries for sqlc
user.sql
migrations/ # Database migrations
001_create_users.up.sql
001_create_users.down.sql
```
## Padrões-Chave
### Interface de Repositório
```go
type UserRepository interface {
Create(ctx context.Context, user *User) error
FindByID(ctx context.Context, id uuid.UUID) (*User, error)
FindByEmail(ctx context.Context, email string) (*User, error)
Update(ctx context.Context, user *User) error
Delete(ctx context.Context, id uuid.UUID) error
}
```
### Serviço com Injeção de Dependência
```go
type UserService struct {
repo domain.UserRepository
hasher PasswordHasher
logger *slog.Logger
}
func NewUserService(repo domain.UserRepository, hasher PasswordHasher, logger *slog.Logger) *UserService {
return &UserService{repo: repo, hasher: hasher, logger: logger}
}
func (s *UserService) Create(ctx context.Context, req CreateUserRequest) (*domain.User, error) {
existing, err := s.repo.FindByEmail(ctx, req.Email)
if err != nil && !errors.Is(err, domain.ErrUserNotFound) {
return nil, fmt.Errorf("checking email: %w", err)
}
if existing != nil {
return nil, domain.ErrEmailTaken
}
hashed, err := s.hasher.Hash(req.Password)
if err != nil {
return nil, fmt.Errorf("hashing password: %w", err)
}
user := &domain.User{
ID: uuid.New(),
Name: req.Name,
Email: req.Email,
Password: hashed,
}
if err := s.repo.Create(ctx, user); err != nil {
return nil, fmt.Errorf("creating user: %w", err)
}
return user, nil
}
```
### Table-Driven Tests
```go
func TestUserService_Create(t *testing.T) {
tests := []struct {
name string
req CreateUserRequest
setup func(*MockUserRepo)
wantErr error
}{
{
name: "valid user",
req: CreateUserRequest{Name: "Alice", Email: "alice@example.com", Password: "secure123"},
setup: func(m *MockUserRepo) {
m.On("FindByEmail", mock.Anything, "alice@example.com").Return(nil, domain.ErrUserNotFound)
m.On("Create", mock.Anything, mock.Anything).Return(nil)
},
wantErr: nil,
},
{
name: "duplicate email",
req: CreateUserRequest{Name: "Alice", Email: "taken@example.com", Password: "secure123"},
setup: func(m *MockUserRepo) {
m.On("FindByEmail", mock.Anything, "taken@example.com").Return(&domain.User{}, nil)
},
wantErr: domain.ErrEmailTaken,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := new(MockUserRepo)
tt.setup(repo)
svc := NewUserService(repo, &bcryptHasher{}, slog.Default())
_, err := svc.Create(context.Background(), tt.req)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
} else {
assert.NoError(t, err)
}
})
}
}
```
## Variáveis de Ambiente
```bash
# Database
DATABASE_URL=postgres://user:pass@localhost:5432/myservice?sslmode=disable
# gRPC
GRPC_PORT=50051
REST_PORT=8080
# Auth
JWT_SECRET= # Load from vault in production
TOKEN_EXPIRY=24h
# Observability
LOG_LEVEL=info # debug, info, warn, error
OTEL_ENDPOINT= # OpenTelemetry collector
```
## Estratégia de Teste
```bash
/go-test # TDD workflow for Go
/go-review # Go-specific code review
/go-build # Fix build errors
```
### Comandos de Teste
```bash
# Unit tests (fast, no external deps)
go test ./internal/... -short -count=1
# Integration tests (requires Docker for testcontainers)
go test ./internal/repository/... -count=1 -timeout 120s
# All tests with coverage
go test ./... -coverprofile=coverage.out -count=1
go tool cover -func=coverage.out # summary
go tool cover -html=coverage.out # browser
# Race detector
go test ./... -race -count=1
```
## Workflow ECC
```bash
# Planning
/plan "Add rate limiting to user endpoints"
# Development
/go-test # TDD with Go-specific patterns
# Review
/go-review # Go idioms, error handling, concurrency
/security-scan # Secrets and vulnerabilities
# Before merge
go vet ./...
staticcheck ./...
```
## Fluxo Git
- `feat:` novas features, `fix:` correções de bug, `refactor:` mudanças de código
- Branches de feature a partir da `main`, PRs obrigatórios
- CI: `go vet`, `staticcheck`, `go test -race`, `golangci-lint`
- Deploy: imagem Docker gerada no CI e publicada em Kubernetes

View File

@@ -0,0 +1,285 @@
# Serviço de API Rust — CLAUDE.md de Projeto
> Exemplo real para um serviço de API Rust com Axum, PostgreSQL e Docker.
> Copie para a raiz do seu projeto e customize para seu serviço.
## Visão Geral do Projeto
**Stack:** Rust 1.78+, Axum (web framework), SQLx (banco assíncrono), PostgreSQL, Tokio (runtime assíncrono), Docker
**Arquitetura:** Arquitetura em camadas com separação handler → service → repository. Axum para HTTP, SQLx para SQL verificado em tempo de compilação, middleware Tower para preocupações transversais.
## Regras Críticas
### Convenções Rust
- Use `thiserror` para erros de library, `anyhow` apenas em crates binários ou testes
- Sem `.unwrap()` ou `.expect()` em código de produção — propague erros com `?`
- Prefira `&str` a `String` em parâmetros de função; retorne `String` quando houver transferência de ownership
- Use `clippy` com `#![deny(clippy::all, clippy::pedantic)]` — corrija todos os warnings
- Derive `Debug` em todos os tipos públicos; derive `Clone`, `PartialEq` só quando necessário
- Sem blocos `unsafe` sem justificativa com comentário `// SAFETY:`
### Banco de Dados
- Todas as queries usam macros SQLx `query!` ou `query_as!` — verificadas em compile time contra o schema
- Migrations em `migrations/` com `sqlx migrate` — nunca alterar banco diretamente
- Use `sqlx::Pool<Postgres>` como estado compartilhado — nunca criar conexão por requisição
- Todas as queries usam placeholders parametrizados (`$1`, `$2`) — nunca string formatting
```rust
// BAD: String interpolation (SQL injection risk)
let q = format!("SELECT * FROM users WHERE id = '{}'", id);
// GOOD: Parameterized query, compile-time checked
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&pool)
.await?;
```
### Tratamento de Erro
- Defina enum de erro de domínio por módulo com `thiserror`
- Mapeie erros para respostas HTTP via `IntoResponse` — nunca exponha detalhes internos
- Use `tracing` para logs estruturados — nunca `println!` ou `eprintln!`
```rust
use thiserror::Error;
#[derive(Debug, Error)]
pub enum AppError {
#[error("Resource not found")]
NotFound,
#[error("Validation failed: {0}")]
Validation(String),
#[error("Unauthorized")]
Unauthorized,
#[error(transparent)]
Internal(#[from] anyhow::Error),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let (status, message) = match &self {
Self::NotFound => (StatusCode::NOT_FOUND, self.to_string()),
Self::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
Self::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
Self::Internal(err) => {
tracing::error!(?err, "internal error");
(StatusCode::INTERNAL_SERVER_ERROR, "Internal error".into())
}
};
(status, Json(json!({ "error": message }))).into_response()
}
}
```
### Testes
- Testes unitários em módulos `#[cfg(test)]` dentro de cada arquivo fonte
- Testes de integração no diretório `tests/` usando PostgreSQL real (Testcontainers ou Docker)
- Use `#[sqlx::test]` para testes de banco com migration e rollback automáticos
- Faça mock de serviços externos com `mockall` ou `wiremock`
### Estilo de Código
- Tamanho máximo de linha: 100 caracteres (enforced by rustfmt)
- Agrupe imports: `std`, crates externas, `crate`/`super` — separados por linha em branco
- Módulos: um arquivo por módulo, `mod.rs` só para re-exports
- Tipos: PascalCase, funções/variáveis: snake_case, constantes: UPPER_SNAKE_CASE
## Estrutura de Arquivos
```
src/
main.rs # Entrypoint, server setup, graceful shutdown
lib.rs # Re-exports for integration tests
config.rs # Environment config with envy or figment
router.rs # Axum router with all routes
middleware/
auth.rs # JWT extraction and validation
logging.rs # Request/response tracing
handlers/
mod.rs # Route handlers (thin — delegate to services)
users.rs
orders.rs
services/
mod.rs # Business logic
users.rs
orders.rs
repositories/
mod.rs # Database access (SQLx queries)
users.rs
orders.rs
domain/
mod.rs # Domain types, error enums
user.rs
order.rs
migrations/
001_create_users.sql
002_create_orders.sql
tests/
common/mod.rs # Shared test helpers, test server setup
api_users.rs # Integration tests for user endpoints
api_orders.rs # Integration tests for order endpoints
```
## Padrões-Chave
### Handler (Enxuto)
```rust
async fn create_user(
State(ctx): State<AppState>,
Json(payload): Json<CreateUserRequest>,
) -> Result<(StatusCode, Json<UserResponse>), AppError> {
let user = ctx.user_service.create(payload).await?;
Ok((StatusCode::CREATED, Json(UserResponse::from(user))))
}
```
### Service (Lógica de Negócio)
```rust
impl UserService {
pub async fn create(&self, req: CreateUserRequest) -> Result<User, AppError> {
if self.repo.find_by_email(&req.email).await?.is_some() {
return Err(AppError::Validation("Email already registered".into()));
}
let password_hash = hash_password(&req.password)?;
let user = self.repo.insert(&req.email, &req.name, &password_hash).await?;
Ok(user)
}
}
```
### Repository (Acesso a Dados)
```rust
impl UserRepository {
pub async fn find_by_email(&self, email: &str) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as!(User, "SELECT * FROM users WHERE email = $1", email)
.fetch_optional(&self.pool)
.await
}
pub async fn insert(
&self,
email: &str,
name: &str,
password_hash: &str,
) -> Result<User, sqlx::Error> {
sqlx::query_as!(
User,
r#"INSERT INTO users (email, name, password_hash)
VALUES ($1, $2, $3) RETURNING *"#,
email, name, password_hash,
)
.fetch_one(&self.pool)
.await
}
}
```
### Teste de Integração
```rust
#[tokio::test]
async fn test_create_user() {
let app = spawn_test_app().await;
let response = app
.client
.post(&format!("{}/api/v1/users", app.address))
.json(&json!({
"email": "alice@example.com",
"name": "Alice",
"password": "securepassword123"
}))
.send()
.await
.expect("Failed to send request");
assert_eq!(response.status(), StatusCode::CREATED);
let body: serde_json::Value = response.json().await.unwrap();
assert_eq!(body["email"], "alice@example.com");
}
#[tokio::test]
async fn test_create_user_duplicate_email() {
let app = spawn_test_app().await;
// Create first user
create_test_user(&app, "alice@example.com").await;
// Attempt duplicate
let response = create_user_request(&app, "alice@example.com").await;
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
}
```
## Variáveis de Ambiente
```bash
# Server
HOST=0.0.0.0
PORT=8080
RUST_LOG=info,tower_http=debug
# Database
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
# Auth
JWT_SECRET=your-secret-key-min-32-chars
JWT_EXPIRY_HOURS=24
# Optional
CORS_ALLOWED_ORIGINS=http://localhost:3000
```
## Estratégia de Teste
```bash
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test module
cargo test api_users
# Check coverage (requires cargo-llvm-cov)
cargo llvm-cov --html
open target/llvm-cov/html/index.html
# Lint
cargo clippy -- -D warnings
# Format check
cargo fmt -- --check
```
## Workflow ECC
```bash
# Planning
/plan "Add order fulfillment with Stripe payment"
# Development with TDD
/tdd # cargo test-based TDD workflow
# Review
/code-review # Rust-specific code review
/security-scan # Dependency audit + unsafe scan
# Verification
/verify # Build, clippy, test, security scan
```
## Fluxo Git
- `feat:` novas features, `fix:` correções de bug, `refactor:` mudanças de código
- Branches de feature a partir da `main`, PRs obrigatórios
- CI: `cargo fmt --check`, `cargo clippy`, `cargo test`, `cargo audit`
- Deploy: Docker multi-stage build com base `scratch` ou `distroless`

View File

@@ -0,0 +1,166 @@
# Aplicação SaaS — CLAUDE.md de Projeto
> Exemplo real para uma aplicação SaaS com Next.js + Supabase + Stripe.
> Copie para a raiz do seu projeto e customize para sua stack.
## Visão Geral do Projeto
**Stack:** Next.js 15 (App Router), TypeScript, Supabase (auth + DB), Stripe (billing), Tailwind CSS, Playwright (E2E)
**Arquitetura:** Server Components por padrão. Client Components apenas para interatividade. API routes para webhooks e server actions para mutações.
## Regras Críticas
### Banco de Dados
- Todas as queries usam cliente Supabase com RLS habilitado — nunca bypass de RLS
- Migrations em `supabase/migrations/` — nunca modificar banco diretamente
- Use `select()` com lista explícita de colunas, não `select('*')`
- Todas as queries user-facing devem incluir `.limit()` para evitar resultados sem limite
### Autenticação
- Use `createServerClient()` de `@supabase/ssr` em Server Components
- Use `createBrowserClient()` de `@supabase/ssr` em Client Components
- Rotas protegidas checam `getUser()` — nunca confiar só em `getSession()` para auth
- Middleware em `middleware.ts` renova tokens de auth em toda requisição
### Billing
- Handler de webhook Stripe em `app/api/webhooks/stripe/route.ts`
- Nunca confiar em preço do cliente — sempre buscar do Stripe server-side
- Status da assinatura checado via coluna `subscription_status`, sincronizada por webhook
- Usuários free tier: 3 projetos, 100 chamadas de API/dia
### Estilo de Código
- Sem emojis em código ou comentários
- Apenas padrões imutáveis — spread operator, nunca mutar
- Server Components: sem diretiva `'use client'`, sem `useState`/`useEffect`
- Client Components: `'use client'` no topo, mínimo possível — extraia lógica para hooks
- Prefira schemas Zod para toda validação de entrada (API routes, formulários, env vars)
## Estrutura de Arquivos
```
src/
app/
(auth)/ # Auth pages (login, signup, forgot-password)
(dashboard)/ # Protected dashboard pages
api/
webhooks/ # Stripe, Supabase webhooks
layout.tsx # Root layout with providers
components/
ui/ # Shadcn/ui components
forms/ # Form components with validation
dashboard/ # Dashboard-specific components
hooks/ # Custom React hooks
lib/
supabase/ # Supabase client factories
stripe/ # Stripe client and helpers
utils.ts # General utilities
types/ # Shared TypeScript types
supabase/
migrations/ # Database migrations
seed.sql # Development seed data
```
## Padrões-Chave
### Formato de Resposta de API
```typescript
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string; code?: string }
```
### Padrão de Server Action
```typescript
'use server'
import { z } from 'zod'
import { createServerClient } from '@/lib/supabase/server'
const schema = z.object({
name: z.string().min(1).max(100),
})
export async function createProject(formData: FormData) {
const parsed = schema.safeParse({ name: formData.get('name') })
if (!parsed.success) {
return { success: false, error: parsed.error.flatten() }
}
const supabase = await createServerClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return { success: false, error: 'Unauthorized' }
const { data, error } = await supabase
.from('projects')
.insert({ name: parsed.data.name, user_id: user.id })
.select('id, name, created_at')
.single()
if (error) return { success: false, error: 'Failed to create project' }
return { success: true, data }
}
```
## Variáveis de Ambiente
```bash
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY= # Server-only, never expose to client
# Stripe
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# App
NEXT_PUBLIC_APP_URL=http://localhost:3000
```
## Estratégia de Teste
```bash
/tdd # Unit + integration tests for new features
/e2e # Playwright tests for auth flow, billing, dashboard
/test-coverage # Verify 80%+ coverage
```
### Fluxos E2E Críticos
1. Sign up → verificação de e-mail → criação do primeiro projeto
2. Login → dashboard → operações CRUD
3. Upgrade de plano → Stripe checkout → assinatura ativa
4. Webhook: assinatura cancelada → downgrade para free tier
## Workflow ECC
```bash
# Planning a feature
/plan "Add team invitations with email notifications"
# Developing with TDD
/tdd
# Before committing
/code-review
/security-scan
# Before release
/e2e
/test-coverage
```
## Fluxo Git
- `feat:` novas features, `fix:` correções de bug, `refactor:` mudanças de código
- Branches de feature a partir da `main`, PRs obrigatórios
- CI roda: lint, type-check, unit tests, E2E tests
- Deploy: preview da Vercel em PR, produção no merge para `main`

View File

@@ -0,0 +1,109 @@
# Exemplo de CLAUDE.md no Nível de Usuário
Este é um exemplo de arquivo CLAUDE.md no nível de usuário. Coloque em `~/.claude/CLAUDE.md`.
Configurações de nível de usuário se aplicam globalmente em todos os projetos. Use para:
- Preferências pessoais de código
- Regras universais que você sempre quer aplicar
- Links para suas regras modulares
---
## Filosofia Central
Você é Claude Code. Eu uso agentes e skills especializados para tarefas complexas.
**Princípios-Chave:**
1. **Agent-First**: Delegue trabalho complexo para agentes especializados
2. **Execução Paralela**: Use ferramenta Task com múltiplos agentes quando possível
3. **Planejar Antes de Executar**: Use Plan Mode para operações complexas
4. **Test-Driven**: Escreva testes antes da implementação
5. **Security-First**: Nunca comprometa segurança
---
## Regras Modulares
Diretrizes detalhadas em `~/.claude/rules/`:
| Rule File | Contents |
|-----------|----------|
| security.md | Security checks, secret management |
| coding-style.md | Immutability, file organization, error handling |
| testing.md | TDD workflow, 80% coverage requirement |
| git-workflow.md | Commit format, PR workflow |
| agents.md | Agent orchestration, when to use which agent |
| patterns.md | API response, repository patterns |
| performance.md | Model selection, context management |
| hooks.md | Hooks System |
---
## Agentes Disponíveis
Localizados em `~/.claude/agents/`:
| Agent | Purpose |
|-------|---------|
| planner | Feature implementation planning |
| architect | System design and architecture |
| tdd-guide | Test-driven development |
| code-reviewer | Code review for quality/security |
| security-reviewer | Security vulnerability analysis |
| build-error-resolver | Build error resolution |
| e2e-runner | Playwright E2E testing |
| refactor-cleaner | Dead code cleanup |
| doc-updater | Documentation updates |
---
## Preferências Pessoais
### Privacidade
- Sempre anonimizar logs; nunca colar segredos (API keys/tokens/passwords/JWTs)
- Revise a saída antes de compartilhar - remova qualquer dado sensível
### Estilo de Código
- Sem emojis em código, comentários ou documentação
- Prefira imutabilidade - nunca mutar objetos ou arrays
- Muitos arquivos pequenos em vez de poucos arquivos grandes
- 200-400 linhas típico, 800 máximo por arquivo
### Git
- Conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`
- Sempre testar localmente antes de commitar
- Commits pequenos e focados
### Testes
- TDD: escreva testes primeiro
- Cobertura mínima de 80%
- Unit + integration + E2E para fluxos críticos
### Captura de Conhecimento
- Notas pessoais de debug, preferências e contexto temporário → auto memory
- Conhecimento de time/projeto (decisões de arquitetura, mudanças de API, runbooks de implementação) → seguir estrutura de docs já existente no projeto
- Se a tarefa atual já produzir docs/comentários/exemplos relevantes, não duplique o mesmo conhecimento em outro lugar
- Se não houver local óbvio de docs no projeto, pergunte antes de criar um novo doc de topo
---
## Integração com Editor
Eu uso Zed como editor principal:
- Agent Panel para rastreamento de arquivos
- CMD+Shift+R para command palette
- Vim mode habilitado
---
## Métricas de Sucesso
Você tem sucesso quando:
- Todos os testes passam (80%+ de cobertura)
- Não há vulnerabilidades de segurança
- O código é legível e manutenível
- Os requisitos do usuário são atendidos
---
**Filosofia**: Design agent-first, execução paralela, planejar antes de agir, testar antes de codar, segurança sempre.