# 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.