CodeGym /Cursos /ChatGPT Apps /Ambientes: local dev, staging, production + Dev Mode

Ambientes: local dev, staging, production + Dev Mode

ChatGPT Apps
Nível 7 , Lição 0
Disponível

1. Por que pensar em ambientes

No desenvolvimento web comum, cedo ou tarde aparece a tríade: desenvolvimento local, servidor de testes e ambiente de produção. No mundo dos ChatGPT Apps é a mesma coisa, mas com um detalhe adicional: o cliente (ChatGPT) está sempre na nuvem, mesmo quando você desenvolve “na sua máquina”.

Se tudo roda apenas no seu notebook sob um endereço aleatório de túnel, surgem alguns efeitos incômodos. Primeiro, a URL muda o tempo todo e você não lembra a qual endpoint o Dev Mode está apontando agora. Segundo, desempenho e rede não se parecem com condições reais. Terceiro, o ambiente local muitas vezes usa outras chaves, outros serviços e, no geral, vive numa realidade paralela.

Por outro lado, “viver sempre em prod” também é ruim. Qualquer ajuste pode, de repente, quebrar fluxos para usuários reais, especialmente se você já tem integrações como Stripe, OAuth ou pagamentos via ACP. Do ponto de vista jurídico e de políticas, isso também é problemático: experimentar com usuários reais não é o melhor caminho para o Store.

Por isso, o objetivo desta aula é formar um esquema simples, porém rígido: existe local dev, existe staging, existe production, e existe o Dev Mode como um modo de direcionar o ChatGPT para o ambiente certo. E não um grande “meu notebook com um túnel que às vezes vira prod do nada”.

2. Particularidade dos ChatGPT Apps: o cliente está sempre na nuvem

Num SPA clássico, você costuma executar cliente e servidor localmente: o navegador em localhost, o backend em localhost, e tudo conversa feliz dentro da mesma máquina.

Nos ChatGPT Apps isso não acontece. O cliente (ChatGPT + seu widget) sempre vive na infraestrutura da OpenAI. Mesmo que o código do seu app rode no seu notebook, a requisição flui assim:

sequenceDiagram
    participant User as Usuário
    participant ChatGPT as ChatGPT (nuvem)
    participant Tunnel as Túnel HTTPS
    participant App as Seu Next.js + MCP

    User->>ChatGPT: Mensagem / clique no widget
    ChatGPT->>Tunnel: Requisição HTTPS para a URL do App
    Tunnel->>App: Proxy para o localhost
    App-->>Tunnel: Resposta (UI/JSON)
    Tunnel-->>ChatGPT: Resposta
    ChatGPT-->>User: Chat atualizado + widget

Mesmo quando você “só está testando localmente”, você já está em um sistema distribuído: há um cliente na nuvem, há rede, há um túnel e há seu servidor local.

Isso é importante porque:

  1. O ambiente local não é “tudo local”. É “nuvem → túnel → servidor local”.
  2. Quando você adicionar staging e production, o esquema só vai diferir em para onde o ChatGPT envia as requisições: para o túnel, para o domínio de staging ou para o domínio de produção.

3. Local dev: como está seu esquema atual

