Frameworks
Bastide recognises most web applications without a configuration file: it detects the framework, composes the image and serves it. This page says which frameworks are supported and at what commitment, how detection works, when to supply your own Dockerfile, the runtime contract your application must honour, and how to declare several services in one project.
Three support tiers
| Tier | Commitment | Frameworks | Recognised today |
|---|---|---|---|
| A, sold | Template written and maintained by Glowsoft, conformance suite on every version, published pass rate, blocking regressions. | Next.js (16.2 and later), Nuxt 4, SvelteKit 2, Astro 5, React Router 7 / Remix, Vite (single-page app), static export, generic Node (Express, Fastify, Hono, NestJS) | yes |
| B, supported | Template written, integration tests, fixes within 30 days, no feature-parity commitment. | Python ASGI and WSGI (FastAPI, Django, Flask), Go, static site generators (Hugo, Docusaurus, VitePress), PHP 8.3 and later (Symfony, Laravel) | partly: Python and Go |
| C, best effort | General-purpose fallback (Railpack), no commitment, a warning at detection. | Ruby, Rust, Bun, Deno, Java | no |
The published matrix, with each tier A framework's pass rate and the conditions of its measurement, is generated from the code: it is the authority. Tier B static site generators and PHP are not yet recognised. In tier C, only a Deno repository has been measured through the fallback; Ruby, Rust, Bun and Java have not yet.
Next.js
- From 16.2, the application goes through the Bastide adapter: standalone server, immutable assets served separately, deployment manifest.
- Before 16.2, it is assembled by OpenNext; if assembly fails, it is served as a Node application (
next start). Under OpenNext,revalidateTagonly applies to the instance that calls it. - There is no edge isolate runtime: middleware and
runtime = 'edge'routes run in the container's Node runtime.
Detection
On every build, the platform reads the files at the build root (the « Racine du projet » setting, or the repository root) without running any repository script. It tries detectors from the most specific to the most general: a Next.js project contains React, an Astro project contains Vite, and the order avoids a plan that would almost work. The detected framework, the build stage and the plan's hash can be read in buildPlan from deployment_read, and under « Détails techniques » on the Déploiement screen.
The image is built at one of three stages, in this order:
- **Your
Dockerfile**, if it sits at the build root: it is built as is. - The image composed by the platform, from the detected framework.
- The general-purpose fallback, for a repository no detector recognises.
Runtime versions
| Runtime | Versions served | Default | Read from |
|---|---|---|---|
| Node | 20, 22, 24 | 22 | engines.node in package.json |
| Python | 3.11, 3.12, 3.13 | 3.12 | .python-version, then requires-python in pyproject.toml |
| Go | 1.22, 1.23, 1.24 | 1.23 | the go line of go.mod |
For Node, any form naming a single major version is recognised: 20, 20.x, ^20.0.0, ~20.11, 20.11.1 all give Node 20. An open range (>=20) is not, and the default applies. A project that declares nothing keeps the version it received at creation: no major upgrade happens without your action. If that version leaves the catalogue, the build is refused rather than silently upgraded.
The package manager (pnpm, yarn, npm or bun) is inferred from the repository. For pnpm and modern yarn, the version is the one packageManager declares.
Supply your own Dockerfile
A Dockerfile at the build root is used as is, without rewriting: the platform builds it or refuses it, never anything in between. A refusal quotes the line number, the instruction and the reason. The policy is an allow-list:
- Allowed instructions:
FROM,ARG,RUN,COPY,ADD,CMD,ENTRYPOINT,ENV,EXPOSE,WORKDIR,USER,LABEL,SHELL,STOPSIGNAL,HEALTHCHECK,MAINTAINER.VOLUMEandONBUILDare refused. # syntax=and# escape=directives are refused; heredoc blocks are not built (a multi-line command with\is still allowed).FROM --platform: onlylinux/amd64,$BUILDPLATFORMor$TARGETPLATFORM.RUN --network: onlynone.RUN --mount: onlytmpfsandbind;cache,secretandsshare refused.- Base images pulled from
docker.io,ghcr.io,gcr.io,mcr.microsoft.com,quay.io,public.ecr.awsorregistry.k8s.io. The project's « Registres d'images admis » (allowed image registries) setting narrows this list. - 256 KiB, 4,000 lines and 32 KiB per logical line at most; valid UTF-8.
- The image must declare
CMDorENTRYPOINT, target Linux, and not declare/as a volume.
With your Dockerfile, the platform does not guess the port: declare it with port in glowsoft.json. Without a declaration it takes 3000, and says so in the deployment event.
The platform adds nothing to your file: no ENV PORT, no probe, no user. The runtime constraints below do apply to every container, though: build an image that works under a non-root user and on a read-only root.
The runtime contract
Every image, composed or supplied, must honour this contract.
| Requirement | Detail |
|---|---|
Listen on PORT | The platform sets the PORT variable. The composed image sets it to 3000 (8080 for a static site); with a declared probe, PORT equals the probed port. Do not hard-code a port. |
| Start on its own | A CMD or an ENTRYPOINT. NODE_ENV and PORT are provided by the platform. |
Stop on SIGTERM | On shutdown, the container receives SIGTERM and has 30 seconds to finish its requests before being killed. A STOPSIGNAL may choose SIGQUIT, SIGWINCH, SIGINT, SIGHUP, SIGUSR1 or SIGUSR2, written by name. |
Write only under /tmp | Every container runs as UID 10000, with a read-only root, /tmp in memory and no Linux capabilities, including with your Dockerfile. |
The health probe
There is no default probe. Without a declared probe, « En ligne » (live) means "the container is running". For a deployment to switch only once the application answers, declare one in glowsoft.json:
{
"version": 1,
"probe": { "path": "/sante", "startupBudgetSeconds": 120 }
}
path is the path the platform queries over HTTP on the application's port; it starts with / and carries no spaces or metacharacters. The path is yours to choose: /sante, /health, /api/ping. The probe expects a success response, polls every ten seconds with a two-second timeout, and the start-up budget ranges from 60 to 180 seconds (60 by default). Beyond it, the deployment fails and the old one keeps serving.
Several services per project
By default a project has a single, unnamed web service. services in glowsoft.json declares several, which share the same image and reach each other by name on the project's private network.
| Kind | What it does |
|---|---|
web | Listens, and receives the project address's traffic. Exactly one per declaration. |
worker | Does not listen; starts with <package manager> run <start>, where start is the name of a package.json script, never a command. |
statique | Serves the files of a directory produced by the build (directory), on the private network only. |
cron | One container per run, on the declared schedule: see Scheduled tasks. |
{
"version": 1,
"services": [
{ "name": "web", "type": "web" },
{ "name": "worker", "type": "worker", "start": "start:worker" }
]
}
A service name starts with a lowercase letter, followed by up to thirty letters, digits or hyphens, and two services cannot share a name. A worker is only started when the platform composes the Node image itself: not with a supplied Dockerfile, a static export, Python, Go or the fallback.
| Tier | Services per project |
|---|---|
| Découverte | 1 |
| Standard | 10 |
| Pro | 25 |
| Souverain | negotiated |
The number of production service instances (1 to 10) is set in the project's Réglages (Settings). The console does not yet list a release's services.
Common errors
| Code | Remedy |
|---|---|
framework_not_detected | Neither a detector nor the fallback produced a plan. Supply a Dockerfile, or fix the « Racine du projet ». |
build_version_gelee_indisponible | The project's frozen version has left the catalogue: declare a served version in the repository (engines.node for Node). |
image_sans_demarrage | Add CMD or ENTRYPOINT to the Dockerfile. |
image_signal_darret | Use only a signal from the served list. |
service_hors_gabarit_node | A worker requires the Node image composed by the platform. |
declaration_refusee | More services than the tier allows, or an invalid glowsoft.json. |
A deployment that stays in « Mise en service » (going live) and then fails on the probe most often comes from an application that does not listen on PORT, or a Dockerfile whose port is not declared.
See also: Builds, Git and automatic deployment, Deploy, Scheduled tasks, Environments and variables.