# Frameworks supportés

Source : https://webgune.cloud/fr-fr/docs/frameworks-supportes · Mis à jour le 2026-10-27

# 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 :

1. **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](#surcharger-la-détection)).
2. **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.
3. **Frameworks Python** (Django, FastAPI, Flask) et **pipelines statiques** (Gulp).
4. **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.
5. **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 :

1. **Le script `start` de votre `package.json`** → `npm start`. Vous savez mieux que nous comment démarrer votre application.
2. **Le champ `main`** s'il pointe vers un fichier existant → `node <main>`.
3. **Les points d'entrée conventionnels du framework** présents dans le dépôt (ex. `app.js` pour Koa, `server.js` pour Fastify).
4. **La sortie de build attendue** en dernier recours (ex. `dist/main.js` pour 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'` dans `next.config.*`) : l'image finale n'embarque que `.next/standalone`, `.next/static` et `public`. Voir aussi le guide [Next.js](/docs/web-nextjs).
- **Nuxt / SolidStart** : les deux produisent une sortie Nitro, et seul le dossier `.output` est gardé dans l'image finale.
- **SvelteKit** : la commande générée suppose **adapter-node** (`@sveltejs/adapter-node`), qui produit `build/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 `adapter` figure dans `astro.config.*` (utilisez `@astrojs/node`), sinon le site est servi statiquement depuis `dist/`.
- **Qwik City** : lancez `npx qwik add express` pour le SSR. La présence de `src/entry.express.tsx` déclenche le mode serveur ; sinon la sortie `dist/` 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 `start` dans votre `package.json` ; à défaut, le builder cherche `server/index.js`, `server.js` puis `index.js`.
- **Fresh / Deno** : runtime différent. Le builder auto utilise l'image Deno officielle : il lance la tâche `start` de votre `deno.json` si 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](#résolution-de-la-commande-de-démarrage-nodejs) décrit plus haut.

### Notes par framework

- **NestJS** : `nest start` recompile au boot et exige la CLI Nest. Le builder lance directement `dist/main.js`, produit par `npm run build` (`nest build`). Vérifiez que votre script `build` existe.
- **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-scripts` tourne 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 dossier `services/`.
- **LoopBack 4** : `node .` suit le champ `main` (généralement `dist/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.html` est publié tel quel (racine, puis `public`, `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 sur `index.html` pour les routeurs côté client.
- Aucun dépôt sous la main ? Le template [Site statique](/docs/templates-catalogue) 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](/docs/web-python), [PHP](/docs/web-php) et [Go](/docs/web-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.

```js
// 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](/docs/commande-demarrage)).

### 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.

```text
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](/docs/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.lock` et `package-lock.json` sont supprimés : les dépendances sont réinstallées proprement via `npm install` ;
- le champ `packageManager` (corepack) et les entrées `engines.pnpm` / `engines.yarn` / `engines.bun` sont retirés du `package.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 garde `only-allow`, dont le rôle est de faire échouer `npm 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. `express` dans 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](#le-port--la-seule-convention-exigée). 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 script `build` ne produit pas la sortie attendue. Alignez la sortie de build ou définissez un script `start`.
- **Framework absent de cette liste** : Le builder auto tente une détection générique par langage. Si elle échoue, ajoutez un `Procfile` ou passez en mode Dockerfile, et dites-nous quel framework vous manque sur le [Discord](https://discord.webgune.cloud/).
