Frameworks supportés
Frameworks supportés
À chaque déploiement depuis GitHub, le builder clone votre branche et analyse le dépôt pour identifier le framework : il en déduit la commande de build, les artefacts à embarquer dans l'image de production et la commande de démarrage adaptée. Le framework retenu et la commande générée s'affichent dans les logs de build, à l'étape « Détection du framework ».
Cette page est la référence complète : signaux de détection, commandes générées, notes par framework et méthodes de surcharge.
Comment fonctionne la détection
La détection suit un ordre strict, du plus spécifique au plus générique :
- Le mode Dockerfile, s'il est choisi dans les réglages du service : votre Dockerfile fait foi et aucune détection n'est appliquée (voir Surcharger la détection).
- Meta-frameworks (Next.js, Nuxt, SvelteKit, Remix, Astro…), détectés avant leurs briques : un projet Blitz n'est pas confondu avec le Next.js qu'il embarque, un projet Qwik ou Vike n'est pas réduit à sa config Vite.
- Frameworks Python (Django, FastAPI, Flask) et pipelines statiques (Gulp).
- Frameworks backend Node.js (NestJS, Fastify, Koa…). Express est testé en dernier, car il apparaît en dépendance directe de beaucoup d'autres frameworks.
- Génériques par langage : Node.js avec script
start, Laravel, Go, Ruby on Rails, Rust.
Deux types de signaux sont utilisés, dans cet ordre de confiance :
- Les dépendances de
package.json(dependencies+devDependencies). Le signal le plus fiable : beaucoup de frameworks fonctionnent sans fichier de config. - Les fichiers conventionnels :
next.config.*,astro.config.*,go.mod,Cargo.toml,manage.py,artisan…
Résolution de la commande de démarrage (Node.js)
Pour les frameworks Node « bruts » (Express, Koa, Fastify…), la commande de démarrage se résout par ordre de préférence :
- Le script
startde votrepackage.json→npm start. Vous savez mieux que nous comment démarrer votre application. - Le champ
mains'il pointe vers un fichier existant →node <main>. - Les points d'entrée conventionnels du framework présents dans le dépôt (ex.
app.jspour Koa,server.jspour Fastify). - La sortie de build attendue en dernier recours (ex.
dist/main.jspour NestJS : le fichier n'existe pas au clone mais sera produit par le build).
Les frameworks compilés (NestJS, AdonisJS, FoalTS, Marble.js) démarrent directement sur leur sortie de build plutôt que sur leur CLI de développement : boot plus rapide, pas d'outillage de dev requis dans l'image.
Fullstack & SSR
| Framework | Détection | Build | Démarrage généré |
|---|---|---|---|
| Next.js | next ou next.config.* | next build | npm start (next start) |
| Next.js standalone | output: 'standalone' dans la config | next build | node .next/standalone/server.js |
| Blitz.js | blitz | blitz build | npx blitz start |
| Nuxt | nuxt ou nuxt.config.* | nuxt build | node .output/server/index.mjs |
| SvelteKit | @sveltejs/kit ou svelte.config.* | vite build | node build/index.js |
| Remix (classique) | remix.config.* | remix build | npx remix-serve build |
| Remix (Vite) | @remix-run/* sans remix.config | vite build | npx remix-serve build/server/index.js |
| Astro (SSR) | astro + un adapter dans la config | astro build | node ./dist/server/entry.mjs |
| Astro (statique) | astro sans adapter | astro build | npx serve dist |
| RedwoodJS | @redwoodjs/* ou redwood.toml | npx rw build | npx rw serve --port $PORT |
| SolidStart | @solidjs/start | vinxi build | node .output/server/index.mjs |
| Qwik City (SSR) | @builder.io/qwik-city + src/entry.express.tsx | qwik build | node server/entry.express.js |
| Qwik City (statique) | @builder.io/qwik-city sans adapter Express | qwik build | npx serve dist |
| Gatsby | gatsby ou gatsby-config.* | gatsby build | npx serve public |
| Vike | vike | vite build | serveur custom (npm start prioritaire) |
| Fresh (Deno) | deno.json | Aucun | deno run -A main.ts |
Notes par framework
- Next.js : le mode standalone est détecté automatiquement (
output: 'standalone'dansnext.config.*) : l'image finale n'embarque que.next/standalone,.next/staticetpublic. Voir aussi le guide Next.js. - Nuxt / SolidStart : les deux produisent une sortie Nitro, et seul le dossier
.outputest gardé dans l'image finale. - SvelteKit : la commande générée suppose adapter-node (
@sveltejs/adapter-node), qui produitbuild/index.js. Les adapters serverless (Vercel, Netlify…) ne produisent pas de serveur autonome. - Remix : les deux ères sont gérées : compilateur classique (
remix.config.*présent) et plugin Vite (dépendance@remix-run/*seule). - Astro : SSR si un
adapterfigure dansastro.config.*(utilisez@astrojs/node), sinon le site est servi statiquement depuisdist/. - Qwik City : lancez
npx qwik add expresspour le SSR. La présence desrc/entry.express.tsxdéclenche le mode serveur ; sinon la sortiedist/est servie statiquement. - RedwoodJS : build et serve passent par la CLI
rw, qui gère le monorepo api + web. - Vike : Vike suppose un serveur custom. Définissez un script
startdans votrepackage.json; à défaut, le builder chercheserver/index.js,server.jspuisindex.js. - Fresh / Deno : runtime différent. Le builder auto utilise l'image Deno officielle : il lance la tâche
startde votredeno.jsonsi elle existe, sinon le premier fichier d'entrée trouvé (main.ts,server.ts…).
Backend Node.js
| Framework | Clé package.json | Démarrage généré |
|---|---|---|
| Express | express | npm start › main › index.js, server.js, app.js, src/* |
| Fastify | fastify | npm start › main › server.js, app.js, index.js, src/* |
| NestJS | @nestjs/core | node dist/main.js |
| Koa | koa | npm start › main › app.js, index.js, server.js, src/* |
| Hapi | @hapi/hapi (ou hapi) | npm start › main › server.js, index.js, src/* |
| Sails | sails | npm start › main › app.js |
| AdonisJS v6 | @adonisjs/core + adonisrc.ts | node build/bin/server.js |
| AdonisJS v5 | @adonisjs/core | node build/server.js |
| LoopBack 4 | @loopback/core | npm start, sinon node . |
| FeathersJS | @feathersjs/* | npm start › main › src/index.js, lib/index.js, dist/index.js |
| Restify | restify | npm start › main › server.js, index.js, src/* |
| Egg.js | egg | npx egg-scripts start --port $PORT |
| Total.js | total.js (ou total4/total5) | npm start › main › index.js, debug.js |
| FoalTS | @foal/core | npm start, sinon node build/index.js |
| Marble.js | @marblejs/core | npm start, sinon node dist/main.js |
| Moleculer | moleculer | npm start, sinon npx moleculer-runner services |
| Seneca | seneca | npm start › main › index.js, server.js, app.js |
| Node.js générique | script start présent | npm start |
La notation npm start › main › fichiers… désigne l'ordre de résolution décrit plus haut.
Notes par framework
- NestJS :
nest startrecompile au boot et exige la CLI Nest. Le builder lance directementdist/main.js, produit parnpm run build(nest build). Vérifiez que votre scriptbuildexiste. - AdonisJS : la version est déduite de la présence d'
adonisrc.ts(v6). Les chemins de sortie diffèrent entre v5 et v6. - Egg.js :
egg-scriptstourne en avant-plan (pas de--daemon). Dans un conteneur, le process principal est l'application. - Moleculer : sans script
start, le runner charge les services depuis le dossierservices/. - LoopBack 4 :
node .suit le champmain(généralementdist/index.js, produit par le build TypeScript).
Frontend statique
| Outil | Détection | Build | Démarrage généré |
|---|---|---|---|
| Vite (React, Vue, vanilla…) | vite.config.* | vite build | npx serve dist -p $PORT |
| Gulp | gulpfile.* | npx gulp | npx serve <sortie> -p $PORT |
| Gatsby | gatsby | gatsby build | npx serve public -p $PORT |
Pour Gulp, le dossier de sortie est extrait du premier appel dest() du gulpfile ; à défaut, dist/, www/ puis build/ sont essayés. Seul le dossier de sortie est embarqué dans l'image finale.
La nature « Site statique »
Le tableau ci-dessus décrit la détection automatique, qui suppose un projet Node. Quand vous choisissez la nature Site statique à la création du service (ou depuis ses Paramètres), le build ne passe plus par la détection automatique : l'image produite est un Nginx qui sert vos fichiers.
- Dépôt de fichiers HTML/CSS/JS : le dossier contenant
index.htmlest publié tel quel (racine, puispublic,dist,build,site,_site,www). - Dépôt avec un script
build: il est exécuté, et seule sa sortie est embarquée (dist,build,out,_site,.output/public,public,www). - Nginx écoute sur le port du service, sert les URL sans extension (
/a-propos→a-propos.html) et retombe surindex.htmlpour les routeurs côté client. - Aucun dépôt sous la main ? Le template Site statique déploie le même Nginx avec un dossier persistant, éditable depuis l'onglet Fichiers.
Autres runtimes
| Framework | Détection | Démarrage généré |
|---|---|---|
| Django | manage.py + django dans les requirements | gunicorn <app>.wsgi:application --bind 0.0.0.0:$PORT |
| FastAPI | fastapi dans requirements.txt | uvicorn main:app --host 0.0.0.0 --port $PORT |
| Flask | flask dans requirements.txt | gunicorn app:app --bind 0.0.0.0:$PORT |
| Laravel | artisan | php artisan serve --host=0.0.0.0 --port=$PORT |
| Ruby on Rails | rails dans le Gemfile | bundle exec rails server -b 0.0.0.0 -p $PORT |
| Go | go.mod | ./<binaire> (nom du module) |
| Rust | Cargo.toml | ./target/release/<binaire> (nom du crate) |
| Deno | deno.json / deno.jsonc | deno run -A main.ts |
Les guides dédiés Python, PHP et Go détaillent les variables d'environnement propres à chaque runtime.
Le port : la seule convention exigée
Quel que soit le framework, votre application doit lire la variable d'environnement PORT et écouter sur 0.0.0.0, et non sur localhost ni sur un port codé en dur. C'est la cause n°1 des déploiements qui buildent mais ne répondent pas.
// Node.js — valable pour tous les frameworks
const port = process.env.PORT || 3000;
app.listen(port, "0.0.0.0");
Surcharger la détection
Trois mécanismes, du plus léger au plus complet :
1. Commande de démarrage personnalisée
Depuis le dashboard, remplacez la commande générée sans toucher au dépôt (voir Commande de démarrage personnalisée).
2. Procfile
Une ligne web: <commande> dans un Procfile à la racine de votre dépôt remplace la commande de démarrage détectée. Elle vaut pour tous les langages, sauf les projets Node, qui passent par la commande de démarrage du dashboard.
web: gunicorn monapp.wsgi --bind 0.0.0.0:$PORT
3. Mode Dockerfile
Dans les réglages du service, changez le type de build :
- Dockerfile : votre dépôt pilote entièrement le build, sans détection et selon vos règles (voir Docker).
Gestionnaire de paquets
Le builder normalise tout projet Node sur npm au moment du build : c'est le seul gestionnaire garanti présent dans toutes les images de base. Dans la copie clonée du dépôt :
- les lockfiles
bun.lock,bun.lockb,pnpm-lock.yaml,yarn.locketpackage-lock.jsonsont supprimés : les dépendances sont réinstallées proprement vianpm install; - le champ
packageManager(corepack) et les entréesengines.pnpm/engines.yarn/engines.bunsont retirés dupackage.json; - les configs propres à un autre gestionnaire (
pnpm-workspace.yaml,.yarnrc.yml,.yarn/,bunfig.toml…) sont supprimées ; - les scripts qui appellent un autre gestionnaire sont réécrits (
pnpm run build→npm run build,bunx prisma→npx prisma,yarn dlx→npx…), et la gardeonly-allow, dont le rôle est de faire échouernpm install, est retirée.
Votre dépôt reste inchangé : seule la copie utilisée pour construire l'image est modifiée. Un lockfile désynchronisé ne peut donc jamais faire échouer un déploiement.
Ce qui n'a pas d'équivalent npm (pnpm --filter, yarn workspace, bun run app.ts) est laissé tel quel et signalé dans les logs de build, à l'étape « Gestionnaire de paquets ». Ces commandes échoueront : adaptez le script dans votre dépôt, ou passez en mode Dockerfile pour piloter vous-même l'installation.
Dépannage
- Mauvais framework détecté : vérifiez les logs de build (étape « Détection du framework »). Le cas typique est une dépendance résiduelle dans
package.json(ex.expressdans un projet migré). Nettoyez la dépendance ou passez en mode Dockerfile. - Build OK mais le service ne répond pas : presque toujours le port. Vérifiez aussi que votre commande de démarrage n'écoute pas en
localhost. Cannot find module 'dist/main.js'au boot d'un framework compilé : votre scriptbuildne produit pas la sortie attendue. Alignez la sortie de build ou définissez un scriptstart.- Framework absent de cette liste : Le builder auto tente une détection générique par langage. Si elle échoue, ajoutez un
Procfileou passez en mode Dockerfile, et dites-nous quel framework vous manque sur le Discord (fenèstra novèla).