Files
petlink_final/docs/03-arquitectura.md
2026-05-04 09:43:36 +01:00

6.5 KiB

3. Arquitectura do Sistema

3.1 Visão Geral

A arquitectura da PawLink segue o padrão de aplicação web moderna com separação clara entre frontend, backend e serviços externos. Adoptamos uma abordagem server-first com Next.js, que permite renderização no servidor (SSR) para melhor SEO e desempenho inicial, combinada com componentes interactivos no cliente onde necessário.

┌─────────────────────────────────────────────────────────────┐
│                        CLIENTE (Browser)                    │
│           React 18 · Tailwind CSS · TanStack Query          │
└───────────────────────┬─────────────────────────────────────┘
                        │ HTTPS
┌───────────────────────▼─────────────────────────────────────┐
│                  VERCEL (Edge Network)                      │
│        Next.js 14 — SSR · API Routes · Middleware           │
├──────────────┬──────────────┬───────────────────────────────┤
│  Auth Layer  │  API Routes  │      Static Assets (CDN)      │
│  NextAuth.js │  Prisma ORM  │      Cloudflare               │
└──────┬───────┴──────┬───────┴───────────────────────────────┘
       │              │
┌──────▼──────┐ ┌─────▼──────────────────────────────────────┐
│  Supabase   │ │           Serviços Externos                  │
│ PostgreSQL  │ │  Stripe · Resend · Anthropic · Upstash      │
│  + Storage  │ │                                              │
└─────────────┘ └──────────────────────────────────────────────┘

3.2 Camadas da Arquitectura

Camada de Apresentação (Frontend)

Tecnologia Função
Next.js 14+ (App Router) Framework principal — SSR, routing, optimização de imagens
TypeScript Tipagem estática para reduzir bugs em desenvolvimento
Tailwind CSS Estilos utilitários responsivos e consistentes
shadcn/ui Componentes acessíveis (ARIA) e personalizáveis
TanStack Query Cache de dados do servidor, loading/error states
Zustand Estado global da aplicação (sessão, preferências UI)
React Hook Form + Zod Formulários com validação type-safe

Camada de Lógica de Negócio (Backend)

Tecnologia Função
Next.js API Routes Endpoints serverless co-localizados com o frontend
NextAuth.js Autenticação completa com middleware de protecção de rotas
Prisma ORM Acesso type-safe à base de dados com migrações automáticas
Zod Validação rigorosa de todos os dados de entrada
bcryptjs Hash seguro de palavras-passe

Camada de Dados

Tecnologia Função
PostgreSQL via Supabase Base de dados relacional principal
Supabase Storage Armazenamento de imagens de animais e documentos
Upstash Redis Cache de sessões e rate limiting

Serviços Externos

Serviço Função
Stripe Processamento de pagamentos (Cartão, MBWay via Payment Element)
Resend + react-email Envio de emails transaccionais com templates profissionais
Anthropic Claude API IA para match inteligente e chatbot de suporte
Cloudflare CDN global, protecção DDoS, cache de assets
Sentry Monitorização de erros em produção
Vercel Analytics Core Web Vitals e métricas de performance

3.3 Fluxo de Dados — Adopção

Utilizador
    │
    ▼
[1] GET / → Next.js SSR → Prisma query → PostgreSQL
    │       Renderiza lista de animais no servidor
    │
    ▼
[2] Aplica filtros → TanStack Query → GET /api/animals?district=Lisboa&species=DOG
    │
    ▼
[3] API Route valida params (Zod) → Prisma query com WHERE clause
    │
    ▼
[4] Resposta JSON → React actualiza componentes AnimalGrid
    │
    ▼
[5] Clica "Adoptar" → Middleware Next.js verifica sessão JWT
    │  (sem sessão → redirect /login)
    │
    ▼
[6] Selecciona data → POST /api/reservations { animalId, date }
    │
    ▼
[7] API Route valida (Zod) → Prisma: UPDATE animal SET status='RESERVED'
                           → Prisma: CREATE reservation
    │
    ▼
[8] Resend envia email de confirmação com template react-email
    │
    ▼
[9] Resposta 201 → TanStack Query invalida cache → UI actualiza estado do animal

3.4 Fluxo de Dados — Doação Monetária

[1] Utilizador selecciona canil e montante
[2] POST /api/donations/intent → Stripe cria PaymentIntent
[3] Frontend renderiza Stripe Payment Element (dados do cartão tratados pelo Stripe)
[4] Stripe processa pagamento → webhook POST /api/payments/webhook
[5] API Route verifica assinatura HMAC do webhook
[6] Prisma: UPDATE donation SET status='COMPLETED'
[7] Resend envia recibo de doação

3.5 Decisões de Arquitectura

Porque Next.js e não SPA pura (Vite/React)?

O SEO é crítico para uma plataforma de adopção — os animais devem aparecer nos resultados de pesquisa do Google. Com SSR, a página /animals/bobi-labrador-lisboa renderiza HTML completo no servidor, indexável pelos motores de busca. Uma SPA devolveria apenas HTML vazio.

Porque Supabase e não base de dados gerida manualmente?

O Supabase oferece PostgreSQL gerido, storage de ficheiros, autenticação e realtime numa única plataforma com free tier generoso. Reduz a complexidade operacional para uma equipa pequena sem comprometer escalabilidade.

Porque Stripe e não Paypal?

O Stripe tem suporte nativo a MBWay (método de pagamento dominante em Portugal), SEPA Direct Debit e MB Multibanco através do Stripe Payment Element. Tem a melhor integração com o ecossistema Node.js/TypeScript e é PCI DSS Level 1.