CodeGym /Cours /ChatGPT Apps /Déploiement sur Vercel : dépôt, variables d’environnement...

Déploiement sur Vercel : dépôt, variables d’environnement, Preview → Production

ChatGPT Apps
Niveau 7 , Leçon 3
Disponible

1. Pourquoi Vercel pour l’app ChatGPT

Dans les cours précédents, nous avons lancé GiftGenius en local et l’avons connecté à ChatGPT via le mode Dev et un tunnel. Il est maintenant temps de faire un pas de plus vers une production « adulte » et de porter le même code sur Vercel.

À ce stade, vous avez déjà une application fonctionnelle GiftGenius (notre app pédagogique). En local, elle tourne sur Next.js 16 avec un endpoint MCP (par exemple, /api/mcp) et est bâtie sur la base du ChatGPT Apps SDK Next.js Starter officiel.

On pourrait suivre la voie « je loue un VPS, j’installe Node, nginx à la main et je configure tout moi‑même », mais pour Next.js, c’est à peu près comme écrire du frontend en pur document.write en 2025. Ça marche, mais vous vous compliquez clairement la vie.

Vercel est intéressant pour nous pour plusieurs raisons.

Premièrement, il comprend nativement Next.js : il configure automatiquement la build, le SSR, les assets statiques, la couche edge et les fonctions serverless. Pour une app ChatGPT c’est particulièrement pratique, car le widget et l’endpoint MCP se déploient en un clic et vivent dans la même infrastructure.

Deuxièmement, Vercel offre du CI/CD prêt à l’emploi : vous connectez un dépôt Git — et chaque push crée un nouveau déploiement immuable avec une URL unique. Depuis la branche main il est considéré comme production, depuis les autres branches — preview.

Troisièmement, Vercel a une bonne gestion des environnements et des secrets. Il sépare clairement les variables d’environnement en Development, Preview et Production, les stocke chiffrées et permet de les injecter facilement dans Next.js. C’est exactement ce dont a besoin une app ChatGPT, où les clés et l’URL du serveur MCP doivent varier selon l’environnement.

Quatrièmement, Vercel propose des rollbacks pratiques : si une nouvelle release se passe mal, on peut rapidement promouvoir le déploiement réussi précédent et remettre le système en état de marche. Cela réduit la « peur du déploiement » et encourage de petites releases fréquentes.

Enfin, Vercel est l’entreprise à l’origine de Next.js. Ils ont ajusté Next.js à leurs serveurs, et leurs serveurs à Next.js. En utilisant Vercel, vous ressentirez plus d’une fois à quel point tout fonctionne de façon fluide et en quelques clics. Je vous garantis que vous allez aimer.

2. Point de départ : structure du projet GiftGenius

Selon le plan du cours, notre GiftGenius vit dans un seul dépôt. Il y a deux options d’organisation, toutes deux acceptées par Vercel :

1) Monorepo avec plusieurs applications — par exemple :

giftgenius/
  apps/
    web/   # Next.js (widget + MCP)
    mcp/   # serveur MCP séparé (si vous l’avez extrait)

2) Un seul projet Next.js, où le widget et le MCP cohabitent (c’est plus simple au départ et c’est exactement ainsi que l’officiel starter est conçu) :

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

Dans les cours du Module 2, vous avez déjà cloné l’Apps SDK Starter, installé les dépendances et lancé npm run dev. À présent, nous partons du principe que :

  • le projet est déjà dans Git (GitHub / GitLab / Bitbucket) ;
  • en local, vous utilisez .env.local avec des clés (OPENAI_API_KEY et autres) ;
  • ChatGPT Dev Mode est relié à votre tunnel.

Notre objectif est de faire en sorte que le même code se construise et fonctionne sur Vercel, et que ChatGPT n’utilise plus un tunnel mais un domaine HTTPS stable du type https://giftgenius.vercel.app.

3. Préparer le dépôt au déploiement

