blog
Troubleshooting

Meu app funciona local mas não em produção — e agora?

O guia de troubleshooting para o problema mais frustrante do desenvolvimento web. Diagnóstico passo a passo para vibecoders.

hidden: true

TL;DR

Se funciona local mas não em produção, o problema está em uma dessas áreas: variáveis de ambiente, URLs hardcoded, dependências de build, banco de dados, ou CORS. Este guia te ajuda a diagnosticar e resolver cada uma.


hidden: true

Respira fundo

Esse é o problema mais comum no desenvolvimento web. Acontece com todo mundo — de iniciantes a seniors. Não é você que é burro, é que o ambiente local e o de produção são fundamentalmente diferentes.

A boa notícia: 95% dos casos caem em meia dúzia de causas. Vamos passar por cada uma.

Causa #1: Variáveis de ambiente (a mais comum)

Sintoma: App abre mas funcionalidades não funcionam, ou dá erro 500.

No localhost, suas variáveis estão no .env. Em produção, elas precisam ser configuradas na plataforma. Se você esqueceu alguma, o app vai quebrar silenciosamente.

Diagnóstico:

# Liste suas variáveis locais
cat .env
 
# Compare com as de produção
veloz env list
# ou
vercel env ls

Solução:

# Adicione cada variável que falta
veloz env set DATABASE_URL="sua-url-de-producao"
veloz env set STRIPE_SECRET_KEY="sua-chave-de-producao"

Dica: Mantenha um .env.example atualizado. Antes de cada deploy, compare com as variáveis configuradas em produção.

Causa #2: URLs apontando para localhost

Sintoma: Requests falhando, dados não carregam, erros de rede no console.

Você tem algum localhost:3000 ou 127.0.0.1 escondido no código? Em produção, isso aponta para lugar nenhum.

Diagnóstico:

# Procure por localhost no código
grep -r "localhost" src/
grep -r "127.0.0.1" src/

Solução: Substitua por variáveis de ambiente:

// ❌ Errado
const apiUrl = "http://localhost:3000/api";
 
// ✅ Certo
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3000/api";

O fallback para localhost funciona no dev. Em produção, a variável de ambiente assume.

Causa #3: Build falhando silenciosamente

Sintoma: Site não atualiza, mostra versão antiga, ou dá 404.

Às vezes o build falha mas a plataforma serve a última versão que funcionou. Você acha que deployou, mas na verdade não.

Diagnóstico:

# Rode o build localmente primeiro
npm run build

Se der erro local, vai dar erro em produção. Erros comuns:

  • TypeScript reclamando de tipos
  • Imports de arquivos que não existem
  • Dependências faltando no package.json

Solução: Corrija os erros de build localmente antes de deployar. Se o build passa local mas falha na plataforma, verifique:

  • Versão do Node.js (sua máquina vs produção)
  • Dependências em devDependencies que deveriam estar em dependencies
  • Case sensitivity (Mac ignora maiúsculas/minúsculas, Linux não)

Causa #4: Banco de dados

Sintoma: Erro 500, "connection refused", dados não aparecem.

Seu banco local é diferente do de produção. Problemas comuns:

  • URL erradaDATABASE_URL ainda aponta pro localhost
  • Migrations não rodaram — as tabelas não existem em produção
  • IP não liberado — o banco rejeita conexões do servidor de produção

Diagnóstico e solução:

# 1. Verifique a URL do banco em produção
veloz env get DATABASE_URL
 
# 2. Rode as migrations
npx prisma migrate deploy
# ou
npx prisma db push
 
# 3. Se usa Supabase/Neon, verifique se o IP do servidor está liberado

Dica: Use o connection string de produção com SSL. A maioria dos bancos cloud exige:

postgresql://user:pass@host:5432/db?sslmode=require

Causa #5: CORS

Sintoma: Requests funcionam no Postman mas falham no navegador. Erro "CORS policy" no console.

CORS (Cross-Origin Resource Sharing) é uma proteção do navegador. Se seu frontend está em meuapp.com e a API em api.meuapp.com, o navegador bloqueia por padrão.

No localhost, tudo roda na mesma origin, então não tem problema. Em produção, são domínios diferentes.

Solução no backend:

// Express/Hono
app.use(
  cors({
    origin: process.env.FRONTEND_URL, // https://meuapp.com
    credentials: true,
  }),
);

Solução simples: Se frontend e backend estão no mesmo projeto (Next.js com API Routes), CORS não é problema — tudo roda na mesma origin.

Causa #6: Caminhos de arquivo e case sensitivity

Sintoma: 404 para páginas ou assets, imports quebrados.

Mac e Windows ignoram maiúsculas/minúsculas em nomes de arquivo. Linux (onde a maioria dos servidores roda) não ignora.

// Funciona no Mac, quebra no Linux:
import Header from "./components/header"; // arquivo se chama Header.jsx

Diagnóstico:

# Procure inconsistências
find src -name "*.jsx" -o -name "*.tsx" | sort

Solução: Sempre use o nome exato do arquivo, respeitando maiúsculas e minúsculas.

Fluxo de diagnóstico rápido

Quando seu app não funciona em produção, siga essa ordem:

  1. Veja os logs de build — buildou com sucesso?
  2. Abra o console do navegador (F12) — tem erro JavaScript?
  3. Verifique variáveis de ambiente — todas configuradas?
  4. Procure por localhost no código
  5. Teste o banco — conexão funciona? Migrations rodaram?
  6. Cheque CORS — se frontend e API estão em domínios diferentes

Na maioria das vezes, o problema é o item 3. Sempre comece por aí.

Como evitar no futuro

  1. Rode npm run build antes de deployar — se falha local, falha em produção
  2. Use .env.example — documente todas as variáveis
  3. Nunca hardcode URLs — sempre use variáveis de ambiente
  4. Configure CI/CD — deploy automático garante que o build sempre passa
  5. Use uma plataforma que facilite — Veloz detecta problemas comuns e avisa antes do deploy
$ veloz deploy
 Detectando... Next.js
 Verificando variáveis... ⚠️ DATABASE_URL não configurada
 Configure com: veloz env set DATABASE_URL="..."

O melhor bug é o que você pega antes de ir pro ar.


hidden: true

FAQ

Por que meu app mostra tela branca em produção?

Geralmente é um erro de JavaScript que não aparece visualmente. Abra o console do navegador (F12 → Console) e procure erros em vermelho. As causas mais comuns são: variáveis de ambiente faltando, imports incorretos, ou URLs apontando para localhost.

Como descubro o que está dando errado em produção?

Primeiro, veja os logs de build da plataforma (Veloz, Vercel, etc.). Depois, abra o console do navegador no site em produção. Se for erro de servidor, veja os logs do servidor na plataforma de deploy.

Funciona no Vercel mas não no Veloz (ou vice-versa)?

Cada plataforma tem configurações padrão diferentes. Verifique: versão do Node.js, variáveis de ambiente, build command e output directory. A maioria dos problemas vem de variáveis de ambiente não configuradas na nova plataforma.