CodeGym /Corsi /ChatGPT Apps /Deploy su Vercel: repository, variabili d’ambiente (env),...

Deploy su Vercel: repository, variabili d’ambiente (env), preview → production

ChatGPT Apps
Livello 7 , Lezione 3
Disponibile

1. Perché usare Vercel per ChatGPT App

Nelle lezioni precedenti abbiamo eseguito GiftGenius in locale e lo abbiamo collegato a ChatGPT tramite Dev Mode e un tunnel. Ora è il momento di fare un altro passo verso un «vero» production e spostare lo stesso codice su Vercel.

A questo punto avete già un’app funzionante, GiftGenius (la nostra app didattica). In locale gira su Next.js 16 con un endpoint MCP (per esempio, /api/mcp) ed è basata sul ChatGPT Apps SDK Next.js Starter ufficiale.

Si potrebbe seguire la strada «noleggio un VPS, installo a mano Node, nginx e configuro tutto da solo», ma per Next.js è più o meno come scrivere il frontend con document.write nel 2025. Funziona, ma vi complicate la vita.

Vercel è ottimo per noi per diversi motivi.

Per prima cosa, capisce nativamente Next.js: configura automaticamente build, SSR, statici, livello edge e funzioni serverless. Per una ChatGPT App è particolarmente comodo, perché il widget e l’endpoint MCP si distribuiscono con un solo clic e vivono nella stessa infrastruttura.

In secondo luogo, Vercel offre CI/CD out‑of‑the‑box: collegate il repository Git — e ogni push crea un nuovo deployment immutabile con URL univoco. Dal branch main è considerato production, dagli altri branch — preview.

In terzo luogo, Vercel ha una gestione ordinata di ambienti e segreti. Separa chiaramente le variabili d’ambiente in Development, Preview e Production, le conserva criptate e permette di iniettarle comodamente in Next.js. È esattamente ciò che serve a una ChatGPT App, dove chiavi e URL del server MCP devono cambiare a seconda dell’ambiente.

In quarto luogo, Vercel offre rollback comodi: se una nuova release va storta, potete promuovere rapidamente il deployment precedente e riportare il sistema in uno stato funzionante. Questo riduce la «paura del deploy» e incoraggia rilasci piccoli e frequenti.

Infine, Vercel è l’azienda creatrice di Next.js. Hanno adattato Next.js ai loro server e i loro server a Next.js. Usando Vercel sentirete più volte quanto tutto funzioni in modo fluido e in pochi clic. Vi piacerà, garantito.

2. Punto di partenza: struttura del progetto GiftGenius

Secondo il piano del corso, il nostro GiftGenius vive in un unico repository. Ci sono due varianti di organizzazione, entrambe valide per Vercel:

1) Monorepo con più applicazioni — per esempio:

giftgenius/
  apps/
    web/   # Next.js (widget + MCP)
    mcp/   # server MCP separato (se lo avete estratto)

2) Un unico progetto Next.js, in cui sia il widget sia l’MCP vivono insieme (più semplice nella fase iniziale ed è proprio così che è strutturato lo starter ufficiale):

giftgenius/
  app/
    page.tsx         # widget
    api/
      mcp/route.ts   # endpoint MCP
  next.config.mjs
  package.json
  ...

Nelle lezioni del Modulo 2 avete già clonato l’Apps SDK Starter, installato le dipendenze ed eseguito npm run dev. Ora assumiamo che:

  • il progetto sia già su Git (GitHub / GitLab / Bitbucket);
  • in locale utilizziate .env.local con le chiavi (OPENAI_API_KEY e altre);
  • ChatGPT Dev Mode sia collegato al vostro tunnel.

Il nostro obiettivo — fare in modo che lo stesso codice venga buildato ed eseguito su Vercel, e che ChatGPT possa raggiungere non il tunnel, ma un dominio HTTPS stabile del tipo https://giftgenius.vercel.app.

