# Frameworks soportados

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

# Frameworks soportados

En cada despliegue desde GitHub, el builder clona tu rama y analiza el repositorio para identificar el framework: deduce de ahí el comando de build, los artefactos a incluir en la imagen de producción y el **comando de inicio adaptado**. El framework elegido y el comando generado se muestran en los logs de build, en el paso «Detección del framework».

Esta página es la referencia completa: señales de detección, comandos generados, notas por framework y métodos de sobrescritura.

## Cómo funciona la detección

La detección sigue un orden estricto, de lo más específico a lo más genérico:

1. **El modo Dockerfile**, si lo eliges en los ajustes del servicio: tu Dockerfile es la autoridad y no se aplica ninguna detección (ver [Sobrescribir la detección](#sobrescribir-la-detección)).
2. **Meta-frameworks** (Next.js, Nuxt, SvelteKit, Remix, Astro…), detectados antes que sus piezas base: un proyecto Blitz no se confunde con el Next.js que incluye, un proyecto Qwik o Vike no se reduce a su configuración de Vite.
3. **Frameworks Python** (Django, FastAPI, Flask) y **pipelines estáticos** (Gulp).
4. **Frameworks backend Node.js** (NestJS, Fastify, Koa…). Express se prueba en último lugar, porque aparece como dependencia directa de muchos otros frameworks.
5. **Genéricos por lenguaje**: Node.js con script `start`, Laravel, Go, Ruby on Rails, Rust.

Se usan dos tipos de señales, en este orden de confianza:

- **Las dependencias de `package.json`** (`dependencies` + `devDependencies`). La señal más fiable: muchos frameworks funcionan sin archivo de configuración.
- **Los archivos convencionales**: `next.config.*`, `astro.config.*`, `go.mod`, `Cargo.toml`, `manage.py`, `artisan`…

## Resolución del comando de inicio (Node.js)

Para los frameworks Node "puros" (Express, Koa, Fastify…), el comando de inicio se resuelve por orden de preferencia:

1. **El script `start` de tu `package.json`** → `npm start`. Tú sabes mejor que nosotros cómo iniciar tu aplicación.
2. **El campo `main`** si apunta a un archivo existente → `node <main>`.
3. **Los puntos de entrada convencionales del framework** presentes en el repositorio (ej. `app.js` para Koa, `server.js` para Fastify).
4. **La salida de build esperada** como último recurso (ej. `dist/main.js` para NestJS: el archivo no existe al clonar pero será producido por el build).

Los frameworks **compilados** (NestJS, AdonisJS, FoalTS, Marble.js) arrancan directamente desde su salida de build en lugar de su CLI de desarrollo: boot más rápido, sin herramientas de desarrollo necesarias en la imagen.

## Fullstack y SSR

| Framework | Detección | Build | Inicio generado |
|-----------|-----------|-------|------------------|
| Next.js | `next` o `next.config.*` | `next build` | `npm start` (`next start`) |
| Next.js standalone | `output: 'standalone'` en la config | `next build` | `node .next/standalone/server.js` |
| Blitz.js | `blitz` | `blitz build` | `npx blitz start` |
| Nuxt | `nuxt` o `nuxt.config.*` | `nuxt build` | `node .output/server/index.mjs` |
| SvelteKit | `@sveltejs/kit` o `svelte.config.*` | `vite build` | `node build/index.js` |
| Remix (clásico) | `remix.config.*` | `remix build` | `npx remix-serve build` |
| Remix (Vite) | `@remix-run/*` sin `remix.config` | `vite build` | `npx remix-serve build/server/index.js` |
| Astro (SSR) | `astro` + un `adapter` en la config | `astro build` | `node ./dist/server/entry.mjs` |
| Astro (estático) | `astro` sin adapter | `astro build` | `npx serve dist` |
| RedwoodJS | `@redwoodjs/*` o `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 (estático) | `@builder.io/qwik-city` sin adapter Express | `qwik build` | `npx serve dist` |
| Gatsby | `gatsby` o `gatsby-config.*` | `gatsby build` | `npx serve public` |
| Vike | `vike` | `vite build` | servidor custom (`npm start` prioritario) |
| Fresh (Deno) | `deno.json` | Ninguno | `deno run -A main.ts` |

### Notas por framework

- **Next.js**: el modo standalone se detecta automáticamente (`output: 'standalone'` en `next.config.*`): la imagen final solo incluye `.next/standalone`, `.next/static` y `public`. Ver también la guía [Next.js](/docs/web-nextjs).
- **Nuxt / SolidStart**: ambos producen una salida Nitro, y solo se conserva la carpeta `.output` en la imagen final.
- **SvelteKit**: el comando generado asume **adapter-node** (`@sveltejs/adapter-node`), que produce `build/index.js`. Los adapters serverless (Vercel, Netlify…) no producen un servidor autónomo.
- **Remix**: se gestionan ambas eras: compilador clásico (`remix.config.*` presente) y plugin Vite (dependencia `@remix-run/*` sola).
- **Astro**: SSR si un `adapter` figura en `astro.config.*` (usa `@astrojs/node`), si no el sitio se sirve estáticamente desde `dist/`.
- **Qwik City**: ejecuta `npx qwik add express` para el SSR. La presencia de `src/entry.express.tsx` activa el modo servidor; si no, la salida `dist/` se sirve estáticamente.
- **RedwoodJS**: build y serve pasan por la CLI `rw`, que gestiona el monorepo api + web.
- **Vike**: Vike asume un servidor custom. Define un script `start` en tu `package.json`; si no, el builder busca `server/index.js`, `server.js` y luego `index.js`.
- **Fresh / Deno**: runtime diferente. El builder automático usa la imagen oficial de Deno: lanza la tarea `start` de tu `deno.json` si existe y, si no, el primer archivo de entrada que encuentra (`main.ts`, `server.ts`…).

## Backend Node.js

| Framework | Clave `package.json` | Inicio generado |
|-----------|--------------------|------------------|
| 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` (o `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`, si no `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` (o `total4`/`total5`) | `npm start` › `main` › `index.js`, `debug.js` |
| FoalTS | `@foal/core` | `npm start`, si no `node build/index.js` |
| Marble.js | `@marblejs/core` | `npm start`, si no `node dist/main.js` |
| Moleculer | `moleculer` | `npm start`, si no `npx moleculer-runner services` |
| Seneca | `seneca` | `npm start` › `main` › `index.js`, `server.js`, `app.js` |
| Node.js genérico | script `start` presente | `npm start` |

La notación `npm start › main › archivos…` designa el [orden de resolución](#resolución-del-comando-de-inicio-nodejs) descrito arriba.

### Notas por framework

- **NestJS**: `nest start` recompila al arrancar y exige la CLI de Nest. El builder ejecuta directamente `dist/main.js`, producido por `npm run build` (`nest build`). Verifica que tu script `build` exista.
- **AdonisJS**: la versión se deduce de la presencia de `adonisrc.ts` (v6). Las rutas de salida difieren entre v5 y v6.
- **Egg.js**: `egg-scripts` corre en primer plano (sin `--daemon`). En un contenedor, el proceso principal *es* la aplicación.
- **Moleculer**: sin script `start`, el runner carga los servicios desde la carpeta `services/`.
- **LoopBack 4**: `node .` sigue el campo `main` (generalmente `dist/index.js`, producido por el build de TypeScript).

## Frontend estático

| Herramienta | Detección | Build | Inicio generado |
|-------|-----------|-------|------------------|
| Vite (React, Vue, vanilla…) | `vite.config.*` | `vite build` | `npx serve dist -p $PORT` |
| Gulp | `gulpfile.*` | `npx gulp` | `npx serve <salida> -p $PORT` |
| Gatsby | `gatsby` | `gatsby build` | `npx serve public -p $PORT` |

Para Gulp, la carpeta de salida se extrae de la primera llamada `dest()` del gulpfile; si no, se prueban `dist/`, `www/` y luego `build/`. Solo la carpeta de salida se incluye en la imagen final.

### La naturaleza «Sitio estático»

La tabla anterior describe la detección automática, que da por hecho un proyecto Node. Cuando eliges la naturaleza **Sitio estático** al crear el servicio (o más tarde en sus **Ajustes**), la compilación ya no pasa por la detección automática: la imagen producida es un **Nginx** que sirve tus archivos.

- Repositorio de archivos HTML/CSS/JS: se publica tal cual la carpeta que contiene `index.html` (raíz, luego `public`, `dist`, `build`, `site`, `_site`, `www`).
- Repositorio con script `build`: se ejecuta y solo se incluye su salida (`dist`, `build`, `out`, `_site`, `.output/public`, `public`, `www`).
- Nginx escucha en el puerto del servicio, sirve URL sin extensión (`/sobre-mi` → `sobre-mi.html`) y recurre a `index.html` para los enrutadores del lado del cliente.
- ¿Sin repositorio a mano? La plantilla [Sitio estático](/docs/templates-catalogue) despliega el mismo Nginx con una carpeta persistente, editable desde la pestaña **Archivos**.

## Otros runtimes

| Framework | Detección | Inicio generado |
|-----------|-----------|------------------|
| Django | `manage.py` + `django` en los requirements | `gunicorn <app>.wsgi:application --bind 0.0.0.0:$PORT` |
| FastAPI | `fastapi` en `requirements.txt` | `uvicorn main:app --host 0.0.0.0 --port $PORT` |
| Flask | `flask` en `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` en el `Gemfile` | `bundle exec rails server -b 0.0.0.0 -p $PORT` |
| Go | `go.mod` | `./<binario>` (nombre del módulo) |
| Rust | `Cargo.toml` | `./target/release/<binario>` (nombre del crate) |
| Deno | `deno.json` / `deno.jsonc` | `deno run -A main.ts` |

Las guías dedicadas [Python](/docs/web-python), [PHP](/docs/web-php) y [Go](/docs/web-go) detallan las variables de entorno propias de cada runtime.

## El puerto: la única convención exigida

Sea cual sea el framework, tu aplicación debe **leer la variable de entorno `PORT`** y **escuchar en `0.0.0.0`**, nunca en `localhost` ni en un puerto fijo. Es la causa número uno de despliegues que compilan pero no responden.

```js
// Node.js — válido para todos los frameworks
const port = process.env.PORT || 3000;
app.listen(port, "0.0.0.0");
```

## Sobrescribir la detección

Tres mecanismos, del más ligero al más completo:

### 1. Comando de inicio personalizado

Desde el dashboard, reemplaza el comando generado sin tocar el repositorio (ver [Comando de inicio personalizado](/docs/commande-demarrage)).

### 2. `Procfile`

Una línea `web: <comando>` en un `Procfile` en la raíz de tu repositorio sustituye el comando de inicio detectado. Vale para todos los lenguajes salvo los proyectos Node, que usan el comando de inicio del dashboard.

```text
web: gunicorn miapp.wsgi --bind 0.0.0.0:$PORT
```

### 3. Modo Dockerfile

En la configuración del servicio, cambia el tipo de build:

- **Dockerfile**: tu repositorio controla íntegramente el build, sin detección y con tus propias reglas (ver [Docker](/docs/docker)).

## Gestor de paquetes

El builder **normaliza todo proyecto Node a npm** en el momento del build: es el único gestor garantizado en todas las imágenes base. En la copia clonada del repositorio:

- los lockfiles `bun.lock`, `bun.lockb`, `pnpm-lock.yaml`, `yarn.lock` y `package-lock.json` se eliminan: las dependencias se reinstalan limpiamente mediante `npm install`;
- el campo `packageManager` (corepack) y las entradas `engines.pnpm` / `engines.yarn` / `engines.bun` se quitan del `package.json`;
- las configuraciones propias de otro gestor (`pnpm-workspace.yaml`, `.yarnrc.yml`, `.yarn/`, `bunfig.toml`…) se eliminan;
- los scripts que invocan otro gestor se reescriben (`pnpm run build` → `npm run build`, `bunx prisma` → `npx prisma`, `yarn dlx` → `npx`…), y la guarda `only-allow`, cuyo propósito es precisamente hacer fallar `npm install`, se retira.

Tu repositorio queda inalterado: solo se modifica la copia usada para construir la imagen. Un lockfile desincronizado nunca puede, por tanto, hacer fallar un despliegue.

Lo que no tiene equivalente en npm (`pnpm --filter`, `yarn workspace`, `bun run app.ts`) se deja tal cual y se señala en los logs de build, en el paso «Gestor de paquetes». Esos comandos fallarán: adapta el script en tu repositorio, o cambia al modo Dockerfile para controlar tú mismo la instalación.

## Solución de problemas

- **Framework mal detectado**: revisa los logs de build (paso «Detección del framework»). El caso típico es una dependencia residual en `package.json` (ej. `express` en un proyecto migrado). Elimina la dependencia o pasa al modo Dockerfile.
- **Build correcto pero el servicio no responde**: casi siempre es el [puerto](#el-puerto-la-única-convención-exigida). Verifica también que tu comando de inicio no escuche en `localhost`.
- **`Cannot find module 'dist/main.js'`** al arrancar un framework compilado: tu script `build` no produce la salida esperada. Alinea la salida de build o define un script `start`.
- **Framework ausente de esta lista**: El builder automático intenta una detección genérica por lenguaje. Si falla, añade un `Procfile` o pasa al modo Dockerfile, y dinos qué framework te falta en el [Discord](https://discord.webgune.cloud/).
