CodeGym /Kursy /ChatGPT Apps /Środowiska: local dev, staging, production + Dev Mode

Środowiska: local dev, staging, production + Dev Mode

ChatGPT Apps
Poziom 7 , Lekcja 0
Dostępny

1. Po co w ogóle myśleć o środowiskach

W typowym tworzeniu aplikacji webowych prędzej czy później pojawia się trio: lokalne środowisko deweloperskie, serwer testowy i środowisko produkcyjne. W świecie ChatGPT Apps jest tak samo, ale z dodatkowym zwrotem: klient (ChatGPT) zawsze jest w chmurze, nawet gdy „pracujesz lokalnie”.

Jeśli wszystko kręci się wyłącznie na twoim laptopie pod losowym adresem tunelu, pojawia się kilka nieprzyjemnych efektów. Po pierwsze, URL ciągle się zmienia i nie pamiętasz, do którego endpointu jest teraz podpięty Dev Mode. Po drugie, wydajność i sieć nie przypominają warunków produkcyjnych. Po trzecie, środowisko lokalne często używa innych kluczy, innych usług i w ogóle żyje w równoległej rzeczywistości.

Z drugiej strony, ciągłe „życie na produkcji” też jest złe. Każda poprawka może nagle zepsuć scenariusze żywym użytkownikom, zwłaszcza jeśli masz już integracje typu Stripe, OAuth lub płatności przez ACP. Prawnie i pod względem polityk to również problematyczne – eksperymenty na realnych użytkownikach to nie najlepsza droga do Store.

Dlatego celem tego wykładu jest ułożenie w głowie prostej, ale twardej schemy: jest local dev, jest staging, jest production, i jest Dev Mode jako sposób skierowania ChatGPT do właściwego środowiska. A nie jeden wielki „mój laptop z tunelem, który czasem nagle zamienia się w produkcję”.

2. Cechy ChatGPT Apps: klient zawsze w chmurze

W klasycznej aplikacji SPA często uruchamiasz i klienta, i serwer lokalnie: przeglądarka na localhost, backend na localhost – i wszystko szczęśliwie komunikuje się w obrębie jednej maszyny.

W ChatGPT Apps tak się nie dzieje. Klient (ChatGPT + twój widżet) zawsze żyje w infrastrukturze OpenAI. Nawet jeśli kod twojej aplikacji kręci się na twoim laptopie, żądanie przebiega tak:

sequenceDiagram
    participant User as Użytkownik
    participant ChatGPT as ChatGPT (chmura)
    participant Tunnel as HTTPS-tunel
    participant App as Twój Next.js + MCP

    User->>ChatGPT: Wiadomość / klik w widżet
    ChatGPT->>Tunnel: Żądanie HTTPS do URL aplikacji
    Tunnel->>App: Proxy na localhost
    App-->>Tunnel: Odpowiedź (UI/JSON)
    Tunnel-->>ChatGPT: Odpowiedź
    ChatGPT-->>User: Zaktualizowany czat + widżet

Nawet gdy „tylko testujesz lokalnie”, już żyjesz w systemie rozproszonym: jest klient w chmurze, jest sieć, jest tunel i jest twój lokalny serwer.

To ważne, ponieważ:

  1. Środowisko lokalne to nie „wszystko u mnie lokalnie”. To „chmura → tunel → lokalny serwer”.
  2. Gdy później dodasz staging i production, schemat będzie się różnił tylko tym, dokąd dokładnie ChatGPT wysyła żądania: do tunelu, na domenę stagingową lub na domenę produkcyjną.

3. Local dev: jak wygląda twoja obecna schemat