3. Preparazione del repository al deploy

Prima di cliccare su «New Project» in Vercel, conviene mettere un po’ in ordine il repository. Sono passi semplici, ma faranno risparmiare molto tempo dopo.

Per prima cosa, assicuratevi che .env.local e .vercel non finiscano nel repository. In .gitignore dello Starter Next.js di solito è già tutto previsto, ma meglio controllare:

node_modules
.next
.env.local
.vercel

.env.local — è la vostra configurazione locale e i vostri segreti. Non deve mai finire su Git, soprattutto se contiene OPENAI_API_KEY o chiavi del database. Su Vercel conserveremo i segreti separatamente nell’interfaccia.

In secondo luogo, date un’occhiata a package.json. Per Vercel sono importanti gli scripts corretti:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

Per impostazione predefinita Vercel chiamerà npm run build (o pnpm build, se usate pnpm). Questo deve buildare il progetto senza errori.

In terzo luogo, assicuratevi che la versione di Node sia indicata e adatta a Next.js 16. Nelle release notes di Next.js 16 la versione minima è 18.18.0. Spesso basta il campo in package.json:

{
  "engines": {
    "node": ">=18.18.0"
  }
}

Vercel sceglierà una versione LTS di Node compatibile con la vostra applicazione.

Se tutto questo è fatto, potete pushare l’ultimo codice su Git e passare a Vercel.

4. Primo import del progetto in Vercel

Ora andiamo nell’interfaccia web di Vercel. Se non vi siete ancora registrati — è il momento.

Accedete a Vercel, cliccate «New Project» e scegliete dall’elenco il vostro repository giftgenius. In questa fase Vercel, sotto il cofano, controlla il contenuto del repository e quasi sempre riconosce automaticamente che è un progetto Next.js, proponendo il preset corrispondente.

Nelle impostazioni del progetto Vercel proporrà:

  • Framework = Next.js;
  • Build Command = npm run build (oppure pnpm build/yarn build);
  • Output Directory — la standard .next (non serve cambiarla).

Per il primo deploy potete anche non indicare subito le variabili d’ambiente (le aggiungeremo in un passaggio a parte). Cliccate «Deploy» — Vercel clona il repository, installa le dipendenze, esegue npm run build e, se va tutto a buon fine, crea il primo deploy con un indirizzo del tipo https://giftgenius-xyz.vercel.app.

È importante capire una cosa: ogni deploy è immutabile. Se poi fate push di modifiche, viene creato un nuovo deploy con un nuovo URL, mentre il vecchio rimane nella cronologia. Il dominio di produzione (per esempio, giftgenius.vercel.app o un vostro dominio personalizzato) punta a un deployment specifico e può essere reindirizzato indietro, facendo rollback.

Schema semplificato:

flowchart LR
    A[GitHub repo
giftgenius] -->|git push| B[Vercel build] B --> C[Preview Deploy #1
unique URL] B --> D[Preview Deploy #2
unique URL] D --> E[Production Alias
giftgenius.vercel.app]

Il branch Git main è di solito considerato il branch di production, tutto il resto — preview. Ma si può riconfigurare.

5. Variabili d’ambiente su Vercel

Al momento il vostro primo deploy, con ogni probabilità, non è molto funzionale: manca OPENAI_API_KEY, il server MCP non chiama API esterne ecc. È ora di occuparsi delle variabili d’ambiente.

In Vercel le variabili d’ambiente si gestiscono in Settings → Environment Variables. Qui si vede anche la separazione in tre scope: Development, Preview e Production.

Una tabellina mentale:

Scope Dove si usa Analogo in locale
Development vercel dev e sviluppo locale tramite Vercel CLI .env.local
Preview tutti i deploy dai branch diversi dal branch di production staging / test
Production deploy dal branch di production (di solito main) .env.prod «di produzione»

La differenza rispetto a .env.local in locale è che Vercel conserva i valori criptati e li espone automaticamente come process.env.MY_VAR nel codice di Next.js.

