From be6d7f314af585332ef658165dd0770bb9f8c24e Mon Sep 17 00:00:00 2001 From: Paulo Victor Gomes Date: Sat, 21 Mar 2026 14:06:49 +0100 Subject: [PATCH] docs(pt-BR): add examples translation --- docs/pt-BR/examples/CLAUDE.md | 100 ++++++ docs/pt-BR/examples/django-api-CLAUDE.md | 308 ++++++++++++++++++ docs/pt-BR/examples/go-microservice-CLAUDE.md | 267 +++++++++++++++ docs/pt-BR/examples/rust-api-CLAUDE.md | 285 ++++++++++++++++ docs/pt-BR/examples/saas-nextjs-CLAUDE.md | 166 ++++++++++ docs/pt-BR/examples/user-CLAUDE.md | 109 +++++++ 6 files changed, 1235 insertions(+) create mode 100644 docs/pt-BR/examples/CLAUDE.md create mode 100644 docs/pt-BR/examples/django-api-CLAUDE.md create mode 100644 docs/pt-BR/examples/go-microservice-CLAUDE.md create mode 100644 docs/pt-BR/examples/rust-api-CLAUDE.md create mode 100644 docs/pt-BR/examples/saas-nextjs-CLAUDE.md create mode 100644 docs/pt-BR/examples/user-CLAUDE.md diff --git a/docs/pt-BR/examples/CLAUDE.md b/docs/pt-BR/examples/CLAUDE.md new file mode 100644 index 00000000..bd1c4b77 --- /dev/null +++ b/docs/pt-BR/examples/CLAUDE.md @@ -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 { + 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 diff --git a/docs/pt-BR/examples/django-api-CLAUDE.md b/docs/pt-BR/examples/django-api-CLAUDE.md new file mode 100644 index 00000000..1ec37f50 --- /dev/null +++ b/docs/pt-BR/examples/django-api-CLAUDE.md @@ -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 diff --git a/docs/pt-BR/examples/go-microservice-CLAUDE.md b/docs/pt-BR/examples/go-microservice-CLAUDE.md new file mode 100644 index 00000000..9cf45da3 --- /dev/null +++ b/docs/pt-BR/examples/go-microservice-CLAUDE.md @@ -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 diff --git a/docs/pt-BR/examples/rust-api-CLAUDE.md b/docs/pt-BR/examples/rust-api-CLAUDE.md new file mode 100644 index 00000000..92c21a54 --- /dev/null +++ b/docs/pt-BR/examples/rust-api-CLAUDE.md @@ -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` 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, + Json(payload): Json, +) -> Result<(StatusCode, Json), 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 { + 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, 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 { + 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` diff --git a/docs/pt-BR/examples/saas-nextjs-CLAUDE.md b/docs/pt-BR/examples/saas-nextjs-CLAUDE.md new file mode 100644 index 00000000..e9c785f8 --- /dev/null +++ b/docs/pt-BR/examples/saas-nextjs-CLAUDE.md @@ -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 = + | { 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` diff --git a/docs/pt-BR/examples/user-CLAUDE.md b/docs/pt-BR/examples/user-CLAUDE.md new file mode 100644 index 00000000..e5b4e474 --- /dev/null +++ b/docs/pt-BR/examples/user-CLAUDE.md @@ -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.