Sprawdźmy, jak ten ogólny schemat wygląda u ciebie teraz.
Po modułach 2–6 najprawdopodobniej masz taki obraz:

  • Serwer deweloperski Next.js uruchomiony poleceniem npm run dev (zwykle http://localhost:3000).
  • Lokalny serwer MCP (często to osobny proces, na przykład http://localhost:2091).
  • Tunel HTTPS (ngrok, Cloudflare Tunnel itd.), który wystawia twój endpoint Next.js/HTTP na zewnątrz pod adresem w rodzaju https://abc123.ngrok.app.

W Dev Mode w ChatGPT wskazujesz ten publiczny URL i ChatGPT zaczyna chodzić do twojej aplikacji. To wszystko to środowisko local dev.

Najważniejsze cechy local dev:

  • Środowisko lokalne daje bardzo szybki feedback loop. Zmieniasz kod w VS Code, Next.js robi hot reload, widżet odświeża się po kilku sekundach.
  • Tutaj możesz psuć wszystko, co chcesz, używać danych mock, testowych kluczy, dziwnych konfiguracji.
  • Nie ma tu realnych użytkowników – mało kto poza tobą w ogóle zna ten URL.

Zwykle wygląda to tak:

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

    ChatGPT((ChatGPT Cloud))
    Tunnel[[HTTPS tunel]]

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

Aby dalej nie mylić local/staging/production, dobrze, by sama aplikacja „wiedziała”, gdzie teraz działa. Z punktu widzenia kodu w twojej aplikacji warto jasno ustalić, że jesteś w środowisku deweloperskim. Najprostszy krok – wprowadzić mały moduł konfiguracji środowiska.

Na przykład utwórzmy plik 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';

Tutaj:

  1. Wprowadzamy typowane wyliczenie środowisk.
  2. Odczytujemy zmienną NEXT_PUBLIC_APP_ENV (później ustawisz ją na różne wartości na dev/staging/prod).
  3. Domyślnie zakładamy, że jesteśmy w 'local', aby lokalna praca działała „out of the box”.

Na razie to niczego nie deployuje, ale już daje punkt zaczepienia: twój kod rozumie, w jakim środowisku się wykonuje.

Dalej można, na przykład, pokazać środowisko w samym widżecie, żeby się nie mylić.

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

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

Taki mały badge bardzo pomaga nie pomylić „czy jestem teraz na stagingu, czy na produkcji?”, zwłaszcza gdy widżet wygląda identycznie.

4. Staging: generalna próba środowiska produkcyjnego

Środowisko staging to „próba generalna produkcji”. To już nie twój laptop z dev‑serwerem, lecz zdalny serwer lub deployment na Vercel, na który trafia zbudowany kod.

Z punktu widzenia ChatGPT staging wygląda prawie jak production: to wygodny, stabilny endpoint HTTPS z domeną w rodzaju https://staging.giftgenius.app, gdzie:

  • kod jest już zbudowany (npm run build zakończył się powodzeniem);
  • używane są zmienne środowiskowe podobne do produkcyjnych (te same nazwy, ten sam format), ale z kluczami testowymi;
  • dostępne są te same usługi zewnętrzne (Stripe sandbox, testowe konta OAuth);
  • topologia sieci jest podobna do produkcyjnej (na przykład ten sam typ bazy i ten sam region).

Po co staging w kontekście ChatGPT Apps:

Po pierwsze, to właśnie na staging wygodnie uruchamiać scenariusze end‑to‑end. Na przykład: użytkownik w ChatGPT → ChatGPT uruchamia twoją aplikację → widżet pyta użytkownika → wywoływany jest MCP‑tool, który sięga do zewnętrznego API → zwraca rekomendacje → widżet pokazuje wynik. Taki scenariusz na lokalce przez losowy tunel może zachowywać się w jeden sposób, a w staging‑środowisku – już inaczej: tam latencja, sieć i zasoby są bliższe rzeczywistości.

Po drugie, staging pozwala testować integracje, których po prostu strach używać lokalnie. Na przykład płatności: Stripe, ACP/Instant Checkout itp. Na staging konfigurujesz klucze testowe, testowe webhooki i odpalasz scenariusze „na poważnie”, ale bez prawdziwych pieniędzy.

Po trzecie, staging to miejsce wspólnej weryfikacji. Jeśli masz kilku deweloperów, projektanta, QA, product – potrzebują wspólnego URL‑a, który nie zależy od tego, czyj laptop jest włączony i komu padł tunel.

Wygodnie wyobrazić sobie staging tak:

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

    ChatGPT --> AppStaging

A już w środku https://staging.giftgenius.app mogą działać Next.js, serwer MCP, baza staging i cała reszta.

W tym wykładzie nie schodzimy w szczegóły deployu na Vercel – to zadanie kolejnych tematów. Teraz ważne jest po prostu przyjąć jako fakt: staging to osobne środowisko, maksymalnie podobne do production pod względem konfiguracji i tego, jak ChatGPT się do niego dostaje.

5. Production: serwer bojowy i prawdziwi użytkownicy

Środowisko production to miejsce, gdzie pojawiają się prawdziwi użytkownicy i prawdziwe pieniądze. Tu już nie ma „to ja szybko poprawię w main i zobaczę, co będzie” – wszelkie zmiany muszą być przemyślane, przetestowane i najlepiej z możliwością odwołania.

Domena produkcyjna musi być stabilna. To nie losowy ngrok‑URL, ale normalna nazwa w rodzaju https://giftgenius.app lub coś podobnego. Właśnie ten adres podajesz w ustawieniach App dla Store: gdy użytkownik znajdzie twoją aplikację w ChatGPT Store i uruchomi ją, ChatGPT będzie wywoływać właśnie ten endpoint.

Do środowiska produkcyjnego zwykle są wyższe wymagania:

  • Stabilność. Niski procent błędów, przewidywalny czas odpowiedzi, poprawne działanie pod obciążeniem. W późniejszych modułach będziemy mówić o SLO/SLI, ale intuicyjnie to „aplikacja powinna „prawie zawsze” działać i „prawie zawsze” odpowiadać szybko”.
  • Bezpieczeństwo. Tylko potrzebne sekrety, minimalnie niezbędne uprawnienia, ostrożna praca z PII i pieniędzmi.
  • Ograniczenie eksperymentów. Żadnego „znowu zrestartowałem serwer dev” w środku dnia pracy; eksperymenty przez feature flagi, A/B lub osobne środowisko dev/staging, a nie przez bezpośrednie grzebanie przy serwerze produkcyjnym.

W kategoriach ChatGPT production to historia już nie o Dev Mode, lecz o opublikowanej App: jest dostępna użytkownikom przez Store albo ustawienia organizacji, przechodzi review i powinna być wystarczająco niezawodna, by nie wstydzić się przed moderacją.

6. Dev Mode vs użycie produkcyjne App: co do czego jest podpięte

Teraz najczęstsze nieporozumienie: Dev Mode ChatGPT nie jest „osobnym środowiskiem”. To raczej przełącznik trasy: na jaki URL patrzy ChatGPT, kiedy testujesz aplikację.

W Dev Mode możesz:

  • podłączyć lokalną aplikację przez tunel;
  • podłączyć środowisko staging;
  • nawet tymczasowo skierować Dev Mode na production (czego zwykle nie warto robić).

Formalnie Dev Mode mówi ChatGPT: „Oto manifest mojej App, oto URL mojego endpointu MCP/Apps SDK. Używaj go, gdy uruchamiam tę aplikację”. I możesz ten URL zmieniać.

Po publikacji w Store twoja App otrzymuje oficjalny endpoint produkcyjny. To on będzie używany dla prawdziwych użytkowników i nie można go tak po prostu zmienić: potrzeba nowej wersji, review itd.

W praktyce rozsądny schemat dla twojej aplikacji edukacyjnej może wyglądać tak:

graph TD
    subgraph Dev Mode
      DevApp["GiftGenius Dev App
(Dev Mode)"] end subgraph Store ProdApp["GiftGenius
(Store App)"] end UserDev[Ty / zespół] --> DevApp UserProd[Prawdziwi użytkownicy] --> ProdApp DevApp -->|URL tunelu| LocalEnv[Local dev
https://abc123.ngrok.app] DevApp -->|staging URL| StagingEnv[Staging
https://staging.giftgenius.app] ProdApp -->|prod URL| ProdEnv[Production
https://giftgenius.app]

Aplikację Dev Mode GiftGenius Dev konfigurujesz tak, by zwykle patrzyła na local dev (przez tunel), a kiedy trzeba – na staging. Sklepowa aplikacja GiftGenius jest na stałe powiązana z produkcyjnym URL.

Czasem tworzy się też osobną App dla QA, w rodzaju GiftGenius Staging, która patrzy tylko na staging‑URL. To wygodne, jeśli masz duży zespół testerów; w ramach kursu wystarczy jedna dev‑App.

Ważne, by się przyzwyczaić do myślenia tak: Dev Mode to prywatna piaskownica dla ciebie i zespołu, gdzie można zmieniać URL, poprawiać metadane, restartować tunel. Produkcyjna App w Store patrzy tylko na production i żyje według bardziej rygorystycznych zasad.

7. Powiązanie gałęzi Git, domen i ChatGPT App

Środowiska to nie tylko serwery. To także gałęzie kodu i konfiguracje App w ChatGPT. Prędzej czy później będziesz chciał, aby po jednym rzucie okiem na URL lub nazwę App było wiadomo, jaka dokładnie wersja kodu tam działa.

Proste minimalne podejście jest takie.

Do rozwoju pojedynczych funkcji używasz gałęzi feature/*, na przykład feature/new-recommendation-algo. Kod uruchamiasz lokalnie + tunel. Dev Mode ChatGPT zwykle wskazuje na ten sam dev‑endpoint, gdzie po kolei uruchamiasz wersje lokalne. Osobna App pod każdą gałąź feature to przesada.

Do integracji funkcji przed wydaniem możesz utworzyć gałąź develop albo staging. Wszystko, co jest w tej gałęzi, automatycznie się deployuje na środowisko staging, na przykład na Vercel preview URL w rodzaju https://giftgenius-staging.vercel.app. Dla niego możesz założyć osobną Dev Mode‑App albo okresowo przestawiać wspólną Dev‑App na ten URL.

Gałąź main (lub master) to tylko przetestowany kod. To ona jest deployowana na production‑URL i powiązana ze sklepową aplikacją GiftGenius.

Może to wyglądać mniej więcej tak:

Środowisko Gałąź Git URL ChatGPT App
Local dev
feature/*
https://abc123.ngrok.app
GiftGenius Dev (Dev Mode)
Staging
develop / staging
https://staging.gift...
GiftGenius Dev lub GiftGenius Staging
Prod
main
https://giftgenius.app
GiftGenius (Store)

Pamiętasz APP_ENV z app/config/env.ts? Wartości 'local'/'staging'/'production' tutaj wprost odpowiadają kolumnie „Środowisko”: w local dev uruchamiasz aplikację z APP_ENV=local, deployment staging – z APP_ENV=staging, a production – z APP_ENV=production.

Taka tabelka to nie biurokracja, tylko sposób, by nie debugować według schematu „a co to w ogóle za wersja działa teraz na tej domenie?”.

W samym kodzie można tę więź trochę wzmocnić. Na przykład wyświetlać nie tylko ENV, ale i commit/gałąź w trybie debug widżetu:

// 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>;
}

Jeśli podczas deployu podstawisz do NEXT_PUBLIC_BUILD_COMMIT wartość SHA commita, w widżecie będzie uczciwie napisane, jaki dokładnie kod teraz działa. Na staging/prod to czasem ratuje godziny debugowania.

8. Mini‑praktyka: rysujemy schemat swoich środowisk

Zanim przejdziemy do Vercela i logów, warto dosłownie „narysować na serwetce” schemat swoich środowisk. To może być diagram mermaid w README.md, szkic na tablicy albo nawet obrazek w notesie.

Dla naszego przykładowego GiftGenius schemat może wyglądać tak:

graph TD
    subgraph ChatGPT
      DevMode["Dev Mode
(ty i zespół)"] Store["Store
(prawdziwi użytkownicy)"] end subgraph Servers Local[Local dev
Tunnel → localhost] Staging[Staging
staging.giftgenius.app] Prod[Production
giftgenius.app] end DevMode --> Local DevMode --> Staging Store --> Prod

Przydatne ćwiczenie dla ciebie zaraz po wykładzie:

  1. Wypisz wszystkie środowiska, które już masz: lokalka z tunelem, ewentualnie wczesny deployment na Vercel, coś jeszcze.
  2. Obok dopisz, które gałęzie Git tam się deployują.
  3. Jeszcze obok – które ChatGPT Apps (lub konektory) dokąd patrzą.
  4. Zaznacz strzałkami, skąd ChatGPT trafia do każdego serwera.

Jeśli pracujesz w zespole, dodaj taki plik architecture/environments.md w repozytorium. To od razu zmniejszy ryzyko „staging nam padł, ale nikt nie wie, jaki to w ogóle URL”.

Aby powiązać to z twoją aplikacją, możesz w Dev Mode już teraz założyć jedną App GiftGenius Dev i ustalić: domyślnie patrzy na tunel środowiska lokalnego, a kiedy chcesz przetestować cały release, tymczasowo przestawiasz ją na staging‑URL. W kolejnych wykładach nauczysz się deployować staging/prod na Vercel i wiązać to ze zmiennymi środowiskowymi.

Jeśli to wszystko zebrać w jedną myśl: traktuj środowiska i Dev Mode jak układ współrzędnych dla twojej App. Lokalnie – do szybkiego rozwoju, staging – do próby generalnej, production – dla prawdziwych użytkowników, a Dev Mode – twój przełącznik między nimi, a nie osobne magiczne środowisko.

9. Typowe błędy przy pracy ze środowiskami i Dev Mode

Błąd nr 1: żyć tylko na localhost + tunel i uważać to za produkcję.
Takie podejście wydaje się wygodne: „po co mi staging i prod, przecież mam tunel, ChatGPT się podłącza”. Ale tunel ma niestabilny URL, inne charakterystyki sieci i cała ta konstrukcja stoi na jednym laptopie. Gdy tylko będzie ci potrzebne coś w rodzaju OAuth callback, Stripe webhooks albo MCP Gateway, brak normalnego staging/prod doprowadzi do bólu.

Błąd nr 2: mylić Dev Mode z osobnym środowiskiem.
Wielu myśli: „Mam Dev Mode, więc mam środowisko dev”. W rzeczywistości Dev Mode tylko mówi ChatGPT, dokąd chodzić: do tunelu, na staging albo nawet na produkcję. Dev Mode to ustawienie po stronie klienta, a nie serwera. Środowiska serwerowe (local/staging/prod) tworzysz sam: deployujesz kod, ustawiasz domeny, zmienne środowiskowe.

Błąd nr 3: kierować Dev Mode na production i „trochę potestować”.
Technicznie to możliwe: możesz w Dev Mode wpisać produkcyjny URL i pobawić się App tak, jakby to była lokalka. Problem w tym, że nagle zaczynasz testować na prawdziwych użytkownikach, prawdziwych danych i, być może, prawdziwych pieniądzach. Każdy błąd narzędzia albo widżetu może doprowadzić do awarii dla użytkowników produkcyjnych, a ty nawet nie od razu zrozumiesz, skąd problem. Lepiej trzymać Dev Mode na dev/staging i używać sklepowej App dla produkcji.

Błąd nr 4: brak jasnej mapy „gałąź ↔ środowisko ↔ URL ↔ App”.
Jeśli nikt w zespole nie potrafi za pierwszym razem odpowiedzieć, która gałąź deployuje się na staging, jaki jest jego URL i która App w ChatGPT na niego patrzy, to gwarantowane źródło chaosu. Zaczynają się historie „u mnie działa, na staging nie, na produkcji jeszcze coś trzeciego”. Prosta tabelka albo plik markdown z taką mapą zwraca się wielokrotnie.

Błąd nr 5: nie doceniać różnicy między local dev a staging.
Lokalnie uruchamiasz dev‑serwer, masz jeden zestaw kluczy, jeden zestaw usług i jedną sieć. Na staging kod jest już zbudowany, działa w innym środowisku, z innymi limitami, timeoutami i trasami. Jeśli wszystko testujesz tylko lokalnie, a staging trzymasz „dla zasady”, krytyczne błędy wyjdą dopiero na produkcji. Ważne, by przywyknąć do łańcucha: najpierw lokalny rozwój, potem sprawdzenie na staging, i dopiero potem release na production.

Błąd nr 6: próbować rozwiązywać wszystkie problemy przez ChatGPT, ignorując schemat środowisk.
Czasem przy problemach deweloperzy zaczynają „pytać ChatGPT, co się stało”, zamiast spojrzeć na obrazek: która App do którego URL jest podpięta, w jakim środowisku padło, gdzie są logi. Nasz dzisiejszy schemat środowisk to fundament do kolejnego wykładu, gdzie będziemy systemowo debugować: zaglądać do logów, używać MCP‑inspektora, a dopiero potem obwiniać model.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION