Um resumo honesto das decisões de arquitetura por trás do sistema — porquê, e não apenas o quê — pensado para correr inteiramente em infraestrutura serverless na Vercel.
Frontend
Next.js 14 (App Router) + TypeScript + Tailwind CSS
Backend
Next.js Route Handlers (funções serverless nativas da Vercel)
Base de dados
MongoDB Atlas + Mongoose ODM
Autenticação
NextAuth.js v5 — sessões JWT, credenciais com bcrypt
Validação
Zod em todas as fronteiras de API
Deploy
Vercel — build e runtime 100% serverless
A Vercel não mantém processos Node de longa duração — cada rota de API é implantada como uma função serverless isolada. Por isso o Orbita usa Route Handlers do Next.js em vez de um servidor Express separado: é a mesma linguagem, o mesmo repositório, e nativamente compatível com o modelo de execução da Vercel, sem necessitar de infraestrutura adicional (containers, processos persistentes).
Funções serverless podem ser reutilizadas ('warm') entre pedidos, mas cada nova instância recria o módulo. A ligação ao Mongoose é guardada num objeto global e reutilizada quando o processo está quente, evitando esgotar o pool de conexões do cluster Atlas — um erro comum em aplicações serverless mal configuradas.
Em vez de uma base de dados por cliente (mais cara e complexa de gerir), o Orbita usa uma estratégia de 'tenant compartilhado com discriminador': todos os documentos de Project, Task e User carregam um tenantId, e cada query do lado do servidor é filtrada por esse valor extraído da sessão autenticada — nunca fornecido pelo cliente. Isto é validado num único ponto central (getApiContext), o que reduz a superfície de erro.
As permissões por papel (Proprietário, Administrador, Gestor, Membro) estão definidas numa única tabela de permissões (lib/rbac.ts) e são verificadas em cada rota de API antes de qualquer escrita. A interface esconde botões que o utilizador não pode usar, mas a garantia real de segurança está no servidor — um pedido direto à API com um papel insuficiente é sempre rejeitado.
Um 'Membro' só pode ver e atualizar o estado das tarefas que lhe foram atribuídas; não pode reatribuí-las nem alterá-las livremente. Esta regra está implementada na própria rota de API (comparando assigneeId com o utilizador autenticado), não apenas como um filtro de exibição.
Para manter o âmbito de portfólio auto-contido (sem depender de chaves de API de terceiros para correr), o convite de utilizadores gera uma password temporária devolvida ao administrador, em vez de um fluxo de email. A arquitetura já isola esse ponto (app/api/users/route.ts) para ser trivialmente substituído por um provedor de email (Resend, SES) em produção.
Quatro coleções no MongoDB Atlas. Note o campo tenantId presente em todas exceto Tenant — é a base de todo o isolamento multi-tenant.
name, slug, plan, status, ownerId, settings
name, email, passwordHash, tenantId, role, status
tenantId, name, status, ownerId, memberIds, dueDate
tenantId, projectId, title, status, priority, assigneeId