API de encurtador de URLs com analytics em tempo real e geolocalização.
Uma plataforma performática para criar URLs curtas, gerar QR codes, e acompanhar engajamentos detalhados por localização, dispositivo e navegador. Ideal para campanhas de marketing, tracking de links e análise de audiência geográfica.
- 🔗 Encurtamento de URLs com slugs customizáveis
- 📊 Analytics em tempo real (hits, engajamentos, cliques)
- 🌍 Rastreamento geográfico (país, cidade) com mapa de engajamentos
- 📱 Detecção automática de dispositivo (mobile/desktop) e SO
- 🎯 Geração de QR codes com opções de customização
- 🔐 Autenticação com JWT (email/senha + OAuth via Supabase)
- ⚡ Cache inteligente com Redis
- 🛡️ Rate limiting e proteção contra abuso
- 📈 Paginação otimizada para grandes volumes de dados
- 🐳 Deploy containerizado com Docker
- Runtime: Node.js >= 24
- Framework: Fastify (HTTP rápido e tipo-seguro)
- Banco de Dados: PostgreSQL + Prisma ORM
- Cache: Redis
- Auth: JWT + Supabase
- Geolocalização: geoip-lite
- TypeScript: 100% type-safe
- Node.js >= 24
- pnpm
- Docker
Copie o arquivo de exemplo e preencha os valores:
cp .env.exemple .envPara IA entender a estrutura automaticamente, consulte:
ARCHITECTURE.md- Documentação completa (Clean Architecture + DDD).copilot-instructions.md- Instruções para GitHub CopilotCLAUDE.md- Instruções para Claude/Claude Code
Ambiente local: só os bancos (Postgres + Redis) rodam em Docker, a API roda direto na sua máquina com hot-reload.
-
Instale as dependências
pnpm install
-
Configure o
.env(veja Variáveis de ambiente). Para bater com odocker-compose.dev.yml, use:DATABASE_URL="postgresql://mvUser:mbPass@localhost:5432/mvDb" REDIS_HOST=localhost REDIS_PORT=6379 NODE_ENV=development -
Suba Postgres e Redis via Docker (
docker-compose.dev.ymlsó sobe os bancos, não a API):docker-compose -f docker-compose.dev.yml up -d
Serviço Container Porta local Credenciais Postgres mv_postgres_dev5432user mvUser/ senhambPass/ dbmvDbRedis mv_redis_dev6379sem senha Para derrubar os bancos:
docker-compose -f docker-compose.dev.yml down(adicione-vpara apagar os volumes/dados). -
Gere o client do Prisma e rode as migrations
pnpm generate pnpm deploy # roda as migrations pnpm seed # popula dados iniciais (planos, etc.) — obrigatório antes do primeiro uso
-
Suba a API em modo dev (watch)
pnpm dev
A API sobe em http://localhost:<PORT> e a documentação interativa fica em http://localhost:<PORT>/docs (veja Documentação da API (Swagger)).
Com o servidor rodando, a documentação interativa (OpenAPI) fica disponível em:
http://localhost:<PORT>/docs
- Gerada automaticamente a partir dos schemas Zod de cada rota (
fastify-type-provider-zod+@fastify/swagger+@fastify/swagger-ui) — não há DTOs duplicados só para a doc. - Rotas organizadas por tag de domínio:
Auth,Links,Redirect,Analytics,User,Health. - Rotas protegidas exigem JWT: clique em Authorize no topo da página e informe
Bearer <token>. - A UI abre direto na aba de schema (tipos, obrigatoriedade, enums) em vez do exemplo cru; configurável em
src/infra/http/plugins/swagger.ts.
pnpm buildSobe toda a stack (API + Postgres + Redis) via Docker:
docker-compose up -dRebuildar após mudanças no código:
docker-compose up -d --build apiVer logs da API:
docker-compose logs -f api# Rodar migrations
pnpm deploy
# Rodar seed
pnpm seedOs testes unitários rodam automaticamente a cada commit via husky.
pnpm test:unitCrie o arquivo .skip-tests-until na raiz com a data de expiração no formato YYYY-MM-DD:
echo "2026-04-10" > .skip-tests-untilO hook ignorará os testes até essa data (inclusive) e removerá o arquivo automaticamente ao expirar. Para reativar antes do prazo:
rm .skip-tests-untilO arquivo está no
.gitignoree não será commitado.
Os testes unitários rodam automaticamente a cada commit via husky.
pnpm test:unitCrie o arquivo .skip-tests-until na raiz com a data de expiração no formato YYYY-MM-DD:
echo "2026-04-10" > .skip-tests-untilO hook ignorará os testes até essa data (inclusive) e removerá o arquivo automaticamente ao expirar. Para reativar antes do prazo:
rm .skip-tests-untilO arquivo está no
.gitignoree não será commitado.