Deploy from source code
Upload a JavaScript project as it is, with no Dockerfile. Agent Lab detects the framework, builds it, and makes it a web page or an app.
What happens#
Zip the project with package.json at the top and upload it. The platform reads the project, makes a build plan and builds it:
- A project that only produces files for the browser becomes a web page, served from the CDN. A single-page app's routes, such as
/orders/42, all answer withindex.html. - A project that runs a server becomes a container app, built into an image that runs as a non-root user on port 8080.
You don't write a Dockerfile. If the project has one at the top, it is used instead of detection; see build settings to turn that off.
Leave these out of the zip
node_modules, .git, dist and .env. The platform installs dependencies itself and skips them if they are included anyway.
Supported frameworks#
| Becomes a web page | Becomes an app |
|---|---|
| Vite (React, Vue, Svelte), Create React App, Vue CLI | Next.js (also output: "export" becomes a web page) |
| Angular, static Astro, plain HTML with a build script | Nuxt, SvelteKit, Remix, React Router 7, Astro with SSR |
| Express, Fastify, Koa, Hono, NestJS, any Node server |
npm, pnpm, Yarn and Bun are detected from the lockfile or the packageManager field. Node.js comes from engines.node, .nvmrc or .node-version; otherwise the latest LTS (24) is used. 18, 20, 22 and 24 are available.
Environment variables#
The plan lists the variables the code reads — from .env.example, process.env.* and import.meta.env.* — and marks the ones that look like secrets or are needed at build time (such as VITE_* and NEXT_PUBLIC_*).
- Enter them before deploying: an app's in Settings › Runtime settings (secrets under Secrets), a web page's in Settings › Build variables. A version built from source lists the names the code reads that nothing sets yet.
- Variables are passed to the build too: a build-time name is baked into the web page, so never put a secret in a
VITE_orNEXT_PUBLIC_variable. - Secrets are available to the install and build steps as mounted values, for example a private registry token. They are never written into the image.
Build settings#
When detection guesses wrong, override it in Settings › Build settings. An empty field is detected.
| Setting | Example | Variable |
|---|---|---|
| Node.js version | 22 | ALPACK_NODE_VERSION |
| Install command | npm ci | ALPACK_INSTALL_CMD |
| Build command | npm run build:prod | ALPACK_BUILD_CMD |
| Start command | node dist/server.js | ALPACK_START_CMD |
| Output directory | dist/browser | ALPACK_OUTPUT_DIR |
| Ignore the repo's Dockerfile | on | ALPACK_IGNORE_DOCKERFILE |
| App path | apps/web | — |
A variable with that name, set in the branch's runtime settings, wins over the setting. ALPACK_* variables steer the build only and are never passed to the running app.
Setting a start command on a project detected as a web page makes it an app.
Monorepos#
For a repository with several projects, upload the whole repository and set App path in the build settings to the app's folder, such as apps/web. The platform plans and builds from that folder, so its own package.json and lockfile decide the build. Packages from elsewhere in the repository, such as workspace:* dependencies, are not available to it yet.
When the build fails#
| What you see | Fix |
|---|---|
| Can't tell how to build this source | Put package.json at the top of the zip, or set a start command. |
| The build produced nothing | Set the output directory to where the build writes its files. |
| An app's upload is only a web page | An app can't go back to being a web page. Create a new app for it, or set a start command. |
| A native module fails to compile | Commit the lockfile; the platform adds the compilers when it sees native dependencies. |
The build log on the version page shows each step. With an AI tool, ask for the build plan first; see MCP tools.