Avant de cliquer sur « New Project » dans Vercel, il vaut la peine de mettre un peu d’ordre dans le dépôt. Ce sont des étapes simples, mais elles vous feront gagner beaucoup de temps par la suite.

Premièrement, assurez‑vous que .env.local et .vercel n’entrent pas dans le dépôt. Dans le .gitignore du Next.js Starter, c’est généralement déjà le cas, mais mieux vaut vérifier :

node_modules
.next
.env.local
.vercel

.env.local est votre configuration locale et vos secrets. Il ne doit jamais être committé dans Git, surtout si l’on y trouve OPENAI_API_KEY ou des clés de base de données. Sur Vercel, nous stockerons les secrets séparément dans l’interface.

Deuxièmement, regardez package.json. Pour Vercel, il est important d’avoir des scripts corrects :

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

Par défaut, Vercel appellera npm run build (ou pnpm build si vous utilisez pnpm). Cela doit construire le projet sans erreurs.

Troisièmement, assurez‑vous que la version de Node est spécifiée et compatible avec Next.js 16. Dans les release notes de Next.js 16, la version minimale est 18.18.0. Le plus souvent, un champ dans package.json suffit :

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

Vercel sélectionnera une version LTS de Node compatible avec votre application.

Si tout cela est fait, vous pouvez pousser le dernier code dans Git et passer à Vercel.

4. Premier import du projet dans Vercel

Passez maintenant à l’interface web de Vercel. Si vous n’y êtes pas encore inscrit, c’est le moment.

Connectez‑vous à Vercel, cliquez sur « New Project » et choisissez dans la liste votre dépôt giftgenius. À cette étape, Vercel inspecte le dépôt et, presque toujours, détecte de lui‑même qu’il s’agit d’un projet Next.js, en appliquant le preset adéquat.

Dans les paramètres du projet, Vercel proposera :

  • Framework = Next.js ;
  • Build Command = npm run build (ou pnpm build/yarn build) ;
  • Output Directory — .next standard (inutile de modifier).

Pour le premier déploiement, vous pouvez ne pas renseigner tout de suite les variables d’environnement (nous les ajouterons juste après). Cliquez sur « Deploy » — Vercel clone le dépôt, installe les dépendances, lance npm run build et, si tout réussit, crée un premier déploiement avec une adresse du type https://giftgenius-xyz.vercel.app.

Il est important de comprendre une chose : chaque déploiement est immuable. Si vous poussez ensuite des modifications, un nouveau déploiement est créé avec une nouvelle URL, et l’ancien reste dans l’historique. Le domaine de production (par exemple, giftgenius.vercel.app ou votre domaine personnalisé) pointe vers un déploiement donné et peut être basculé en arrière en effectuant un rollback.

Schématiquement, cela ressemble à ceci :

flowchart LR
    A[Dépôt GitHub
giftgenius] -->|git push| B[Build Vercel] B --> C[Déploiement Preview #1
URL unique] B --> D[Déploiement Preview #2
URL unique] D --> E[Alias Production
giftgenius.vercel.app]

La branche Git main est généralement considérée comme la branche de production, tout le reste — preview. Mais cela peut être reconfiguré.

5. Variables d’environnement sur Vercel

À présent, votre premier déploiement n’est probablement pas très fonctionnel : pas de OPENAI_API_KEY, le serveur MCP n’appelle pas d’API externes, etc. Il est temps de s’occuper des variables d’environnement.

Sur Vercel, les variables d’environnement se trouvent dans Settings → Environment Variables. On y voit aussi la séparation en trois scopes : Development, Preview et Production.

Petit tableau comme modèle mental :

Scope Où c’est utilisé Équivalent en local
Development vercel dev et dev local via Vercel CLI .env.local
Preview tous les déploiements issus des branches autres que la branche de production staging / test
Production déploiements depuis la branche de production (généralement main) .env.prod « de prod »

La différence par rapport à .env.local en local, c’est que Vercel stocke les valeurs chiffrées et les injecte automatiquement comme process.env.MY_VAR dans le code Next.js.

Il est très important de comprendre le préfixe NEXT_PUBLIC_. Tout ce qui commence par NEXT_PUBLIC_ se retrouvera dans le bundle du navigateur et sera visible par n’importe quel utilisateur (on peut le voir via les DevTools). C’est bien pour une configuration publique (NEXT_PUBLIC_ENV=preview, NEXT_PUBLIC_API_BASE_URL=https://giftgenius.vercel.app), mais absolument pas pour des clés comme OPENAI_API_KEY.

Pour les secrets, nous utilisons des noms sans NEXT_PUBLIC_ et nous ne les lisons que côté serveur : dans les route handlers, les outils MCP, etc.

6. Configurer les variables d’env pour GiftGenius : exemple

Voyons quelles variables d’environnement sont nécessaires à notre GiftGenius pédagogique.

Un ensemble minimal peut ressembler à ceci :

  • OPENAI_API_KEY — clé pour appeler les modèles / le client MCP ;
  • APP_BASE_URL — URL de base de l’application (https://giftgenius.vercel.app ou une URL de preview) ;
  • éventuellement, GIFTDATA_API_URL ou PRODUCTS_API_URL, si vous avez un catalogue externe.

En développement local, cela se trouve dans .env.local :

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

Sur Vercel, allez dans Settings → Environment Variables et ajoutez les mêmes clés et valeurs, mais dans les scopes correspondants.

Exemple de ce à quoi cela ressemble dans le code de l’endpoint MCP :

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

const apiKey = process.env.OPENAI_API_KEY!; // ne faites pas cela sans validations dans un vrai code :)

export async function POST(req: NextRequest) {
  if (!apiKey) {
    return new Response('Missing OPENAI_API_KEY', { status: 500 });
  }
  // Appel à OpenAI ou à un autre service avec apiKey...
}

Le widget peut utiliser APP_BASE_URL côté serveur, par exemple pour construire des liens absolus en tenant compte de l’iframe ChatGPT et de la configuration assetPrefix/basePath du starter.

S’il lui faut une URL publique d’API (par exemple pour window.fetch vers votre backend), on peut créer NEXT_PUBLIC_API_BASE_URL. Mais surtout pas NEXT_PUBLIC_OPENAI_API_KEY.

7. Déploiements Preview : un staging sous stéroïdes

Passons à ce qu’il y a de plus agréable : les déploiements Preview. Une fois que vous avez connecté le dépôt Git, Vercel crée automatiquement un déploiement Preview pour chaque push dans une branche non‑production ou pour chaque Pull Request. Chacun de ces déploiements a une URL unique, par exemple :

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

Ces déploiements utilisent le scope Preview pour les variables d’environnement, ce qui vous permet de définir, par exemple :

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

et de ne pas confondre cela avec la production.

Du point de vue de ChatGPT Dev Mode, une URL de preview est un candidat idéal pour le staging. Dans les paramètres de votre Dev App, vous pouvez temporairement remplacer l’endpoint du tunnel par l’URL de preview et voir comment se comporte la version déjà construite de GiftGenius, mais pas encore en production.

Astuce fréquente : pour une fonctionnalité, vous créez une branche feature/smart-recommendations, vous poussez des changements — Vercel fournit un lien de preview. Vous allez dans Dev Mode, changez l’URL vers ce lien, vérifiez les scénarios avec GPT (sélection de cadeaux, affichage des cartes, appels des outils MCP). Ce n’est que lorsque tout est OK que vous mergez dans main. La production continue, elle, de vivre sa vie tranquille.

Schéma mental du pipeline :

flowchart TD
    A[Dev local
localhost + tunnel] --> B[git push
feature/*] B --> C[Déploiement Preview
preview-URL] C --> D[ChatGPT Dev Mode
App → preview-URL] C --> E[Code review / tests] E --> F[Merge dans main] F --> G[Déploiement Production
prod-URL] G --> H[ChatGPT Prod App
App → prod-URL]

8. Déploiement en production et rollback

Lorsque vous mergez des changements dans main (ou toute autre branche de production que vous avez choisie), Vercel crée un déploiement de production et lui associe l’alias de production : giftgenius.vercel.app ou votre propre domaine.

À ce moment‑là, l’app ChatGPT de prod (que vous créerez un peu plus tard) doit être configurée sur l’URL de production. Dans le Dev Mode, vous continuez d’expérimenter avec le tunnel ou l’URL de preview ; les utilisateurs du ChatGPT Store, eux, utiliseront la production.

L’avantage des déploiements immuables, c’est que le rollback devient très simple. Si la nouvelle release est défaillante (par exemple, un outil MCP plante sur des données réelles), vous n’avez pas besoin de corriger en urgence en prod. Ouvrez la liste des déploiements dans Vercel, choisissez le dernier qui a fonctionné et cliquez sur quelque chose comme « Promote to Production » — quelque part, K8s et Lambda basculent, et votre domaine repointe vers la version stable.

En CLI, cela peut aussi être automatisé via la commande vercel rollback, mais pour notre cours, il suffit de comprendre l’idée : chaque déploiement est un artefact distinct, et l’alias de production peut pointer vers n’importe lequel d’entre eux.

9. Spécificités de Next.js 16 + MCP sur Vercel

Du point de vue de Vercel, votre endpoint MCP dans Next.js est une fonction serverless (ou edge, si vous l’avez configurée ainsi). Elle vit peu longtemps : elle se réveille à la requête, la traite et s’éteint. Il est impossible de conserver de l’état entre les appels, sauf si vous utilisez une base de données externe ou un stockage.

C’est critique pour MCP : si vous décidez de stocker l’historique du dialogue dans un tableau global let history = [] dans route.ts, il sera réinitialisé à chaque cold start. Pour conserver l’état, il faut utiliser un système externe (KV, Postgres, etc.), mais cela viendra dans de futurs modules.

Deuxième aspect — les timeouts d’exécution. Sur les plans gratuits, les fonctions serverless de Vercel ont une limite de temps (au moment de la rédaction — environ 10 secondes sur Hobby, plus sur Pro). Pour des requêtes LLM et surtout pour des chaînes d’outils MCP, cela peut être court.

Dans Next.js 16, pour les route handlers, on peut définir maxDuration afin de demander explicitement à Vercel plus de temps (dans les limites du plan) :

// app/api/mcp/route.ts
export const maxDuration = 60; // secondes, jusqu’à 300 sur Pro

export async function POST(req: Request) {
  // opération longue : requête vers OpenAI, base externe, etc.
}

Ce n’est pas un bouton magique « fais durer autant que tu veux », mais le moyen correct d’indiquer à Vercel : « cette fonction peut tourner plus longtemps, merci de ne pas la tuer trop tôt ».

Enfin, n’oubliez pas les particularités de l’iframe ChatGPT. Dans l’Apps SDK Starter, assetPrefix et basePath sont déjà configurés pour que les assets et les routes fonctionnent correctement dans des iframes imbriquées web-sandbox.oaiusercontent.com. Grâce à cela, toutes les requêtes vont vers votre domaine, pas vers le sandbox. Lors du déploiement sur Vercel, cette configuration est conservée, et vous obtenez ainsi un widget fonctionnel prêt à l’emploi.

10. Intégration avec ChatGPT après le déploiement

Bien que cela relève plutôt des modules sur le Store et la production, la vie d’une application et la logique d’intégration avec ChatGPT après le déploiement sont assez simples et s’intègrent déjà bien ici.

D’abord, vous déployez GiftGenius sur Vercel et obtenez l’URL de production. Ensuite, dans ChatGPT en Dev Mode, vous créez une app séparée, par exemple GiftGenius Prod, et dans ses paramètres, vous mettez en endpoint cette URL (plus précisément, l’endpoint MCP du type https://giftgenius.vercel.app/api/mcp selon le guide OpenAI Apps SDK Deploy).

Pour le développement, vous continuez d’utiliser la Dev App, pointant vers un tunnel ou une URL de preview. Pour tester les builds quotidiens/hebdomadaires, vous pouvez créer une Staging App reliée à un alias de preview stable. Au final, on obtient un schéma en trois niveaux :

Dev App     → tunnel local ou dev-URL (instable)
Staging App → URL de preview/staging stable sur Vercel
Prod App    → URL de production sur Vercel

Pour repère, rassemblons tout dans un tableau :

Quoi URL / déploiement sur Vercel Scope sur Vercel Qui l’utilise
Dev App tunnel local / vercel dev Development vous / équipe
Staging App alias Preview stable Preview équipe / QA
Prod App giftgenius.vercel.app / domaine personnalisé Production utilisateurs

C’est le même modèle local / staging / prod évoqué au début du module, mais désormais relié à Vercel et aux Apps ChatGPT. C’est déjà l’architecture d’un projet mature, et non un localhost éternel.

11. Erreurs courantes lors d’un déploiement sur Vercel

Erreur n° 1 : les secrets ne sont que dans .env.local, mais absents sur Vercel.
Scénario très courant : en local tout fonctionne, vous cliquez en confiance sur « Deploy », l’application se construit, mais les outils MCP en production renvoient 500 avec le texte « Missing OPENAI_API_KEY ». La raison est simple : Vercel ne connaît pas vos .env.local locaux. Il faut saisir séparément les mêmes variables dans les paramètres du projet sur Vercel (et dans les bons scopes : Preview, Production).

Erreur n° 2 : utiliser NEXT_PUBLIC_ pour des données sensibles.
L’envie de « faire marcher vite » l’emporte parfois, et un développeur écrit NEXT_PUBLIC_OPENAI_API_KEY pour accéder à la clé depuis le code client. Résultat : la clé se retrouve dans le bundle JS et accessible à tout utilisateur. Ce n’est pas seulement une mauvaise pratique, c’est la voie directe vers une fuite et un blocage de la clé. Tous les secrets — sans ce préfixe et uniquement côté serveur.

Erreur n° 3 : incohérence des environnements entre le local et Vercel.
En local, vous pouvez avoir une URL pour les produits (http://localhost:4000), sur Vercel — une autre (https://api.gifts-staging.com), et en prod — une troisième. Si vous ne maintenez pas une liste soignée des variables d’environnement et ne vérifiez pas que, en Preview/Production, elles sont correctement renseignées, vous pouvez facilement vous retrouver avec un widget de production qui appelle un backend de staging, et un widget de staging qui appelle la prod. La discipline aide : documenter toutes les variables nécessaires et les vérifier sur chaque environnement.

Erreur n° 4 : ignorer les limites de temps d’exécution pour les endpoints MCP.
En local, vous pouvez attendre la réponse d’un système externe lent 30 secondes sans remarquer de problème. Sur Vercel, la même fonction atteindra un timeout au bout de 10–15 secondes, et ChatGPT verra une erreur. Si vous n’avez pas configuré maxDuration et que vous ne surveillez pas le temps d’exécution des outils MCP, en prod cela se transforme en chutes aléatoires.

Erreur n° 5 : tenter de stocker l’état MCP en mémoire d’une fonction serverless.
Parfois, on veut vraiment mettre l’historique de dialogue ou un cache de recommandations dans une variable globale let cache = {} directement dans le fichier du route handler. En local, tant que le serveur de dev tourne longtemps, cela peut même « marcher ». Mais sur Vercel, chaque fonction serverless vit peu de temps et est souvent recréée. Au final, une partie des requêtes « voit » un ancien cache, d’autres — un nouveau, d’autres encore — un cache vide. Cela engendre des bugs étranges et difficiles à reproduire. Pour l’état, il faut une base externe ou un KV ; au niveau de ce cours, considérez plutôt l’endpoint MCP comme stateless.

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