Vamos ver como esse esquema geral provavelmente está para você agora.
Depois dos módulos 2–6, você provavelmente tem algo assim:

  • Servidor de dev do Next.js, iniciado com npm run dev (geralmente em http://localhost:3000).
  • Servidor MCP local (muitas vezes um processo separado, por exemplo, em http://localhost:2091).
  • Túnel HTTPS (ngrok, Cloudflare Tunnel etc.) que publica seu endpoint Next.js/HTTP externamente em algo como https://abc123.ngrok.app.

Pelo Dev Mode no ChatGPT, você aponta essa URL pública e o ChatGPT começa a chamar seu aplicativo. Tudo isso é o ambiente de local dev.

Principais características do local dev:

  • O ambiente local dá um feedback loop muito rápido. Você altera o código no VS Code, o Next.js faz hot reload e o widget atualiza em poucos segundos.
  • Aqui você pode quebrar o que quiser, usar dados mockados, chaves de teste e configs estranhas.
  • Não há usuários reais aqui; quase ninguém além de você sabe dessa URL.

Normalmente fica assim:

graph LR
    subgraph Dev Laptop
      Next[Next.js dev server]
      MCP[MCP server]
    end

    ChatGPT((ChatGPT Cloud))
    Tunnel[[Túnel HTTPS]]

    ChatGPT --> Tunnel --> Next
    Next --> MCP

Para não confundir mais tarde entre local/staging/production, é útil que o próprio aplicativo “saiba” onde está rodando. Do ponto de vista do código, é bom fixar explicitamente que você está em um ambiente de dev. O passo mais simples é introduzir um pequeno módulo de configuração de ambiente.

Por exemplo, crie o arquivo app/config/env.ts:

// app/config/env.ts
export type AppEnv = 'local' | 'staging' | 'production';

export const APP_ENV: AppEnv =
  (process.env.NEXT_PUBLIC_APP_ENV as AppEnv) ?? 'local';

export const isProd = APP_ENV === 'production';

Aqui nós:

  1. Introduzimos um enum tipado de ambientes.
  2. Lemos a variável NEXT_PUBLIC_APP_ENV (mais tarde você vai defini-la com valores diferentes em dev/staging/prod).
  3. Por padrão, assumimos 'local', para que o desenvolvimento local funcione “out of the box”.

Ainda não estamos fazendo deploy de nada, mas já temos um ponto de partida: seu código entende em qual ambiente está sendo executado.

Depois, você pode, por exemplo, exibir o ambiente no próprio widget, para não se confundir.

// app/components/EnvBadge.tsx
import { APP_ENV } from '../config/env';

export function EnvBadge() {
  return <span>ENV: {APP_ENV}</span>;
}

Um badge pequeno como esse ajuda muito a não confundir “estou em staging ou em prod?”, especialmente quando o widget é visualmente igual.

4. Staging: um ensaio geral do ambiente de production

O ambiente de staging é o “ensaio do ambiente de produção”. Já não é seu notebook com o servidor de dev, e sim um servidor remoto ou um deploy no Vercel para onde o código compilado é publicado.

Do ponto de vista do ChatGPT, o staging parece quase production: é um endpoint HTTPS estável e conveniente com um domínio como https://staging.giftgenius.app, onde:

  • o código já está compilado (o npm run build foi concluído com sucesso);
  • são usadas variáveis de ambiente semelhantes às de produção (mesmos nomes, mesmo formato), mas com chaves de teste;
  • os mesmos serviços externos estão disponíveis (Stripe sandbox, contas de OAuth de teste);
  • a topologia de rede é parecida com a de produção (por exemplo, mesmo tipo de banco e mesma região).

Por que o staging é necessário no contexto de ChatGPT Apps:

Primeiro, é no staging que é conveniente rodar cenários end‑to‑end. Por exemplo: usuário no ChatGPT → o ChatGPT inicia seu aplicativo → o widget pergunta algo ao usuário → é chamado um MCP tool que acessa uma API externa → retorna recomendações → o widget mostra o resultado. Esse cenário, na máquina local via um túnel aleatório, pode se comportar de um jeito. No ambiente de staging — de outro: lá a latência, a rede e os recursos estão mais próximos da realidade.

Segundo, o staging permite testar integrações que dá medo de rodar localmente. Por exemplo, pagamentos: Stripe, ACP/Instant Checkout etc. No staging você configura chaves de teste, webhooks de teste e executa os cenários “de gente grande”, mas sem dinheiro real.

Terceiro, o staging é um lugar para verificação em equipe. Se você tem vários devs, designer, QA, product — todos precisam de uma URL comum que não dependa de quem ligou o notebook ou de quem teve o túnel derrubado.

É útil representar o staging assim:

graph LR
    ChatGPT((ChatGPT Cloud))
    AppStaging["GiftGenius Staging  https://staging.giftgenius.app"]

    ChatGPT --> AppStaging

E dentro de https://staging.giftgenius.app podem estar rodando o Next.js, o servidor MCP, o banco de dados de staging e todo o resto.

Nesta aula não entraremos nos detalhes de deploy no Vercel — isso é assunto de temas seguintes. Por ora, basta aceitar: staging é um ambiente separado, o mais parecido possível com production em configuração e na forma como o ChatGPT chega até ele.

5. Production: servidor de produção e usuários reais

O ambiente de produção é onde chegam os usuários reais e o dinheiro de verdade. Aqui não existe “vou só mexer no main rapidinho para ver no que dá” — quaisquer mudanças devem ser conscientes, testadas e, se possível, com possibilidade de rollback.

O domínio de produção deve ser estável. Não é uma URL aleatória do ngrok, e sim um nome de verdade como https://giftgenius.app ou algo semelhante. É exatamente esse endereço que você informa nas configurações do App para o Store: quando um usuário encontrar seu app no ChatGPT Store e executá-lo, o ChatGPT chamará esse endpoint.

Normalmente há requisitos elevados para o ambiente de produção:

  • Estabilidade. Baixa taxa de erros, tempo de resposta previsível, funcionamento correto sob carga. Em módulos posteriores falaremos sobre SLO/SLI, mas, intuitivamente, é “o app deve funcionar ‘quase sempre’ e responder ‘quase sempre’ rápido”.
  • Segurança. Somente os segredos necessários, permissões mínimas, cuidado com PII e dinheiro.
  • Restrição de experimentos. Nada de “reiniciei o servidor de dev” no meio do expediente; experimente por feature flags, A/B ou em ambientes dev/staging, e não fuçando diretamente no servidor de produção.

Em termos de ChatGPT, production não é mais sobre o Dev Mode, e sim sobre o App publicado: ele fica disponível a usuários via Store ou configurações da organização, passa por review e deve ser confiável o suficiente para não fazer feio na moderação.

6. Dev Mode vs uso em prod do App: como tudo se relaciona

Agora, a confusão mais comum: o Dev Mode do ChatGPT não é um “ambiente separado”. É mais um seletor de rota: para qual URL o ChatGPT está olhando quando você testa o aplicativo.

No Dev Mode você pode:

  • conectar o app local via túnel;
  • conectar o ambiente de staging;
  • até apontar temporariamente o Dev Mode para a produção (o que normalmente não é uma boa ideia).

Formalmente, o Dev Mode diz ao ChatGPT: “Aqui está o manifesto do meu App, aqui está a URL do meu endpoint MCP/Apps SDK. Use-a quando eu iniciar este app”. E você pode trocar essa URL.

Depois da publicação no Store, o App passa a ter um endpoint oficial de produção. É ele que será usado por usuários reais, e trocá-lo não é tão simples: é preciso uma nova versão, review etc.

Na prática, um esquema sensato para seu app de estudo pode ser assim:

graph TD
    subgraph Dev Mode
      DevApp["GiftGenius Dev App
(Dev Mode)"] end subgraph Store ProdApp["GiftGenius
(Store App)"] end UserDev[Você / equipe] --> DevApp UserProd[Usuários reais] --> ProdApp DevApp -->|URL do túnel| LocalEnv[Local dev
https://abc123.ngrok.app] DevApp -->|URL de staging| StagingEnv[Staging
https://staging.giftgenius.app] ProdApp -->|URL de prod| ProdEnv[Production
https://giftgenius.app]

O app do Dev Mode, GiftGenius Dev, você configura para normalmente apontar para o local dev (via túnel) e, quando necessário, para o staging. O app do Store, GiftGenius, fica vinculado estritamente à URL de production.

Às vezes cria-se ainda um App separado para QA, tipo GiftGenius Staging, que aponta apenas para a URL de staging. É útil se você tem uma equipe grande de testes; no curso, um único App de dev é suficiente.

É importante acostumar-se a pensar assim: o Dev Mode é uma sandbox pessoal para você e sua equipe, onde é possível trocar URLs, ajustar metadados e reiniciar o túnel. O App de produção no Store olha apenas para a produção e vive sob regras mais rígidas.

7. Vinculando branches do Git, domínios e o App do ChatGPT

Ambientes não são apenas servidores. São também branches de código e configurações do App no ChatGPT. Cedo ou tarde você vai querer que, com um olhar para a URL ou para o nome do App, dê para entender qual versão do código está rodando ali.

Uma abordagem mínima e simples é esta.

Para desenvolver features individuais, use branches feature/*, por exemplo feature/new-recommendation-algo. Rode o código localmente + túnel. O Dev Mode do ChatGPT geralmente aponta para o mesmo endpoint de dev, onde vocês executam as versões locais em sequência. Ter um App separado para cada branch de feature é exagero.

Para integrar features antes do release, você pode ter um branch develop ou staging. Tudo que estiver nele é deployado automaticamente para o ambiente de staging, por exemplo, num URL de preview do Vercel como https://giftgenius-staging.vercel.app. Para isso, você pode criar um App de Dev Mode separado ou, periodicamente, reconfigurar o App de Dev Mode comum para essa URL.

O branch main (ou master) é apenas para código testado. É ele que faz deploy para a URL de produção e está vinculado ao app do Store GiftGenius.

Pode ficar mais ou menos assim:

Ambiente Branch Git URL ChatGPT App
Local dev
feature/*
https://abc123.ngrok.app
GiftGenius Dev (Dev Mode)
Staging
develop / staging
https://staging.gift...
GiftGenius Dev ou GiftGenius Staging
Prod
main
https://giftgenius.app
GiftGenius (Store)

Lembra do APP_ENV em app/config/env.ts? Os valores 'local'/'staging'/'production' correspondem diretamente à coluna “Ambiente”: no local dev você executa o app com APP_ENV=local, o deploy de staging com APP_ENV=staging, e a produção com APP_ENV=production.

Essa tabela não é burocracia, mas um jeito de evitar o debug “afinal, que versão está rodando nesse domínio?”.

No próprio código, dá para reforçar um pouco esse vínculo. Por exemplo, exibir não apenas o ENV, mas também o commit/branch no modo de debug do widget:

// app/config/buildInfo.ts
export const BUILD_COMMIT = process.env.NEXT_PUBLIC_BUILD_COMMIT ?? 'dev';
export const BUILD_ENV = process.env.NEXT_PUBLIC_APP_ENV ?? 'local';
// app/components/BuildInfo.tsx
import { BUILD_COMMIT, BUILD_ENV } from '../config/buildInfo';

export function BuildInfo() {
  return <small>Build: {BUILD_ENV}@{BUILD_COMMIT}</small>;
}

Se, no deploy, você preencher NEXT_PUBLIC_BUILD_COMMIT com o SHA do commit, o widget mostrará qual código está rodando. Em staging/prod isso às vezes salva horas de debug.

8. Mini prática: desenhando o seu esquema de ambientes

Antes de entrar em Vercel e logs, é útil literalmente “desenhar num guardanapo” o esquema dos seus ambientes. Pode ser um diagrama mermaid no README.md, um rascunho no quadro ou até uma imagem no caderno.

Para nosso GiftGenius de estudo, o esquema pode ser assim:

graph TD
    subgraph ChatGPT
      DevMode["Dev Mode
(você e a equipe)"] Store["Store
(usuários reais)"] end subgraph Servers Local[Local dev
Túnel → localhost] Staging[Staging
staging.giftgenius.app] Prod[Production
giftgenius.app] end DevMode --> Local DevMode --> Staging Store --> Prod

Exercício útil para você logo após a aula:

  1. Liste todos os ambientes que você já tem: local com túnel, talvez algum deploy inicial no Vercel, e assim por diante.
  2. Ao lado, anote quais branches do Git fazem deploy para cada um.
  3. Mais ao lado, quais ChatGPT Apps (ou conectores) apontam para onde.
  4. Marque com setas de onde o ChatGPT acessa cada servidor.

Se você não trabalha sozinho, crie um arquivo architecture/environments.md no repositório. Isso reduz imediatamente a chance de “nosso staging caiu, mas ninguém sabe qual é a URL dele”.

Para vincular isso ao seu app, você pode, no Dev Mode, criar agora um App chamado GiftGenius Dev e decidir: por padrão ele aponta para o túnel do ambiente local e, quando você quiser testar um release inteiro, reconfigura temporariamente para a URL de staging. Nas próximas aulas você vai aprender a fazer deploy de staging/prod no Vercel e a vincular isso às variáveis de ambiente.

Resumindo tudo em uma ideia: trate os ambientes e o Dev Mode como um sistema de coordenadas para o seu App. Local para desenvolvimento rápido, staging para ensaio geral, production para usuários reais, e o Dev Mode como seu seletor entre eles — não um ambiente mágico separado.

9. Erros comuns ao trabalhar com ambientes e Dev Mode

Erro nº 1: viver só em localhost + túnel e achar que isso é produção.
Parece conveniente: “para que preciso de staging e prod, se meu túnel funciona e o ChatGPT conecta?”. Mas o túnel tem URL instável, outras características de rede e todo o esquema depende de um único notebook. Assim que você precisar de algo como OAuth callback, webhooks do Stripe ou MCP Gateway, a ausência de staging/prod de verdade vai doer.

Erro nº 2: confundir o Dev Mode com um ambiente separado.
Muita gente pensa: “Tenho o Dev Mode, então tenho um ambiente de dev”. Na verdade, o Dev Mode só diz ao ChatGPT para onde ir: túnel, staging ou até prod. O Dev Mode é configuração do cliente, não do servidor. Os ambientes de servidor (local/staging/prod) você cria: faz deploy do código, configura domínios e variáveis de ambiente.

Erro nº 3: apontar o Dev Mode para production e “dar uma testadinha”.
Tecnicamente é possível: você pode colocar a URL de production no Dev Mode e brincar com o App como se fosse local. O problema é que você, de repente, começa a testar com usuários reais, dados reais e, possivelmente, dinheiro real. Qualquer erro de ferramenta ou widget pode causar falhas para usuários de produção — e você nem vai entender imediatamente de onde veio. Mantenha o Dev Mode em dev/staging e use o App do Store para production.

Erro nº 4: não ter um mapa explícito “branch ↔ ambiente ↔ URL ↔ App”.
Se ninguém na equipe consegue responder de primeira qual branch faz deploy para o staging, qual é a URL dele e qual App do ChatGPT aponta para lá, isso é fonte certa de caos. Começam as histórias “na minha máquina funciona, no staging não, e no prod dá outra coisa”. Uma tabela simples ou um arquivo markdown com esse mapa se paga muitas vezes.

Erro nº 5: subestimar a diferença entre local dev e staging.
Localmente você roda o servidor de dev, tem um conjunto de chaves, serviços e rede. No staging, o código já está compilado, roda em outro ambiente, com outros limites, timeouts e rotas. Se você só testa localmente e mantém o staging “pro forma”, bugs críticos vão aparecer já em produção. É importante acostumar-se à sequência: primeiro desenvolvimento local, depois verificação em staging, e só então release em production.

Erro nº 6: tentar resolver tudo via ChatGPT, ignorando o esquema de ambientes.
Às vezes, frente a problemas, devs começam a “perguntar ao ChatGPT o que aconteceu”, em vez de olhar para o diagrama: qual App está vinculado a qual URL, em qual ambiente caiu, onde estão os logs. Nosso esquema de ambientes de hoje é o fundamento para a próxima aula, na qual vamos depurar de forma sistemática: olhar logs, usar o MCP Inspector e só depois culpar o modelo.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION