# Monorepos and custom build commands

> Deploy an app from a monorepo subfolder with a root directory, and override install and build commands with FALAK_INSTALL_COMMAND and FALAK_BUILD_COMMAND.

Source: https://falak.sh/docs/deploy/monorepos/

Falak detects how to install and build your app from its root directory: the repository root, or the subfolder you set. When the defaults are not what you need — a custom script, an unusual package manager flag — override them with two site variables.

## Root directory

Set **Root directory** (**Settings → Build & runtime**, or `root_directory` in the [API](/docs/api/sites/#fields)) to the repository subfolder the app lives in, for example `apps/api`. Empty means the repository root.

- Builds run there, and the release is that folder: deploy steps and hooks run in it.
- Docker builds use it as the build context, and resolve the `dockerfile` and the compose file from it.
- The path is relative, surrounding slashes are trimmed, and `.`/`..` segments are refused. A root directory that resolves outside the checkout (through a symlink, for example) fails the build.

Several Falak sites can use the same repository with different root directories, one per app. A [Compose service split into its own site](/docs/guides/compose-apps/#its-own-falak-site) gets its build context as its root directory.

## Override install and build

| Variable | Replaces | Runs |
|---|---|---|
| `FALAK_INSTALL_COMMAND` | The detected dependency install (`npm ci`, `composer install`, …) | `sh -c "<value>"` in the root directory on the builder |
| `FALAK_BUILD_COMMAND` | The detected build step (`npm run build`, …) | `sh -c "<value>"` |

Set them in the site's **Variables** like any other variable. They apply to **native** builds and take effect on the next deployment.

```dotenv title="Site variables"
FALAK_INSTALL_COMMAND=pnpm install --frozen-lockfile
FALAK_BUILD_COMMAND=pnpm run build:prod
```

## Monorepos

For an app that lives in its own folder, set the [root directory](#root-directory). When the app needs files outside its folder (shared workspace packages, a root lockfile), build from the repository root instead with these patterns:

### Node workspaces (pnpm, npm, yarn, bun)

Build the one app with a workspace filter, and give the root `package.json` a `start` script that starts it:

```dotenv title="Site variables"
FALAK_INSTALL_COMMAND=pnpm install --frozen-lockfile
FALAK_BUILD_COMMAND=pnpm --filter @acme/web... build
```

```json title="package.json (repository root)"
{
  "private": true,
  "packageManager": "pnpm@9.12.0",
  "scripts": {
    "start": "pnpm --filter @acme/web start"
  }
}
```

The web process runs `npm run start` in the release root, which calls your root script. Make sure the app listens on `PORT`.

### A static app inside a monorepo

Build it, then set the site's **web directory** (**Settings → Build**) to the app's output, for example `apps/docs/dist`. Caddy serves the document root `current/<web directory>`.

### A PHP app in a subdirectory

Falak's PHP detection needs `composer.json` in the app's root. For a Laravel app in `backend/`, set the root directory to `backend`.

Several Falak sites can point at the same repository, each with its own variables and build commands. Push-to-deploy then deploys all of them on every push to the branch.

## Seeing what Falak will do

Every build log starts with the detected plan (provider, versions, steps). Locally, with the `falak-builder` binary from a Falak release, print the plan for a directory:

```bash
falak-builder detect .
falak-builder detect --dockerfile .   # the Dockerfile Falak would generate for docker mode
falak-builder detect --runtime bun .  # hint: php, node, bun, deno or static
```

## Next steps
