Frameworks soportados
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:
- 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).
- 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.
- Frameworks Python (Django, FastAPI, Flask) y pipelines estáticos (Gulp).
- Frameworks backend Node.js (NestJS, Fastify, Koa…). Express se prueba en último lugar, porque aparece como dependencia directa de muchos otros frameworks.
- 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:
- El script
startde tupackage.json→npm start. Tú sabes mejor que nosotros cómo iniciar tu aplicación. - El campo
mainsi apunta a un archivo existente →node <main>. - Los puntos de entrada convencionales del framework presentes en el repositorio (ej.
app.jspara Koa,server.jspara Fastify). - La salida de build esperada como último recurso (ej.
dist/main.jspara 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'ennext.config.*): la imagen final solo incluye.next/standalone,.next/staticypublic. Ver también la guía Next.js. - Nuxt / SolidStart: ambos producen una salida Nitro, y solo se conserva la carpeta
.outputen la imagen final. - SvelteKit: el comando generado asume adapter-node (
@sveltejs/adapter-node), que producebuild/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
adapterfigura enastro.config.*(usa@astrojs/node), si no el sitio se sirve estáticamente desdedist/. - Qwik City: ejecuta
npx qwik add expresspara el SSR. La presencia desrc/entry.express.tsxactiva el modo servidor; si no, la salidadist/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
starten tupackage.json; si no, el builder buscaserver/index.js,server.jsy luegoindex.js. - Fresh / Deno: runtime diferente. El builder automático usa la imagen oficial de Deno: lanza la tarea
startde tudeno.jsonsi 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 descrito arriba.
Notas por framework
- NestJS:
nest startrecompila al arrancar y exige la CLI de Nest. El builder ejecuta directamentedist/main.js, producido pornpm run build(nest build). Verifica que tu scriptbuildexista. - 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-scriptscorre 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 carpetaservices/. - LoopBack 4:
node .sigue el campomain(generalmentedist/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, luegopublic,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 aindex.htmlpara los enrutadores del lado del cliente. - ¿Sin repositorio a mano? La plantilla Sitio estático 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, PHP y 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.
// 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).
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.
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).
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.lockypackage-lock.jsonse eliminan: las dependencias se reinstalan limpiamente mediantenpm install; - el campo
packageManager(corepack) y las entradasengines.pnpm/engines.yarn/engines.bunse quitan delpackage.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 guardaonly-allow, cuyo propósito es precisamente hacer fallarnpm 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.expressen un proyecto migrado). Elimina la dependencia o pasa al modo Dockerfile. - Build correcto pero el servicio no responde: casi siempre es el puerto. Verifica también que tu comando de inicio no escuche en
localhost. Cannot find module 'dist/main.js'al arrancar un framework compilado: tu scriptbuildno produce la salida esperada. Alinea la salida de build o define un scriptstart.- Framework ausente de esta lista: El builder automático intenta una detección genérica por lenguaje. Si falla, añade un
Procfileo pasa al modo Dockerfile, y dinos qué framework te falta en el Discord (nueva ventana).