È molto importante capire il prefisso NEXT_PUBLIC_. Tutto ciò che inizia con NEXT_PUBLIC_ finirà nel bundle del browser e sarà visibile a qualsiasi utente (si vede tramite DevTools). Va bene per configurazioni pubbliche (NEXT_PUBLIC_ENV=preview, NEXT_PUBLIC_API_BASE_URL=https://giftgenius.vercel.app), ma è assolutamente da evitare per chiavi come OPENAI_API_KEY.

Per i segreti usiamo nomi senza NEXT_PUBLIC_ e li leggiamo solo lato server: nei route handler, negli strumenti MCP, ecc.

6. Configurare le variabili d’ambiente per GiftGenius: esempio

Vediamo quali variabili d’ambiente servono al nostro GiftGenius didattico.

Un set minimo può essere questo:

  • OPENAI_API_KEY — chiave per chiamare i modelli / client MCP;
  • APP_BASE_URL — URL base dell’app (https://giftgenius.vercel.app o l’URL di preview);
  • eventualmente, GIFTDATA_API_URL o PRODUCTS_API_URL, se avete un catalogo esterno.

In sviluppo locale questo vive in .env.local:

OPENAI_API_KEY=sk-local-...
APP_BASE_URL=http://localhost:3000
PRODUCTS_API_URL=https://dev-api.gifts.example.com

Su Vercel andate in Settings → Environment Variables e aggiungete le stesse chiavi e valori, ma nei rispettivi scope.

Esempio di come appare nel codice dell’endpoint MCP:

// app/api/mcp/route.ts
import { NextRequest } from 'next/server';

const apiKey = process.env.OPENAI_API_KEY!; // non fatelo così senza controlli nel codice reale :)

export async function POST(req: NextRequest) {
  if (!apiKey) {
    return new Response('Missing OPENAI_API_KEY', { status: 500 });
  }
  // Chiamata a OpenAI o a un altro servizio con apiKey...
}

Il widget può usare APP_BASE_URL lato server, ad esempio per costruire link assoluti, tenendo conto dell’iframe di ChatGPT e della configurazione assetPrefix/basePath dello starter.

Se gli serve un URL pubblico dell’API (ad esempio per window.fetch verso il vostro backend), si può definire NEXT_PUBLIC_API_BASE_URL. Ma mai NEXT_PUBLIC_OPENAI_API_KEY.

7. Preview deploy: uno staging potenziato

Passiamo alla parte più piacevole: i preview deploy. Quando collegate il repository Git, Vercel inizia automaticamente a creare un preview deploy per ogni push in un branch non‑production o per ogni Pull Request. Ogni deploy ha un URL univoco, del tipo:

https://giftgenius-git-feature-new-layout-username.vercel.app

Questi deploy usano lo scope Preview per le variabili d’ambiente, quindi potete impostare, per esempio:

# Preview env su Vercel
APP_BASE_URL=https://giftgenius-staging.vercel.app
PRODUCTS_API_URL=https://staging-api.gifts.example.com

senza confonderlo con production.

Dal punto di vista del Dev Mode di ChatGPT, l’URL di preview è il candidato ideale per lo staging. Nelle impostazioni della vostra Dev‑App potete temporaneamente cambiare l’endpoint dall’URL del tunnel a quello di preview e vedere come si comporta la versione già buildata di GiftGenius, ma non ancora quella di production.

Approccio frequente: per una feature create il branch feature/smart-recommendations, fate push delle modifiche — Vercel vi dà il link di preview. Andate in Dev Mode, cambiate l’URL con questo link, verificate gli scenari con GPT (scelta del regalo, visualizzazione delle schede, chiamate agli strumenti MCP). Solo quando è tutto ok fate merge in main. Production nel frattempo vive serena.

Schema mentale della pipeline:

flowchart TD
    A[Local dev
localhost + tunnel] --> B[git push
feature/*] B --> C[Preview Deploy
preview-URL] C --> D[ChatGPT Dev Mode
App → preview-URL] C --> E[Code review / test] E --> F[Merge su main] F --> G[Production Deploy
prod-URL] G --> H[ChatGPT Prod App
App → prod-URL]

8. Deploy in production e rollback

Quando fate merge delle modifiche in main (o in un altro branch di production scelto da voi), Vercel crea un deployment di production e gli assegna l’alias di production: giftgenius.vercel.app o il vostro dominio personale.

A questo punto la vostra Prod‑App di ChatGPT (che creerete a breve) deve essere configurata con l’URL di production. In Dev Mode continuerete a sperimentare con il tunnel o con l’URL di preview; gli utenti del ChatGPT Store invece useranno la production.

Il vantaggio dei deploy immutabili è che il rollback diventa molto semplice. Se la nuova release non è riuscita (ad esempio, uno strumento MCP va in errore con i dati reali), non dovete «curare» la produzione al volo. Aprite l’elenco dei deploy in Vercel, scegliete il precedente di successo e cliccate qualcosa come «Promote to Production» — da qualche parte K8s e Lambda si riconfigurano, e il vostro dominio torna a puntare alla versione stabile.

Si può automatizzare anche via CLI con comandi come vercel rollback, ma per il nostro corso basta capire il concetto: ogni deploy è un artefatto separato e l’alias di production può essere puntato a uno qualsiasi di essi.

9. Specificità di Next.js 16 + MCP su Vercel

Dal punto di vista di Vercel, il vostro endpoint MCP in Next.js è una funzione serverless (o una funzione edge, se l’avete configurata così). Vive poco: si «sveglia» alla richiesta, la elabora e termina. Non si può mantenere stato tra le invocazioni, a meno di usare un DB esterno o qualche storage.

Questo è critico per MCP: se decidete di tenere la cronologia della conversazione in un array globale let history = [] in route.ts, verrà azzerato a ogni cold start. Per memorizzare lo stato serve un sistema esterno (KV, Postgres, ecc.), ma questo è materiale per i moduli futuri.

Secondo aspetto — i timeout di esecuzione. Nei piani gratuiti di Vercel le funzioni serverless hanno un limite di tempo (al momento della redazione — circa 10 secondi su Hobby, di più su Pro). Per le richieste LLM e soprattutto per le catene di strumenti MCP può essere poco.

In Next.js 16 per i route handler si può impostare maxDuration per chiedere esplicitamente a Vercel più tempo (entro i limiti del piano):

// app/api/mcp/route.ts
export const maxDuration = 60; // secondi; su Pro si può arrivare fino a 300

export async function POST(req: Request) {
  // operazione lunga: chiamata a OpenAI, DB esterno, ecc.
}

Non è un pulsante magico «fai quanto vuoi», ma il modo corretto per dire a Vercel: «questa funzione può girare più a lungo, per favore non ucciderla troppo presto».

Infine, non dimenticate le particolarità dell’iframe di ChatGPT. Nello Apps SDK Starter sono già configurati assetPrefix e basePath, in modo che statici e route funzionino correttamente dentro gli iframe annidati di web-sandbox.oaiusercontent.com. Grazie a questo, tutte le richieste vanno al vostro dominio, non al sandbox. Con il deploy su Vercel questa configurazione resta, quindi ottenete il funzionamento corretto del widget out‑of‑the‑box.

10. Integrazione con ChatGPT dopo il deploy

Anche se formalmente appartiene di più ai moduli su Store e production, la vita dell’app e la logica di integrazione con ChatGPT dopo il deploy sono piuttosto semplici e si «incastrano» bene già ora.

Prima fate il deploy di GiftGenius su Vercel e ottenete l’URL di production. Poi in ChatGPT, in Dev Mode, create un’App separata, ad esempio GiftGenius Prod, e nelle sue impostazioni, come endpoint, indicate questo URL (più precisamente, l’endpoint MCP del tipo https://giftgenius.vercel.app/api/mcp secondo la guida OpenAI Apps SDK Deploy).

Per lo sviluppo continuate a usare la Dev App, puntata al tunnel o all’URL di preview. Per testare i build giornalieri/settimanali potete creare una Staging‑App collegata a un preview alias stabile. Ne risulta uno schema a tre livelli:

Dev App     → tunnel locale o dev-URL (instabile)
Staging App → preview/staging URL stabile su Vercel
Prod App    → production URL su Vercel

Per riferimento, riassumiamo tutto in una tabella:

Cosa URL / deploy su Vercel Scope su Vercel Chi lo usa
Dev App tunnel locale / vercel dev Development voi / il team
Staging App preview alias stabile Preview team / QA
Prod App giftgenius.vercel.app / dominio personalizzato Production utenti

È il modello local / staging / prod di cui abbiamo parlato all’inizio del modulo, ora agganciato a Vercel e alle ChatGPT Apps. È già l’architettura di un progetto maturo, non il solito localhost.

11. Errori tipici nel deploy su Vercel

Errore n. 1: i segreti sono rimasti solo in .env.local e non sono su Vercel.
Scenario molto frequente: in locale funziona tutto, cliccate con sicurezza «Deploy», l’app si builda, ma gli strumenti MCP in produzione restituiscono 500 con il testo «Missing OPENAI_API_KEY». La causa è semplice: Vercel non conosce i vostri .env.local locali. Occorre inserire separatamente le stesse variabili nelle impostazioni del progetto su Vercel (e negli scope corretti: Preview, Production).

Errore n. 2: uso di NEXT_PUBLIC_ per dati sensibili.
La voglia di «farlo funzionare e basta» a volte prevale e lo sviluppatore scrive NEXT_PUBLIC_OPENAI_API_KEY per avere accesso alla chiave dal codice client. Il risultato è che la chiave finisce nel bundle JS ed è accessibile a chiunque. Non è solo una cattiva pratica, è una via diretta alla fuga di dati e al blocco della chiave. Tutti i segreti — solo senza prefisso e solo lato server.

Errore n. 3: ambienti non allineati tra locale e Vercel.
In locale potreste avere un URL per i prodotti (http://localhost:4000), su Vercel un altro (https://api.gifts-staging.com) e in production un terzo. Se non mantenete un elenco accurato delle variabili d’ambiente e non verificate che in Preview/Production siano valorizzate correttamente, è facile ritrovarsi con il widget di production che chiama il backend di staging e quello di staging che chiama il backend di production. Aiuta una semplice disciplina: documentare tutte le variabili necessarie e controllarle in ogni ambiente.

Errore n. 4: ignorare i limiti di tempo di esecuzione per gli endpoint MCP.
In locale potete aspettare la risposta di un sistema esterno lento per 30 secondi senza accorgervi di problemi. Su Vercel la stessa funzione va in timeout dopo 10–15 secondi e ChatGPT vedrà un errore. Se non avete configurato maxDuration e non monitorate i tempi di esecuzione degli strumenti MCP, in production questo può trasformarsi in cadute sporadiche.

Errore n. 5: tentare di conservare lo stato di MCP in memoria nella funzione serverless.
A volte è forte la tentazione di mettere la cronologia del dialogo o una cache delle raccomandazioni in una variabile globale let cache = {} direttamente nel file del route handler. In locale, finché il dev server resta attivo a lungo, può persino «funzionare». Ma su Vercel ogni funzione serverless vive poco e spesso viene ricreata. Di conseguenza, alcune richieste «vedono» una cache vecchia, altre una nuova, altre ancora nulla. Questo genera bug strani e difficili da riprodurre. Per lo stato serve un DB esterno o un KV store; al livello di questa lezione è meglio considerare l’endpoint MCP stateless.

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