Next.js: Projeto Final: Deploy & CI/CD
Última atualização: 2026-08-26
Do commit do código ao navegador do usuário, existem várias etapas no meio — deploy, CI/CD, monitoramento e otimização de performance — e este é o passo final para colocar sua aplicação verdadeiramente "no ar".
1. O Que Você Vai Aprender
- O Processo Completo de Deploy no Vercel (vercel.json + PostgreSQL + Domínio Personalizado + Variáveis de Ambiente)
- Solução Docker Self-Hosted (Build Multi-estágio com Dockerfile + docker-compose.yml + Nginx + PM2)
- Pipeline CI/CD com GitHub Actions (lint → test → build → deploy → Lighthouse CI)
- Rastreamento de Eventos com PostHog + @vercel/speed-insights + Monitoramento de Erros com Sentry
- Otimização Prática de Performance (Lighthouse 90+/100+ next/image lazy loading + análise de bundle)
- Resumo do Caminho de Aprendizado Full-Stack com Next.js 16 e Direções Avançadas
2. Uma História Real de uma Engenheira DevOps
(1) Ponto de Dor: Cada deploy é como "pisar em uma mina terrestre"
Diana é engenheira DevOps na Acme Corp, responsável pelo deploy e operações do TaskFlow. A equipe faz 20 deploys por mês, mas cada deploy é uma experiência estressante: envio manual de código via SSH resultava em variáveis de ambiente faltando (fazendo o banco de produção ficar inacessível); npm run build funcionava localmente mas causava erro de OOM (memória insuficiente) no servidor; erros dos usuários só eram descobertos duas horas após o deploy (por falta de alertas de monitoramento); e ninguém percebia quando a pontuação do Lighthouse caía de 85 para 62. O deploy mais recente causou 30 minutos de indisponibilidade, gerando mais de 200 reclamações no suporte ao cliente.
(2) Uma Solução de CI/CD Automatizado + Deploy Duplo + Monitoramento
Automatize verificações de qualidade com GitHub Actions + deploy sem configuração com Vercel + alternativa Docker self-hosted + monitoramento completo com PostHog/Sentry.
# Uma linha do GitHub Actions dispara o deploy totalmente automatizado
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: amondnet/vercel-action@v20
(3) Retorno
| Dimensão | Deploy Manual | Automação CI/CD |
|---|---|---|
| Tempo de Deploy | 45 minutos (incluindo verificações manuais) | 8 minutos (totalmente automatizado) |
| Risco de Indisponibilidade | Alto (arquivos faltando/configuração incorreta) | Baixo (consistência garantida) |
| Detecção de Problemas | Reclamação do usuário 2h depois | Alerta em tempo real do Sentry |
| Pontuação Lighthouse | Executado manualmente uma vez por mês | Detecção automática em PRs |
| Velocidade de Rollback | 15 minutos de restauração manual | 1 minuto com Vercel Rollback |
| Eficiência da Equipe | Gargalos no DevOps | Deploy Self-Service |
3. Deploy no Vercel
(1) Arquitetura do Vercel
graph TB
subgraph "Rede Edge do Vercel"
A[CDN Global] --> B[Edge Functions]
B --> C[Serverless Functions]
C --> D[Vercel Postgres]
end
subgraph "GitHub"
E[Código Fonte] -->|Push| F[GitHub Actions]
F -->|Deploy Automático| A
end
subgraph "Monitoramento"
G[Vercel Analytics]
H[Sentry]
I[PostHog]
end
C --> G
C --> H
B --> I
style A fill:#cce5ff
style E fill:#d4edda
style F fill:#ffeeba
▶ Exemplo: Configuração vercel.json
Saída:
Configuração JSON com chaves: framework ("nextjs"), buildCommand, outputDirectory, installCommand, regions (iad1/hkg1/gru1), env, crons, headers (headers de segurança + regras de cache) e redirects.
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"regions": ["iad1", "hkg1", "gru1"],
"env": {
"NEXT_PUBLIC_APP_URL": "https://taskflow.vercel.app"
},
"crons": [
{
"path": "/api/cron/daily-digest",
"schedule": "0 8 * * *"
}
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
}
]
},
{
"source": "/uploads/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
],
"redirects": [
{
"source": "/app",
"destination": "/dashboard",
"permanent": true
}
]
}
Saída:
Configuração JSON aplicada com sucesso.
▶ Exemplo: Deploy com o Vercel CLI
Saída:
Comando concluído.
# 1. Instalar o Vercel CLI
npm install -g vercel
# 2. Fazer Login no Vercel
vercel login
# 3. Vincular o Projeto
vercel link
# 4. Configurar Variáveis de Ambiente
vercel env add DATABASE_URL
vercel env add AUTH_SECRET
vercel env add GOOGLE_CLIENT_ID
vercel env add GOOGLE_CLIENT_SECRET
vercel env add AUTH_URL
vercel env add NEXT_PUBLIC_POSTHOG_KEY
vercel env add SENTRY_DSN
# 5. Deploy de Preview
vercel
# 6. Deploy em Produção
vercel --prod
# 7. Ver os logs de deploy
vercel logs
Saída:
added 127 packages in 3.2s
38 packages are looking for funding
run `npm fund` for details
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Vercel CLI 28.0.0
? Set up and deploy "C:\Users\admin\taskflow"? [Y/n] Y
? Which scope? Acme Corp
? Link to existing project? No
? What's your project's name? taskflow
? In which directory is your code? ./
Auto-detected Project Settings (Next.js):
- Build Command: npx next build
- Output Directory: .next
- Node.js Version: 20.x
✅ Production: https://taskflow.vercel.app [7s]
▶ Exemplo: Conectando ao Vercel Postgres
# 1. Criar Banco de Dados Postgres
vercel env add DATABASE_URL
# 2. Instalar o Vercel Postgres SDK
npm install @vercel/postgres
# 3. Atualizar a Fonte de Dados do Prisma
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
// Vercel Postgres — Gerenciamento Automático de Pool de Conexões
// No Vercel, habilite shadowDatabaseUrl para evitar conflitos de migração
}
Saída:
Schema do Prisma atualizado. Execute npx prisma generate para sincronizar o client.
// src/lib/db.ts
import { PrismaClient } from "@prisma/client"
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma
4. Docker Self-Hosted
(1) Arquitetura Self-Hosted
graph TB
subgraph "Host Docker"
A[Nginx<br/>Proxy Reverso] --> B[Aplicação Node.js<br/>(PM2)]
B --> C[PostgreSQL<br/>(Container)]
end
subgraph "Externo"
D[DNS: taskflow.example.com]
end
D --> A
A -->|Terminação SSL| B
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#f8d7da
▶ Exemplo: Build Multi-estágio no Dockerfile
Saída:
Sending build context to Docker daemon 4.096kB
Step 1/8 : FROM node:20-alpine AS deps
---> 1dd67de0f936
...
Successfully built a7b3c2d1e0f9
Successfully tagged taskflow:latest
# ============================================
# Estágio 1: Dependências
# ============================================
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production --ignore-scripts
RUN npm ci --only=development --ignore-scripts
# ============================================
# Estágio 2: Build
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
ENV NEXT_OUTPUT=standalone
RUN npx prisma generate
RUN npm run build
# ============================================
# Estágio 3: Runner de Produção
# ============================================
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
Saída:
Sending build context to Docker daemon 4.096kB
Step 1/8 : FROM node:20-alpine AS deps
---> 1dd67de0f936
...
Successfully built a7b3c2d1e0f9
Successfully tagged taskflow:latest
▶ Exemplo: docker-compose.yml
Saída:
Salve a configuração YAML acima no caminho do arquivo especificado. As configurações entrarão em vigor na próxima reinicialização do servidor.
version: "3.8"
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://taskflow:password@db:5432/taskflow
- AUTH_SECRET=${AUTH_SECRET}
- AUTH_URL=https://taskflow.example.com
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
- NEXTAUTH_URL=https://taskflow.example.com
- NODE_ENV=production
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- taskflow-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=taskflow
- POSTGRES_USER=taskflow
- POSTGRES_PASSWORD=${DB_PASSWORD}
ports:
- "5432:5432"
restart: unless-stopped
networks:
- taskflow-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U taskflow"]
interval: 10s
timeout: 5s
retries: 5
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
restart: unless-stopped
networks:
- taskflow-network
volumes:
postgres-data:
networks:
taskflow-network:
driver: bridge
Saída:
Seções de configuração: version, services, volumes, networks.
▶ Exemplo: Configuração do Nginx
Saída:
Seções: version, services, volumes, networks.
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream taskflow_app {
server app:3000;
}
server {
listen 80;
server_name taskflow.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name taskflow.example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Cabeçalhos de segurança
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Compressão Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;
gzip_min_length 1000;
gzip_comp_level 6;
# Assets estáticos (cache permanente)
location /_next/static {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
expires 365d;
add_header Cache-Control "public, immutable";
}
# Uploads
location /uploads {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Rotas da API (sem cache)
location /api {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
# Todo o restante
location / {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Suporte a WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
Saída:
Configuração do Nginx aplicada. Recarregue para ativar.
5. CI/CD com GitHub Actions
(1) Arquitetura do Pipeline
graph LR
A[Push para main] --> B[Lint]
B --> C[Verificação de Tipos]
C --> D[Testes Unitários]
D --> E[Build]
E --> F[Deploy no Vercel]
F --> G[Lighthouse CI]
G --> H{Pontuação >= 90?}
H -->|Sim| I[Sucesso]
H -->|Não| J[Rollback]
style A fill:#cce5ff
style F fill:#d4edda
style G fill:#ffeeba
style J fill:#f8d7da
6. Monitoramento em Produção
(1) Arquitetura de Monitoramento
graph TB
subgraph "Métricas de Usuário"
A["PostHog<br/>Eventos & Funis"]
B["Vercel Speed Insights<br/>Monitoramento Real de Usuários"]
end
subgraph "Rastreamento de Erros"
C["Sentry<br/>Erros & Performance"]
end
subgraph "Performance"
D["Lighthouse CI<br/>Tendências de Pontuação"]
E["Bundle Analyzer<br/>Tamanho do Bundle"]
end
subgraph "Alertas"
F["Alertas do Sentry<br/>PagerDuty"]
G["GitHub Checks<br/>Comentário no PR"]
end
A --> F
B --> D
C --> F
D --> G
E --> G
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#f8d7da
7. Otimização de Performance
(1) Comparação de Estratégias de Otimização
| Estratégia | Métricas | Antes da Otimização | Após a Otimização | Ferramentas |
|---|---|---|---|---|
| next/image lazy | LCP | 3.2s | 1.5s | <Image loading="lazy"> |
| Divisão de Bundle | TTI | 4.5s | 2.8s | @next/bundle-analyzer |
| Otimização de Fontes | CLS | 0.25 | 0.02 | next/font display:swap |
| PPR Shell Estático | FCP | 2.1s | 0.4s | experimental.ppr |
| CDN de Imagens | LCP | 2.8s | 1.2s | Vercel Image Optimization |
| Estratégia de Cache | TTFB | 800ms | 120ms | revalidateTag + CDN |
8. Exemplo Completo: Deploy e Validação em Ambiente de Produção
# ============================================
# Processo Completo de Deploy em Produção do TaskFlow
# ============================================
# --- Plano A: Deploy no Vercel ---
# 1. Verificações Pré-Build
npm run lint && npx tsc --noEmit && npm run test -- --run
# 2. Build e Verificação
npm run build
# Saída: ✓ Compiled successfully in 12.8s
# 3. Deploy de Preview
vercel
# Saída: https://taskflow-git-feature-abc123.vercel.app
# 4. Executar Testes E2E
npx playwright test --url=https://taskflow-git-feature-abc123.vercel.app
# 5. Inspeção Lighthouse
npx lhci autorun
# 6. Deploy em Produção
vercel --prod
# Saída: https://taskflow.vercel.app (Production)
# 7. Configurar um Domínio Personalizado
vercel domains add taskflow.example.com
# Saída: ✓ Domain taskflow.example.com added
# 8. Verificação
curl -I https://taskflow.example.com/api/health
# Saída: HTTP/2 200
# --- Plano B: Docker Self-Hosted ---
# 1. Construir Imagem Docker
docker build -t taskflow:latest .
# 2. Iniciar o serviço
docker compose up -d
# 3. Executar a migração do banco de dados
docker compose exec app npx prisma migrate deploy
# 4. Executar Seeding
docker compose exec app npx prisma db seed
# 5. Verificação
curl http://localhost/api/health
# Saída: {"status":"healthy","timestamp":"2026-07-06T10:00:00Z"}
# 6. Ver Logs
docker compose logs -f app
# 7. Métricas de Monitoramento
# - PostHog: https://app.posthog.com/project/taskflow
# - Sentry: https://sentry.io/organizations/acme/projects/taskflow
# - Painel Vercel: https://vercel.com/acme/taskflow
# --- Validação de Performance ---
# Relatório Lighthouse
# Performance: 94/100 ✅
# Acessibilidade: 97/100 ✅
# Boas Práticas: 93/100 ✅
# SEO: 100/100 ✅
# Core Web Vitals (RUM)
# LCP: 1.2s ✅ (Objetivo < 2.5s)
# FID: 12ms ✅ (Objetivo < 100ms)
# CLS: 0.02 ✅ (Objetivo < 0.1)
9. Revisão e Tópicos Avançados no Caminho de Aprendizado
(1) Roteiro de Aprendizado Full-Stack com Next.js 16
graph TB
subgraph "Fase 1: Fundamentos (6 aulas)"
A1["01-02: Introdução + Ambiente"]
A2["03-04: Roteamento + Layout"]
A3["05-06: Navegação + Rotas Paralelas"]
end
subgraph "Fase 2: Dados (7 aulas)"
B1["07-08: RSC + Coleta de Dados"]
B2["09-10: SSG/ISR/PPR"]
B3["11-12: Cache + Server Actions"]
B4["13-14: Actions Avançado + Rotas de API"]
end
subgraph "Fase 3: Avançado (6 aulas)"
C1["15: Autenticação Auth.js"]
C2["16: Banco de Dados Prisma"]
C3["17: Streaming"]
C4["18: Imagem/Fonte"]
C5["19: SEO/Metadados"]
C6["20: i18n/Middleware"]
end
subgraph "Fase 4: Produção (6 aulas)"
D1["21-22: Testes Unitários + E2E"]
D2["23-24: CI/CD + Docker"]
D3["25-26: Performance + Segurança/Migração"]
end
subgraph "Fase 5: Projetos Completos (4 aulas)"
E1["27: Inicialização + Autenticação"]
E2["28: Dashboard + PPR"]
E3["29: CRUD + Server Actions"]
E4["30: Deploy + CI/CD + Monitoramento"]
end
A1 --> A2 --> A3 --> B1
B1 --> B2 --> B3 --> B4 --> C1
C1 --> C2 --> C3 --> C4 --> C5 --> C6 --> D1
D1 --> D2 --> D3 --> E1
E1 --> E2 --> E3 --> E4
style A1 fill:#d4edda
style E4 fill:#cce5ff
(2) Lista de Habilidades
| Habilidade | Aula Correspondente | Nível de Proficiência |
|---|---|---|
| Roteamento por Sistema de Arquivos do App Router | #03–#06 | Domínio |
| Mentalidade de Server Components | #07 | Domínio |
| Coleta de Dados e Cache | #08–#11 | Domínio |
| CRUD com Server Actions | #12-#13, #29 | Domínio |
| Autenticação e Autorização | #15, #27 | Proficiente |
| Banco de Dados com Prisma ORM | #16, #27 | Proficiente |
| Testes (Vitest + Playwright) | #21-#22 | Proficiente |
| Pipeline CI/CD | #23, #30 | Proficiente |
| Solução de Deploy Duplo Vercel + Docker | #24, #30 | Proficiente |
| Monitoramento e Otimização de Performance | #25, #30 | Proficiente |
| Segurança e Migração | #26 | Conhecimento |
| PPR + Componentes de Cache | #10-#11 | Domínio (Exclusivo) |
(3) Áreas para Estudo Adicional
| Tópico | Conteúdo de Aprendizado | Recursos Recomendados |
|---|---|---|
| Integração com IA | Vercel AI SDK + RAG + Streaming | vercel/ai (10k⭐) |
| Micro Frontends | Module Federation + Turborepo | Documentação Oficial Nx / Turborepo |
| GraphQL | Apollo + Next.js + Codegen | Documentação do Apollo Client |
| Aplicações em Tempo Real | WebSocket + Socket.io + Liveblocks | Integração Liveblocks com Next.js |
| Edge Computing | Edge Functions + Durable Objects | Cloudflare Workers |
| Engenharia de Plataforma | Backstage + Portal Interno do Desenvolvedor | Spotify Backstage |
❓ Perguntas Frequentes
P: Qual devo escolher, Vercel ou Docker self-hosted? R: O Vercel é adequado para 90% das equipes — configuração zero, CDN global, HTTPS automático e deploys de preview. O Docker self-hosted só é necessário nos seguintes cenários: requisitos de conformidade (dados devem permanecer on-premises), sistemas internos (sem necessidade de acesso à internet pública) e ambientes de hiperescala (que exigem infraestrutura personalizada). O TaskFlow recomenda o Vercel como solução principal e o Docker como backup.
P: Quais são os limites de pontuação adequados para o Lighthouse CI no GitHub Actions? R: Recomendamos Performance ≥ 90, Acessibilidade ≥ 90, Boas Práticas ≥ 90 e SEO ≥ 90. Se o projeto tiver requisitos especiais (como muitos scripts de terceiros fazendo a Performance cair), você pode reduzir o limite para 80, mas deve adicionar uma nota TODO explicando o motivo e delineando um plano de correção.
P: O PostHog e o Sentry têm funcionalidades sobrepostas? R: Não. O PostHog foca na análise de comportamento do usuário (visualizações de página, cliques em botões, funis de conversão), enquanto o Sentry foca no rastreamento de erros (stack traces de crashes, spans de performance, saúde de releases). Os dois são complementares: o PostHog diz "o que os usuários fizeram", enquanto o Sentry diz "por que as coisas deram errado".
P: Qual é a diferença entre o Vercel Postgres e uma instância PostgreSQL self-hosted? R: O Vercel Postgres é um serviço gerenciado — oferece backups automáticos, escalonamento automático, rede VPC de baixa latência e modelo de precificação pay-as-you-go. O PostgreSQL self-hosted oferece controle total, mas exige operações e manutenção (backups, monitoramento e atualizações). O TaskFlow usa Postgres local para desenvolvimento, Vercel Postgres para deploy no Vercel e Postgres em container para self-hosting com Docker.
P: Por que existem três estágios no build multi-estágio do Docker? R: O Estágio 1 (deps) instala todas as dependências; o Estágio 2 (builder) faz o build usando apenas as dependências de desenvolvimento; o Estágio 3 (runner) copia apenas os artefatos e dependências de runtime. A imagem final foi comprimida de 1.2 GB para 358 MB, uma redução de 70%. Os containers de produção não incluem dependências de desenvolvimento como o compilador TypeScript, ferramentas de teste ou
node_modules.
P: Qual é o propósito do modo Standalone (output: 'standalone')? R: O modo standalone do
@latest/nextgera apenas o conjunto mínimo de arquivos necessários para o runtime (oserver.jse subdiretórios.next), excluindo pacotes desnecessários donode_modules. Quando usado com builds multi-estágio do Docker, a imagem final contém apenas o runtime do Next.js, reduzindo significativamente seu tamanho e superfície de ataque.
📖 Resumo
- Deploy no Vercel com configuração zero:
vercel --prodcoloca no ar com um único comando; suporta variáveis de ambiente, nomes de domínio e PostgreSQL - Três containers Docker self-hosted: Nginx (proxy reverso + SSL) + app Node.js (daemon PM2) + PostgreSQL (persistência)
- Um build Dockerfile multi-estágio comprime uma imagem de 1.2GB para 358MB, contendo apenas arquivos de runtime
- CI/CD com GitHub Actions: qualidade → build → deploy → lighthouse, pipeline automatizado de quatro estágios
- Defina um limite de pontuação de 90+ no Lighthouse CI para verificar automaticamente pull requests e evitar degradação de performance
- PostHog rastreia eventos do usuário (visualizações de página, cliques em botões, funis de conversão), enquanto o Sentry captura erros de runtime
@vercel/speed-insights+@vercel/analytics— monitoramento real de usuários com configuração zero- Bundle Analyzer visualiza o tamanho do bundle; meta: JS inicial < 300 kB
- O TaskFlow é um teste abrangente das capacidades full-stack do Next.js 16: de roteamento, RSC, PPR e Server Actions até Prisma, Auth.js e CI/CD
📝 Exercícios
-
Exercício Básico (⭐): Faça o deploy do TaskFlow no Vercel (conta gratuita), configure um domínio personalizado (opcional) e verifique se
/api/healthretorna o código de status 200. Configure a variável de ambienteNEXT_PUBLIC_POSTHOG_KEYe confirme que o PostHog recebe o evento de pageview. -
Exercício Avançado (⭐⭐): Teste a solução Docker self-hosted localmente — construa uma imagem Docker, inicie o
docker-compose(App + Nginx + PostgreSQL), configure um certificado SSL autoassinado, execute as migrações do banco de dados e verifique o acesso HTTPS. Faça commit dodocker-compose.yml,nginx.confeDockerfileno repositório do projeto. -
Desafio (⭐⭐⭐): Implemente monitoramento completo de funções para o TaskFlow: Defina 5 eventos-chave no PostHog (task_created / task_completed / user_signup / file_uploaded / project_created) e adicione atributos (duração, navegador, localização geográfica); Configure regras de alerta no Sentry (enviar notificações no Slack e alertas no PagerDuty quando a taxa de erro exceder 5%); adicione etapas de teste E2E com Playwright ao GitHub Actions (Deploy → E2E → Lighthouse em sequência); por fim, envie um arquivo README.md contendo: um diagrama de arquitetura de deploy, capturas de tela do painel de monitoramento, um relatório Lighthouse e um selo de status CI/CD.