---
title: Deploy from source code
description: 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.
url: https://agentlab.cresclab.com/docs/en/deploy/source-build
language: en
updated: 2026-10-08
---

# 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 with `index.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](https://agentlab.cresclab.com/docs/en/deploy/source-build.md#build-settings) to turn that off.

> [!TIP] 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_*`).

1. 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.
2. 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_` or `NEXT_PUBLIC_` variable.
3. 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](https://agentlab.cresclab.com/docs/en/deploy/mcp-tools.md#sites).
